@blumintinc/eslint-plugin-blumint 1.12.6 → 1.14.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 +171 -99
- package/lib/index.js +300 -17
- package/lib/rules/array-methods-this-context.js +20 -2
- package/lib/rules/avoid-utils-directory.js +11 -2
- package/lib/rules/class-methods-read-top-to-bottom.js +24 -5
- package/lib/rules/consistent-callback-naming.js +1 -1
- package/lib/rules/dynamic-https-errors.d.ts +3 -1
- package/lib/rules/dynamic-https-errors.js +48 -11
- package/lib/rules/enforce-assert-safe-object-key.d.ts +8 -0
- package/lib/rules/{enforce-assertSafe-object-key.js → enforce-assert-safe-object-key.js} +52 -96
- package/lib/rules/enforce-assert-throws.d.ts +3 -1
- package/lib/rules/enforce-assert-throws.js +493 -51
- package/lib/rules/enforce-boolean-naming-prefixes.d.ts +3 -1
- package/lib/rules/enforce-boolean-naming-prefixes.js +820 -39
- package/lib/rules/enforce-callable-types.js +4 -4
- package/lib/rules/enforce-callback-memo.js +143 -18
- package/lib/rules/enforce-centralized-mock-firestore.js +5 -2
- package/lib/rules/enforce-console-error.d.ts +3 -0
- package/lib/rules/enforce-console-error.js +278 -0
- package/lib/rules/enforce-css-media-queries.js +24 -46
- package/lib/rules/enforce-dynamic-file-naming.d.ts +2 -0
- package/lib/rules/enforce-dynamic-file-naming.js +53 -28
- package/lib/rules/enforce-dynamic-firebase-imports.js +100 -19
- package/lib/rules/enforce-dynamic-imports.js +1 -1
- package/lib/rules/enforce-early-destructuring.d.ts +2 -0
- package/lib/rules/enforce-early-destructuring.js +980 -0
- package/lib/rules/enforce-empty-object-check.d.ts +11 -0
- package/lib/rules/enforce-empty-object-check.js +502 -0
- package/lib/rules/enforce-exported-function-types.js +4 -4
- package/lib/rules/enforce-fieldpath-syntax-in-docsetter.d.ts +2 -0
- package/lib/rules/enforce-fieldpath-syntax-in-docsetter.js +262 -0
- package/lib/rules/enforce-firestore-doc-ref-generic.js +350 -3
- package/lib/rules/enforce-firestore-facade.js +349 -157
- package/lib/rules/enforce-firestore-rules-get-access.d.ts +3 -0
- package/lib/rules/enforce-firestore-rules-get-access.js +109 -0
- package/lib/rules/enforce-firestore-set-merge.js +3 -4
- package/lib/rules/enforce-global-constants.d.ts +4 -1
- package/lib/rules/enforce-global-constants.js +240 -12
- package/lib/rules/enforce-identifiable-firestore-type.js +108 -58
- package/lib/rules/enforce-memoize-async.d.ts +2 -1
- package/lib/rules/enforce-memoize-async.js +92 -27
- package/lib/rules/enforce-memoize-getters.d.ts +3 -0
- package/lib/rules/enforce-memoize-getters.js +147 -0
- package/lib/rules/enforce-microdiff.js +3 -2
- package/lib/rules/enforce-object-literal-as-const.js +4 -4
- package/lib/rules/enforce-positive-naming.js +9 -7
- package/lib/rules/enforce-props-argument-name.d.ts +2 -7
- package/lib/rules/enforce-props-argument-name.js +165 -151
- package/lib/rules/enforce-props-naming-consistency.d.ts +2 -0
- package/lib/rules/enforce-props-naming-consistency.js +145 -0
- package/lib/rules/enforce-querykey-ts.d.ts +9 -0
- package/lib/rules/enforce-querykey-ts.js +274 -0
- package/lib/rules/enforce-safe-stringify.js +1 -1
- package/lib/rules/enforce-serializable-params.js +3 -3
- package/lib/rules/enforce-singular-type-names.js +10 -6
- package/lib/rules/enforce-stable-hash-spread-props.d.ts +13 -0
- package/lib/rules/enforce-stable-hash-spread-props.js +342 -0
- package/lib/rules/enforce-storage-context.d.ts +9 -0
- package/lib/rules/enforce-storage-context.js +646 -0
- package/lib/rules/enforce-timestamp-now.js +23 -7
- package/lib/rules/enforce-transform-memoization.d.ts +4 -0
- package/lib/rules/enforce-transform-memoization.js +416 -0
- package/lib/rules/enforce-typescript-markdown-code-blocks.d.ts +1 -0
- package/lib/rules/enforce-typescript-markdown-code-blocks.js +100 -0
- package/lib/rules/enforce-unique-cursor-headers.d.ts +16 -0
- package/lib/rules/enforce-unique-cursor-headers.js +365 -0
- package/lib/rules/enforce-verb-noun-naming.js +90 -14
- package/lib/rules/ensure-pointer-events-none.js +28 -2
- package/lib/rules/export-if-in-doubt.js +27 -4
- package/lib/rules/extract-global-constants.js +92 -53
- package/lib/rules/fast-deep-equal-over-microdiff.d.ts +2 -1
- package/lib/rules/fast-deep-equal-over-microdiff.js +351 -83
- package/lib/rules/firestore-transaction-reads-before-writes.d.ts +1 -0
- package/lib/rules/firestore-transaction-reads-before-writes.js +277 -0
- package/lib/rules/flatten-push-calls.d.ts +2 -0
- package/lib/rules/flatten-push-calls.js +428 -0
- package/lib/rules/generic-starts-with-t.js +8 -2
- package/lib/rules/global-const-style.js +50 -19
- package/lib/rules/jsdoc-above-field.d.ts +11 -0
- package/lib/rules/jsdoc-above-field.js +208 -0
- package/lib/rules/key-only-outermost-element.js +21 -3
- package/lib/rules/logical-top-to-bottom-grouping.d.ts +5 -0
- package/lib/rules/logical-top-to-bottom-grouping.js +1258 -0
- package/lib/rules/memo-compare-deeply-complex-props.d.ts +3 -0
- package/lib/rules/memo-compare-deeply-complex-props.js +788 -0
- package/lib/rules/memo-nested-react-components.d.ts +8 -0
- package/lib/rules/memo-nested-react-components.js +410 -0
- package/lib/rules/memoize-root-level-hocs.d.ts +7 -0
- package/lib/rules/memoize-root-level-hocs.js +242 -0
- package/lib/rules/no-always-true-false-conditions.d.ts +2 -1
- package/lib/rules/no-always-true-false-conditions.js +68 -8
- package/lib/rules/no-array-length-in-deps.d.ts +12 -0
- package/lib/rules/no-array-length-in-deps.js +314 -0
- package/lib/rules/no-async-array-filter.js +5 -2
- package/lib/rules/no-async-foreach.js +210 -12
- package/lib/rules/no-circular-references.js +18 -17
- package/lib/rules/no-class-instance-destructuring.js +55 -12
- package/lib/rules/no-complex-cloud-params.js +22 -5
- package/lib/rules/no-compositing-layer-props.js +6 -4
- package/lib/rules/no-conditional-literals-in-jsx.js +37 -12
- package/lib/rules/no-console-error.d.ts +9 -0
- package/lib/rules/no-console-error.js +525 -0
- package/lib/rules/no-curly-brackets-around-commented-properties.d.ts +2 -0
- package/lib/rules/no-curly-brackets-around-commented-properties.js +258 -0
- package/lib/rules/no-empty-dependency-use-callbacks.d.ts +11 -0
- package/lib/rules/no-empty-dependency-use-callbacks.js +576 -0
- package/lib/rules/no-entire-object-hook-deps.d.ts +3 -1
- package/lib/rules/no-entire-object-hook-deps.js +320 -68
- package/lib/rules/no-excessive-parent-chain.d.ts +5 -0
- package/lib/rules/no-excessive-parent-chain.js +273 -0
- package/lib/rules/no-explicit-return-type.d.ts +2 -1
- package/lib/rules/no-explicit-return-type.js +215 -26
- package/lib/rules/no-filter-without-return.js +5 -1
- package/lib/rules/no-firestore-jest-mock.d.ts +2 -1
- package/lib/rules/no-firestore-jest-mock.js +126 -8
- package/lib/rules/no-firestore-object-arrays.js +398 -28
- package/lib/rules/no-handler-suffix.d.ts +12 -0
- package/lib/rules/no-handler-suffix.js +305 -0
- package/lib/rules/no-hungarian.js +14 -14
- package/lib/rules/no-inline-component-prop.d.ts +10 -0
- package/lib/rules/no-inline-component-prop.js +456 -0
- package/lib/rules/no-jsx-in-hooks.js +6 -1
- package/lib/rules/no-jsx-whitespace-literal.js +8 -2
- package/lib/rules/no-margin-properties.d.ts +7 -1
- package/lib/rules/no-margin-properties.js +22 -9
- package/lib/rules/no-memoize-on-static.js +9 -1
- package/lib/rules/no-misleading-boolean-prefixes.d.ts +7 -0
- package/lib/rules/no-misleading-boolean-prefixes.js +331 -0
- package/lib/rules/no-misused-switch-case.js +22 -1
- package/lib/rules/no-mixed-firestore-transactions.d.ts +3 -1
- package/lib/rules/no-mixed-firestore-transactions.js +296 -34
- package/lib/rules/no-mock-firebase-admin.js +5 -2
- package/lib/rules/no-object-values-on-strings.js +10 -2
- package/lib/rules/no-overridable-method-calls-in-constructor.d.ts +1 -0
- package/lib/rules/no-overridable-method-calls-in-constructor.js +272 -0
- package/lib/rules/no-passthrough-getters.d.ts +4 -0
- package/lib/rules/no-passthrough-getters.js +206 -0
- package/lib/rules/no-redundant-annotation-assertion.d.ts +2 -0
- package/lib/rules/no-redundant-annotation-assertion.js +402 -0
- package/lib/rules/no-redundant-param-types.js +16 -6
- package/lib/rules/no-redundant-this-params.d.ts +3 -0
- package/lib/rules/no-redundant-this-params.js +459 -0
- package/lib/rules/no-redundant-usecallback-wrapper.d.ts +8 -0
- package/lib/rules/no-redundant-usecallback-wrapper.js +328 -0
- package/lib/rules/no-res-error-status-in-onrequest.d.ts +4 -0
- package/lib/rules/no-res-error-status-in-onrequest.js +521 -0
- package/lib/rules/no-restricted-properties-fix.d.ts +12 -0
- package/lib/rules/no-restricted-properties-fix.js +173 -0
- package/lib/rules/no-separate-loading-state.d.ts +8 -0
- package/lib/rules/no-separate-loading-state.js +133 -0
- package/lib/rules/no-stale-state-across-await.d.ts +1 -0
- package/lib/rules/no-stale-state-across-await.js +185 -0
- package/lib/rules/no-static-constants-in-dynamic-files.d.ts +3 -0
- package/lib/rules/no-static-constants-in-dynamic-files.js +149 -0
- package/lib/rules/no-try-catch-already-exists-in-transaction.d.ts +1 -0
- package/lib/rules/no-try-catch-already-exists-in-transaction.js +342 -0
- package/lib/rules/no-type-assertion-returns.js +49 -49
- package/lib/rules/no-undefined-null-passthrough.js +217 -40
- package/lib/rules/no-unmemoized-memo-without-props.d.ts +8 -0
- package/lib/rules/no-unmemoized-memo-without-props.js +426 -0
- package/lib/rules/no-unnecessary-destructuring-rename.d.ts +2 -0
- package/lib/rules/no-unnecessary-destructuring-rename.js +347 -0
- package/lib/rules/no-unnecessary-destructuring.js +14 -4
- package/lib/rules/no-unnecessary-verb-suffix.js +2 -3
- package/lib/rules/no-unpinned-dependencies.js +36 -5
- package/lib/rules/no-unsafe-firestore-spread.js +8 -5
- package/lib/rules/no-unused-props.d.ts +5 -2
- package/lib/rules/no-unused-props.js +451 -112
- package/lib/rules/no-unused-usestate.js +6 -2
- package/lib/rules/no-useless-fragment.js +28 -2
- package/lib/rules/no-useless-usememo-primitives.d.ts +9 -0
- package/lib/rules/no-useless-usememo-primitives.js +393 -0
- package/lib/rules/no-usememo-for-pass-by-value.d.ts +13 -0
- package/lib/rules/no-usememo-for-pass-by-value.js +757 -0
- package/lib/rules/no-uuidv4-base62-as-key.js +18 -13
- package/lib/rules/omit-index-html.d.ts +2 -1
- package/lib/rules/omit-index-html.js +62 -7
- package/lib/rules/optimize-object-boolean-conditions.d.ts +1 -0
- package/lib/rules/optimize-object-boolean-conditions.js +236 -0
- package/lib/rules/parallelize-async-operations.d.ts +8 -0
- package/lib/rules/parallelize-async-operations.js +394 -0
- package/lib/rules/prefer-batch-operations.d.ts +1 -3
- package/lib/rules/prefer-batch-operations.js +228 -35
- package/lib/rules/prefer-block-comments-for-declarations.js +22 -7
- package/lib/rules/prefer-clone-deep.js +3 -3
- package/lib/rules/prefer-destructuring-no-class.d.ts +2 -1
- package/lib/rules/prefer-destructuring-no-class.js +244 -59
- package/lib/rules/prefer-docsetter-setall.d.ts +2 -0
- package/lib/rules/prefer-docsetter-setall.js +243 -0
- package/lib/rules/prefer-document-flattening.d.ts +4 -0
- package/lib/rules/prefer-document-flattening.js +239 -0
- package/lib/rules/prefer-field-paths-in-transforms.d.ts +7 -0
- package/lib/rules/prefer-field-paths-in-transforms.js +251 -0
- package/lib/rules/prefer-fragment-component.js +4 -4
- package/lib/rules/prefer-fragment-shorthand.js +2 -1
- package/lib/rules/prefer-getter-over-parameterless-method.d.ts +13 -0
- package/lib/rules/prefer-getter-over-parameterless-method.js +648 -0
- package/lib/rules/prefer-global-router-state-key.d.ts +7 -3
- package/lib/rules/prefer-global-router-state-key.js +305 -31
- package/lib/rules/prefer-memoized-props.d.ts +3 -0
- package/lib/rules/prefer-memoized-props.js +445 -0
- package/lib/rules/prefer-next-dynamic.d.ts +9 -0
- package/lib/rules/prefer-next-dynamic.js +357 -0
- package/lib/rules/prefer-nullish-coalescing-boolean-props.d.ts +1 -0
- package/lib/rules/prefer-nullish-coalescing-boolean-props.js +435 -0
- package/lib/rules/prefer-nullish-coalescing-override.d.ts +7 -0
- package/lib/rules/prefer-nullish-coalescing-override.js +188 -0
- package/lib/rules/prefer-params-over-parent-id.d.ts +5 -0
- package/lib/rules/prefer-params-over-parent-id.js +277 -0
- package/lib/rules/prefer-settings-object.js +23 -15
- package/lib/rules/prefer-type-alias-over-typeof-constant.d.ts +3 -0
- package/lib/rules/prefer-type-alias-over-typeof-constant.js +259 -0
- package/lib/rules/prefer-type-over-interface.js +7 -2
- package/lib/rules/prefer-url-tostring-over-tojson.d.ts +2 -0
- package/lib/rules/prefer-url-tostring-over-tojson.js +169 -0
- package/lib/rules/prefer-use-deep-compare-memo.d.ts +4 -0
- package/lib/rules/prefer-use-deep-compare-memo.js +431 -0
- package/lib/rules/prefer-usecallback-over-usememo-for-functions.js +25 -2
- package/lib/rules/prefer-usememo-over-useeffect-usestate.js +24 -5
- package/lib/rules/prefer-utility-function-over-private-static.js +34 -2
- package/lib/rules/prevent-children-clobber.d.ts +2 -0
- package/lib/rules/prevent-children-clobber.js +536 -0
- package/lib/rules/react-memoize-literals.d.ts +4 -0
- package/lib/rules/react-memoize-literals.js +495 -0
- package/lib/rules/react-usememo-should-be-component.d.ts +2 -1
- package/lib/rules/react-usememo-should-be-component.js +144 -78
- package/lib/rules/require-dynamic-firebase-imports.js +2 -1
- package/lib/rules/require-hooks-default-params.js +17 -16
- package/lib/rules/require-https-error-cause.d.ts +4 -0
- package/lib/rules/require-https-error-cause.js +136 -0
- package/lib/rules/require-https-error.js +43 -21
- package/lib/rules/require-image-optimized.js +2 -2
- package/lib/rules/require-memo.js +12 -2
- package/lib/rules/require-memoize-jsx-returners.d.ts +3 -0
- package/lib/rules/require-memoize-jsx-returners.js +485 -0
- package/lib/rules/require-usememo-object-literals.js +9 -4
- package/lib/rules/semantic-function-prefixes.js +38 -18
- package/lib/rules/sync-onwrite-name-func.js +5 -1
- package/lib/rules/test-file-location-enforcement.d.ts +1 -0
- package/lib/rules/test-file-location-enforcement.js +57 -0
- package/lib/rules/use-custom-link.js +6 -1
- package/lib/rules/use-custom-router.js +6 -1
- package/lib/rules/use-latest-callback.d.ts +3 -0
- package/lib/rules/use-latest-callback.js +271 -0
- package/lib/rules/vertically-group-related-functions.d.ts +16 -0
- package/lib/rules/vertically-group-related-functions.js +480 -0
- package/lib/utils/ASTHelpers.d.ts +13 -1
- package/lib/utils/ASTHelpers.js +34 -0
- package/lib/utils/createRule.js +1 -1
- package/lib/utils/getMethodName.d.ts +27 -0
- package/lib/utils/getMethodName.js +35 -0
- package/lib/utils/graph/ClassGraphSorterReadability.js +1 -1
- package/lib/utils/ruleTester.d.ts +1 -0
- package/lib/utils/ruleTester.js +4 -1
- package/lib/utils/tsTypeClassifier.d.ts +30 -0
- package/lib/utils/tsTypeClassifier.js +149 -0
- package/package.json +23 -14
- package/lib/rules/enforce-assertSafe-object-key.d.ts +0 -2
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noTryCatchAlreadyExistsInTransaction = void 0;
|
|
4
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
5
|
+
const createRule_1 = require("../utils/createRule");
|
|
6
|
+
const ALREADY_EXISTS_STRINGS = new Set(['already-exists', 'ALREADY_EXISTS']);
|
|
7
|
+
const ALREADY_EXISTS_NUMBERS = new Set([6, '6']);
|
|
8
|
+
function unwrapChainExpression(expression) {
|
|
9
|
+
if (expression.type === utils_1.AST_NODE_TYPES.ChainExpression) {
|
|
10
|
+
return expression.expression;
|
|
11
|
+
}
|
|
12
|
+
return expression;
|
|
13
|
+
}
|
|
14
|
+
function isRunTransactionCall(node) {
|
|
15
|
+
const callee = unwrapChainExpression(node.callee);
|
|
16
|
+
if (callee.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
17
|
+
return callee.name === 'runTransaction';
|
|
18
|
+
}
|
|
19
|
+
if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression) {
|
|
20
|
+
const property = callee.property;
|
|
21
|
+
return (!callee.computed &&
|
|
22
|
+
property.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
23
|
+
property.name === 'runTransaction');
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
function getCallbackArgument(args) {
|
|
28
|
+
for (const arg of args) {
|
|
29
|
+
if (arg.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
30
|
+
arg.type === utils_1.AST_NODE_TYPES.FunctionExpression) {
|
|
31
|
+
return arg;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function isErrorAliasExpression(expression, context) {
|
|
37
|
+
if (expression.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
38
|
+
return context.errorAliases.has(expression.name);
|
|
39
|
+
}
|
|
40
|
+
if (expression.type === utils_1.AST_NODE_TYPES.TSAsExpression ||
|
|
41
|
+
expression.type === utils_1.AST_NODE_TYPES.TSTypeAssertion) {
|
|
42
|
+
return isErrorAliasExpression(expression.expression, context);
|
|
43
|
+
}
|
|
44
|
+
if (expression.type === utils_1.AST_NODE_TYPES.MemberExpression) {
|
|
45
|
+
return isErrorAliasExpression(expression.object, context);
|
|
46
|
+
}
|
|
47
|
+
if (expression.type === utils_1.AST_NODE_TYPES.ChainExpression) {
|
|
48
|
+
return isErrorAliasExpression(expression.expression, context);
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
function isCodeProperty(property) {
|
|
53
|
+
if (property.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
54
|
+
return property.name === 'code';
|
|
55
|
+
}
|
|
56
|
+
if (property.type === utils_1.AST_NODE_TYPES.Literal) {
|
|
57
|
+
return property.value === 'code';
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
function isErrorCodeExpression(expression, context) {
|
|
62
|
+
if (!expression) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (expression.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
66
|
+
return context.codeAliases.has(expression.name);
|
|
67
|
+
}
|
|
68
|
+
const unwrapped = expression.type === utils_1.AST_NODE_TYPES.ChainExpression
|
|
69
|
+
? expression.expression
|
|
70
|
+
: expression;
|
|
71
|
+
if (unwrapped.type === utils_1.AST_NODE_TYPES.MemberExpression) {
|
|
72
|
+
return (isCodeProperty(unwrapped.property) &&
|
|
73
|
+
isErrorAliasExpression(unwrapped.object, context));
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
function isAlreadyExistsLiteral(expression) {
|
|
78
|
+
if (!expression) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
if (expression.type === utils_1.AST_NODE_TYPES.PrivateIdentifier) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
if (expression.type === utils_1.AST_NODE_TYPES.Literal) {
|
|
85
|
+
if (ALREADY_EXISTS_STRINGS.has(`${expression.value}`)) {
|
|
86
|
+
return `${expression.value}`;
|
|
87
|
+
}
|
|
88
|
+
if (ALREADY_EXISTS_NUMBERS.has(expression.value)) {
|
|
89
|
+
return `${expression.value}`;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (expression.type === utils_1.AST_NODE_TYPES.TemplateLiteral &&
|
|
93
|
+
expression.expressions.length === 0 &&
|
|
94
|
+
expression.quasis.length === 1) {
|
|
95
|
+
const raw = expression.quasis[0].value.cooked;
|
|
96
|
+
if (raw && ALREADY_EXISTS_STRINGS.has(raw)) {
|
|
97
|
+
return raw;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
function isAlreadyExistsComparison(expression, context) {
|
|
103
|
+
if (expression.type !== utils_1.AST_NODE_TYPES.BinaryExpression) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
if (!['==', '==='].includes(expression.operator)) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const leftLiteral = isAlreadyExistsLiteral(expression.left);
|
|
110
|
+
const rightLiteral = isAlreadyExistsLiteral(expression.right);
|
|
111
|
+
if (leftLiteral && isErrorCodeExpression(expression.right, context)) {
|
|
112
|
+
return leftLiteral;
|
|
113
|
+
}
|
|
114
|
+
if (rightLiteral && isErrorCodeExpression(expression.left, context)) {
|
|
115
|
+
return rightLiteral;
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
function addAliasesFromDeclarator(declarator, context) {
|
|
120
|
+
const init = declarator.init;
|
|
121
|
+
const id = declarator.id;
|
|
122
|
+
const initIsAliasSource = !!init &&
|
|
123
|
+
(isErrorAliasExpression(init, context) ||
|
|
124
|
+
(init.type === utils_1.AST_NODE_TYPES.AssignmentExpression &&
|
|
125
|
+
isErrorAliasExpression(init.right, context)));
|
|
126
|
+
if (id.type === utils_1.AST_NODE_TYPES.Identifier && initIsAliasSource) {
|
|
127
|
+
context.errorAliases.add(id.name);
|
|
128
|
+
}
|
|
129
|
+
if (id.type === utils_1.AST_NODE_TYPES.ObjectPattern && initIsAliasSource) {
|
|
130
|
+
for (const property of id.properties) {
|
|
131
|
+
if (property.type !== utils_1.AST_NODE_TYPES.Property) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const value = property.value;
|
|
135
|
+
if (isCodeProperty(property.key) &&
|
|
136
|
+
value.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
137
|
+
context.codeAliases.add(value.name);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function containsAlreadyExistsCheck(node, context) {
|
|
143
|
+
if (!node) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
switch (node.type) {
|
|
147
|
+
case utils_1.AST_NODE_TYPES.BlockStatement: {
|
|
148
|
+
for (const statement of node.body) {
|
|
149
|
+
const found = containsAlreadyExistsCheck(statement, context);
|
|
150
|
+
if (found)
|
|
151
|
+
return found;
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
case utils_1.AST_NODE_TYPES.ExpressionStatement:
|
|
156
|
+
return containsAlreadyExistsCheck(node.expression, context);
|
|
157
|
+
case utils_1.AST_NODE_TYPES.ReturnStatement:
|
|
158
|
+
return containsAlreadyExistsCheck(node.argument, context);
|
|
159
|
+
case utils_1.AST_NODE_TYPES.IfStatement: {
|
|
160
|
+
const testMatch = containsAlreadyExistsCheck(node.test, context);
|
|
161
|
+
if (testMatch)
|
|
162
|
+
return testMatch;
|
|
163
|
+
const consequentMatch = containsAlreadyExistsCheck(node.consequent, context);
|
|
164
|
+
if (consequentMatch)
|
|
165
|
+
return consequentMatch;
|
|
166
|
+
return containsAlreadyExistsCheck(node.alternate, context);
|
|
167
|
+
}
|
|
168
|
+
case utils_1.AST_NODE_TYPES.SwitchStatement: {
|
|
169
|
+
const discriminantIsCode = isErrorCodeExpression(node.discriminant, context);
|
|
170
|
+
for (const switchCase of node.cases) {
|
|
171
|
+
const caseLiteral = isAlreadyExistsLiteral(switchCase.test);
|
|
172
|
+
if (discriminantIsCode && caseLiteral) {
|
|
173
|
+
return caseLiteral;
|
|
174
|
+
}
|
|
175
|
+
const found = switchCase.consequent
|
|
176
|
+
.map((stmt) => containsAlreadyExistsCheck(stmt, context))
|
|
177
|
+
.find(Boolean);
|
|
178
|
+
if (found)
|
|
179
|
+
return found;
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
case utils_1.AST_NODE_TYPES.VariableDeclaration: {
|
|
184
|
+
for (const declarator of node.declarations) {
|
|
185
|
+
addAliasesFromDeclarator(declarator, context);
|
|
186
|
+
const found = containsAlreadyExistsCheck(declarator.init, context);
|
|
187
|
+
if (found)
|
|
188
|
+
return found;
|
|
189
|
+
}
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
case utils_1.AST_NODE_TYPES.VariableDeclarator:
|
|
193
|
+
addAliasesFromDeclarator(node, context);
|
|
194
|
+
return containsAlreadyExistsCheck(node.init, context);
|
|
195
|
+
case utils_1.AST_NODE_TYPES.AssignmentExpression:
|
|
196
|
+
if (node.left.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
197
|
+
isErrorAliasExpression(node.right, context)) {
|
|
198
|
+
context.errorAliases.add(node.left.name);
|
|
199
|
+
}
|
|
200
|
+
return containsAlreadyExistsCheck(node.right, context);
|
|
201
|
+
case utils_1.AST_NODE_TYPES.CallExpression:
|
|
202
|
+
case utils_1.AST_NODE_TYPES.NewExpression: {
|
|
203
|
+
const calleeMatch = containsAlreadyExistsCheck(node.callee, context);
|
|
204
|
+
if (calleeMatch)
|
|
205
|
+
return calleeMatch;
|
|
206
|
+
for (const arg of node.arguments) {
|
|
207
|
+
const found = containsAlreadyExistsCheck(arg, context);
|
|
208
|
+
if (found)
|
|
209
|
+
return found;
|
|
210
|
+
}
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
case utils_1.AST_NODE_TYPES.LogicalExpression: {
|
|
214
|
+
const leftMatch = containsAlreadyExistsCheck(node.left, context);
|
|
215
|
+
if (leftMatch)
|
|
216
|
+
return leftMatch;
|
|
217
|
+
return containsAlreadyExistsCheck(node.right, context);
|
|
218
|
+
}
|
|
219
|
+
case utils_1.AST_NODE_TYPES.BinaryExpression:
|
|
220
|
+
return (isAlreadyExistsComparison(node, context) ||
|
|
221
|
+
containsAlreadyExistsCheck(node.left, context) ||
|
|
222
|
+
containsAlreadyExistsCheck(node.right, context));
|
|
223
|
+
case utils_1.AST_NODE_TYPES.ConditionalExpression: {
|
|
224
|
+
const testMatch = containsAlreadyExistsCheck(node.test, context);
|
|
225
|
+
if (testMatch)
|
|
226
|
+
return testMatch;
|
|
227
|
+
const consequentMatch = containsAlreadyExistsCheck(node.consequent, context);
|
|
228
|
+
if (consequentMatch)
|
|
229
|
+
return consequentMatch;
|
|
230
|
+
return containsAlreadyExistsCheck(node.alternate, context);
|
|
231
|
+
}
|
|
232
|
+
case utils_1.AST_NODE_TYPES.MemberExpression:
|
|
233
|
+
return containsAlreadyExistsCheck(node.object, context);
|
|
234
|
+
case utils_1.AST_NODE_TYPES.ChainExpression:
|
|
235
|
+
return containsAlreadyExistsCheck(node.expression, context);
|
|
236
|
+
case utils_1.AST_NODE_TYPES.AwaitExpression:
|
|
237
|
+
case utils_1.AST_NODE_TYPES.UnaryExpression:
|
|
238
|
+
case utils_1.AST_NODE_TYPES.UpdateExpression:
|
|
239
|
+
return containsAlreadyExistsCheck(node.argument, context);
|
|
240
|
+
case utils_1.AST_NODE_TYPES.TemplateLiteral:
|
|
241
|
+
return null;
|
|
242
|
+
case utils_1.AST_NODE_TYPES.TryStatement: {
|
|
243
|
+
const blockMatch = containsAlreadyExistsCheck(node.block, context);
|
|
244
|
+
if (blockMatch)
|
|
245
|
+
return blockMatch;
|
|
246
|
+
const handlerMatch = containsAlreadyExistsCheck(node.handler?.body, context);
|
|
247
|
+
if (handlerMatch)
|
|
248
|
+
return handlerMatch;
|
|
249
|
+
return containsAlreadyExistsCheck(node.finalizer, context);
|
|
250
|
+
}
|
|
251
|
+
default:
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function createCatchContext(handler) {
|
|
256
|
+
const errorAliases = new Set();
|
|
257
|
+
const codeAliases = new Set();
|
|
258
|
+
const param = handler.param;
|
|
259
|
+
if (param?.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
260
|
+
errorAliases.add(param.name);
|
|
261
|
+
}
|
|
262
|
+
else if (param?.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
|
|
263
|
+
for (const property of param.properties) {
|
|
264
|
+
if (property.type !== utils_1.AST_NODE_TYPES.Property) {
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const value = property.value;
|
|
268
|
+
if (isCodeProperty(property.key) &&
|
|
269
|
+
value.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
270
|
+
codeAliases.add(value.name);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return { errorAliases, codeAliases };
|
|
275
|
+
}
|
|
276
|
+
exports.noTryCatchAlreadyExistsInTransaction = (0, createRule_1.createRule)({
|
|
277
|
+
name: 'no-try-catch-already-exists-in-transaction',
|
|
278
|
+
meta: {
|
|
279
|
+
type: 'problem',
|
|
280
|
+
docs: {
|
|
281
|
+
description: 'Disallow catching ALREADY_EXISTS errors inside Firestore transaction callbacks',
|
|
282
|
+
recommended: 'error',
|
|
283
|
+
},
|
|
284
|
+
schema: [],
|
|
285
|
+
messages: {
|
|
286
|
+
noAlreadyExistsCatchInTransaction: 'Do not catch ALREADY_EXISTS ({{codeLiteral}}) inside Firestore transaction callbacks. Firestore retries transaction bodies on contention, so this catch will re-run even though ALREADY_EXISTS is permanent. Move the try/catch outside the transaction or use runCreateForgivenessTransaction so the handler runs once.',
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
defaultOptions: [],
|
|
290
|
+
create(context) {
|
|
291
|
+
const transactionBodies = new Set();
|
|
292
|
+
function isInsideTransaction(node) {
|
|
293
|
+
let current = node;
|
|
294
|
+
while (current) {
|
|
295
|
+
if (transactionBodies.has(current)) {
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
current = current.parent;
|
|
299
|
+
}
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
return {
|
|
303
|
+
CallExpression(node) {
|
|
304
|
+
if (!isRunTransactionCall(node)) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const callback = getCallbackArgument(node.arguments);
|
|
308
|
+
if (callback && callback.body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
309
|
+
transactionBodies.add(callback.body);
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
'CallExpression:exit'(node) {
|
|
313
|
+
if (!isRunTransactionCall(node)) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const callback = getCallbackArgument(node.arguments);
|
|
317
|
+
if (callback && callback.body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
318
|
+
transactionBodies.delete(callback.body);
|
|
319
|
+
}
|
|
320
|
+
},
|
|
321
|
+
TryStatement(node) {
|
|
322
|
+
if (!isInsideTransaction(node)) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const handler = node.handler;
|
|
326
|
+
if (!handler) {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
const catchContext = createCatchContext(handler);
|
|
330
|
+
const match = containsAlreadyExistsCheck(handler.body, catchContext);
|
|
331
|
+
if (match) {
|
|
332
|
+
context.report({
|
|
333
|
+
node: handler,
|
|
334
|
+
messageId: 'noAlreadyExistsCatchInTransaction',
|
|
335
|
+
data: { codeLiteral: match },
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
//# sourceMappingURL=no-try-catch-already-exists-in-transaction.js.map
|
|
@@ -28,6 +28,12 @@ function isTypePredicate(node) {
|
|
|
28
28
|
function isInsideReturnStatement(node) {
|
|
29
29
|
let current = node;
|
|
30
30
|
while (current?.parent) {
|
|
31
|
+
// If we encounter a variable declaration before a return statement,
|
|
32
|
+
// then the node is not directly inside a return statement
|
|
33
|
+
if (current.parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator ||
|
|
34
|
+
current.parent.type === utils_1.AST_NODE_TYPES.VariableDeclaration) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
31
37
|
if (current.parent.type === utils_1.AST_NODE_TYPES.ReturnStatement) {
|
|
32
38
|
return true;
|
|
33
39
|
}
|
|
@@ -91,13 +97,40 @@ exports.noTypeAssertionReturns = (0, createRule_1.createRule)({
|
|
|
91
97
|
},
|
|
92
98
|
],
|
|
93
99
|
messages: {
|
|
94
|
-
noTypeAssertionReturns: '
|
|
95
|
-
|
|
100
|
+
noTypeAssertionReturns: `What's wrong: Return value uses a type assertion to "{{assertedType}}", which bypasses TypeScript checks. ` +
|
|
101
|
+
`→ Why it matters: Casts can hide missing or invalid data and let unsafe values reach callers without compile-time errors. ` +
|
|
102
|
+
`→ How to fix: Create a typed variable or add a narrowing step before returning so the value is validated by the type system instead of forced with a cast.`,
|
|
103
|
+
useExplicitVariable: `What's wrong: Return type "{{returnType}}" is declared while returning an unchecked expression, so TypeScript trusts the annotation instead of validating the actual value. ` +
|
|
104
|
+
`→ Why it matters: This hides mismatches between implementation and contract, letting incorrect return values propagate without type errors. ` +
|
|
105
|
+
`→ How to fix: Assign the expression to a typed variable or narrow it first, then return that variable so TypeScript can verify it against the declared return type.`,
|
|
96
106
|
},
|
|
97
107
|
},
|
|
98
108
|
defaultOptions: [defaultOptions],
|
|
99
109
|
create(context, [options]) {
|
|
100
110
|
const mergedOptions = { ...defaultOptions, ...options };
|
|
111
|
+
const sourceCode = context.getSourceCode();
|
|
112
|
+
function getTypeText(typeNode, fallback) {
|
|
113
|
+
const text = typeNode ? sourceCode.getText(typeNode).trim() : '';
|
|
114
|
+
return text || fallback;
|
|
115
|
+
}
|
|
116
|
+
function reportTypeAssertion(node) {
|
|
117
|
+
context.report({
|
|
118
|
+
node,
|
|
119
|
+
messageId: 'noTypeAssertionReturns',
|
|
120
|
+
data: {
|
|
121
|
+
assertedType: getTypeText(node.typeAnnotation, 'the asserted type'),
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function reportReturnTypeAnnotation(typeAnnotation) {
|
|
126
|
+
context.report({
|
|
127
|
+
node: typeAnnotation,
|
|
128
|
+
messageId: 'useExplicitVariable',
|
|
129
|
+
data: {
|
|
130
|
+
returnType: getTypeText(typeAnnotation.typeAnnotation, 'the declared return type'),
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
}
|
|
101
134
|
/**
|
|
102
135
|
* Checks if a node is inside a JSX attribute or object property (which could be JSX props)
|
|
103
136
|
*/
|
|
@@ -196,7 +229,7 @@ exports.noTypeAssertionReturns = (0, createRule_1.createRule)({
|
|
|
196
229
|
/**
|
|
197
230
|
* Check if the current file is a .f.ts file
|
|
198
231
|
*/
|
|
199
|
-
function isFunctionFile(
|
|
232
|
+
function isFunctionFile() {
|
|
200
233
|
const filename = context.getFilename();
|
|
201
234
|
return filename.endsWith('.f.ts');
|
|
202
235
|
}
|
|
@@ -207,7 +240,7 @@ exports.noTypeAssertionReturns = (0, createRule_1.createRule)({
|
|
|
207
240
|
if (!node.returnType)
|
|
208
241
|
return;
|
|
209
242
|
// Skip checking return types in .f.ts files
|
|
210
|
-
if (isFunctionFile(
|
|
243
|
+
if (isFunctionFile()) {
|
|
211
244
|
return;
|
|
212
245
|
}
|
|
213
246
|
// Allow type predicates if configured
|
|
@@ -218,10 +251,7 @@ exports.noTypeAssertionReturns = (0, createRule_1.createRule)({
|
|
|
218
251
|
// If type predicates are not allowed, report them
|
|
219
252
|
if (!mergedOptions.allowTypePredicates &&
|
|
220
253
|
isTypePredicate(node.returnType)) {
|
|
221
|
-
|
|
222
|
-
node: node.returnType,
|
|
223
|
-
messageId: 'useExplicitVariable',
|
|
224
|
-
});
|
|
254
|
+
reportReturnTypeAnnotation(node.returnType);
|
|
225
255
|
return;
|
|
226
256
|
}
|
|
227
257
|
// Check if the function has a return statement with a direct value (not a variable)
|
|
@@ -238,10 +268,7 @@ exports.noTypeAssertionReturns = (0, createRule_1.createRule)({
|
|
|
238
268
|
if (statement.argument.type === utils_1.AST_NODE_TYPES.ObjectExpression ||
|
|
239
269
|
statement.argument.type === utils_1.AST_NODE_TYPES.ArrayExpression ||
|
|
240
270
|
statement.argument.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
241
|
-
|
|
242
|
-
node: node.returnType,
|
|
243
|
-
messageId: 'useExplicitVariable',
|
|
244
|
-
});
|
|
271
|
+
reportReturnTypeAnnotation(node.returnType);
|
|
245
272
|
break;
|
|
246
273
|
}
|
|
247
274
|
}
|
|
@@ -261,23 +288,14 @@ exports.noTypeAssertionReturns = (0, createRule_1.createRule)({
|
|
|
261
288
|
}
|
|
262
289
|
// For nested type assertions, only report the outermost one
|
|
263
290
|
if (node.argument.expression.type === utils_1.AST_NODE_TYPES.TSAsExpression) {
|
|
264
|
-
|
|
265
|
-
node: node.argument,
|
|
266
|
-
messageId: 'noTypeAssertionReturns',
|
|
267
|
-
});
|
|
291
|
+
reportTypeAssertion(node.argument);
|
|
268
292
|
return;
|
|
269
293
|
}
|
|
270
|
-
|
|
271
|
-
node: node.argument,
|
|
272
|
-
messageId: 'noTypeAssertionReturns',
|
|
273
|
-
});
|
|
294
|
+
reportTypeAssertion(node.argument);
|
|
274
295
|
}
|
|
275
296
|
// Check for type assertions using angle bracket syntax
|
|
276
297
|
if (node.argument.type === utils_1.AST_NODE_TYPES.TSTypeAssertion) {
|
|
277
|
-
|
|
278
|
-
node: node.argument,
|
|
279
|
-
messageId: 'noTypeAssertionReturns',
|
|
280
|
-
});
|
|
298
|
+
reportTypeAssertion(node.argument);
|
|
281
299
|
}
|
|
282
300
|
},
|
|
283
301
|
// Check functions with explicit return types
|
|
@@ -295,7 +313,7 @@ exports.noTypeAssertionReturns = (0, createRule_1.createRule)({
|
|
|
295
313
|
// Check for explicit return type
|
|
296
314
|
if (node.returnType) {
|
|
297
315
|
// Skip checking return types in .f.ts files
|
|
298
|
-
if (isFunctionFile(
|
|
316
|
+
if (isFunctionFile()) {
|
|
299
317
|
return;
|
|
300
318
|
}
|
|
301
319
|
// Allow type predicates if configured
|
|
@@ -306,19 +324,13 @@ exports.noTypeAssertionReturns = (0, createRule_1.createRule)({
|
|
|
306
324
|
// If type predicates are not allowed, report them
|
|
307
325
|
if (!mergedOptions.allowTypePredicates &&
|
|
308
326
|
isTypePredicate(node.returnType)) {
|
|
309
|
-
|
|
310
|
-
node: node.returnType,
|
|
311
|
-
messageId: 'useExplicitVariable',
|
|
312
|
-
});
|
|
327
|
+
reportReturnTypeAnnotation(node.returnType);
|
|
313
328
|
return;
|
|
314
329
|
}
|
|
315
330
|
// If returning an object literal with explicit return type, report it
|
|
316
331
|
if (node.body.type === utils_1.AST_NODE_TYPES.ObjectExpression ||
|
|
317
332
|
node.body.type === utils_1.AST_NODE_TYPES.ArrayExpression) {
|
|
318
|
-
|
|
319
|
-
node: node.returnType,
|
|
320
|
-
messageId: 'useExplicitVariable',
|
|
321
|
-
});
|
|
333
|
+
reportReturnTypeAnnotation(node.returnType);
|
|
322
334
|
}
|
|
323
335
|
}
|
|
324
336
|
// Check for type assertions in the body
|
|
@@ -327,16 +339,10 @@ exports.noTypeAssertionReturns = (0, createRule_1.createRule)({
|
|
|
327
339
|
if (mergedOptions.allowAsConst && isAsConstAssertion(node.body)) {
|
|
328
340
|
return;
|
|
329
341
|
}
|
|
330
|
-
|
|
331
|
-
node: node.body,
|
|
332
|
-
messageId: 'noTypeAssertionReturns',
|
|
333
|
-
});
|
|
342
|
+
reportTypeAssertion(node.body);
|
|
334
343
|
}
|
|
335
344
|
else if (node.body.type === utils_1.AST_NODE_TYPES.TSTypeAssertion) {
|
|
336
|
-
|
|
337
|
-
node: node.body,
|
|
338
|
-
messageId: 'noTypeAssertionReturns',
|
|
339
|
-
});
|
|
345
|
+
reportTypeAssertion(node.body);
|
|
340
346
|
}
|
|
341
347
|
}
|
|
342
348
|
else if (node.returnType) {
|
|
@@ -359,10 +365,7 @@ exports.noTypeAssertionReturns = (0, createRule_1.createRule)({
|
|
|
359
365
|
return;
|
|
360
366
|
}
|
|
361
367
|
// For standalone type assertions in expressions
|
|
362
|
-
|
|
363
|
-
node,
|
|
364
|
-
messageId: 'noTypeAssertionReturns',
|
|
365
|
-
});
|
|
368
|
+
reportTypeAssertion(node);
|
|
366
369
|
},
|
|
367
370
|
// Check for type assertions using angle bracket syntax
|
|
368
371
|
TSTypeAssertion(node) {
|
|
@@ -371,10 +374,7 @@ exports.noTypeAssertionReturns = (0, createRule_1.createRule)({
|
|
|
371
374
|
return;
|
|
372
375
|
}
|
|
373
376
|
// For standalone type assertions in expressions
|
|
374
|
-
|
|
375
|
-
node,
|
|
376
|
-
messageId: 'noTypeAssertionReturns',
|
|
377
|
-
});
|
|
377
|
+
reportTypeAssertion(node);
|
|
378
378
|
},
|
|
379
379
|
};
|
|
380
380
|
},
|