@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
|
@@ -3,21 +3,196 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.enforceAssertThrows = void 0;
|
|
4
4
|
const utils_1 = require("@typescript-eslint/utils");
|
|
5
5
|
const createRule_1 = require("../utils/createRule");
|
|
6
|
+
function isCallbackFunctionNode(node) {
|
|
7
|
+
if (node.type !== utils_1.AST_NODE_TYPES.FunctionExpression &&
|
|
8
|
+
node.type !== utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
const parent = node.parent;
|
|
12
|
+
if (!parent)
|
|
13
|
+
return false;
|
|
14
|
+
if (parent.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
15
|
+
const grandParent = parent.parent;
|
|
16
|
+
if (grandParent &&
|
|
17
|
+
(grandParent.type === utils_1.AST_NODE_TYPES.ConditionalExpression ||
|
|
18
|
+
grandParent.type === utils_1.AST_NODE_TYPES.LogicalExpression)) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
return parent.arguments.includes(node) || parent.callee === node;
|
|
22
|
+
}
|
|
23
|
+
if (parent.type === utils_1.AST_NODE_TYPES.ConditionalExpression ||
|
|
24
|
+
parent.type === utils_1.AST_NODE_TYPES.LogicalExpression) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
function isTypeLikeNode(node) {
|
|
30
|
+
return node.type.startsWith('TS') || node.type.endsWith('TypeAnnotation');
|
|
31
|
+
}
|
|
6
32
|
exports.enforceAssertThrows = (0, createRule_1.createRule)({
|
|
7
33
|
name: 'enforce-assert-throws',
|
|
8
34
|
meta: {
|
|
9
35
|
type: 'problem',
|
|
10
36
|
docs: {
|
|
11
|
-
description: 'Enforce that functions with assert
|
|
37
|
+
description: 'Enforce that functions with an assert prefix must throw an error or call process.exit(1), and functions that call assert-prefixed methods should themselves be assert-prefixed',
|
|
12
38
|
recommended: 'error',
|
|
13
39
|
},
|
|
14
40
|
schema: [],
|
|
15
41
|
messages: {
|
|
16
|
-
assertShouldThrow: '
|
|
42
|
+
assertShouldThrow: 'Assert helper "{{functionName}}" does not throw, exit, or delegate to another assert helper. Assert-prefixed functions are fail-fast guards; letting them return normally hides failed checks and allows callers to continue with invalid state. Throw an error, call process.exit(1), or rename the function if it should not halt execution.',
|
|
43
|
+
shouldBeAssertPrefixed: 'Function "{{functionName}}" calls an assert-prefixed helper but is not assert-prefixed itself. The assert- prefix signals that the function terminates on failed checks; without it, callers may assume it returns safely and keep running after an assertion aborts. Rename the function to start with "assert" or avoid calling assert helpers from non-assert functions.',
|
|
17
44
|
},
|
|
18
45
|
},
|
|
19
46
|
defaultOptions: [],
|
|
20
47
|
create(context) {
|
|
48
|
+
function callsAssertMethod(node) {
|
|
49
|
+
let hasAssertCall = false;
|
|
50
|
+
function walk(node) {
|
|
51
|
+
if (hasAssertCall)
|
|
52
|
+
return; // Early exit if we found an assert call
|
|
53
|
+
if (isTypeLikeNode(node))
|
|
54
|
+
return;
|
|
55
|
+
if (node.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
56
|
+
const callee = node.callee;
|
|
57
|
+
if (callee.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
58
|
+
if (callee.name.toLowerCase().startsWith('assert')) {
|
|
59
|
+
hasAssertCall = true;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression) {
|
|
64
|
+
const property = callee.property;
|
|
65
|
+
if (property.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
66
|
+
if (property.name.toLowerCase().startsWith('assert')) {
|
|
67
|
+
hasAssertCall = true;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Handle nested functions - only skip if it's a standalone function, not a callback
|
|
74
|
+
if (node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration ||
|
|
75
|
+
node.type === utils_1.AST_NODE_TYPES.FunctionExpression ||
|
|
76
|
+
node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
77
|
+
if (node !== currentFunction) {
|
|
78
|
+
// Allow traversing into callback functions
|
|
79
|
+
if (!isCallbackFunctionNode(node)) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Handle specific node types that contain other nodes
|
|
85
|
+
switch (node.type) {
|
|
86
|
+
case utils_1.AST_NODE_TYPES.BlockStatement:
|
|
87
|
+
node.body.forEach((stmt) => walk(stmt));
|
|
88
|
+
break;
|
|
89
|
+
case utils_1.AST_NODE_TYPES.IfStatement:
|
|
90
|
+
walk(node.consequent);
|
|
91
|
+
if (node.alternate) {
|
|
92
|
+
walk(node.alternate);
|
|
93
|
+
}
|
|
94
|
+
break;
|
|
95
|
+
case utils_1.AST_NODE_TYPES.ConditionalExpression:
|
|
96
|
+
walk(node.consequent);
|
|
97
|
+
walk(node.alternate);
|
|
98
|
+
break;
|
|
99
|
+
case utils_1.AST_NODE_TYPES.LogicalExpression:
|
|
100
|
+
walk(node.left);
|
|
101
|
+
walk(node.right);
|
|
102
|
+
break;
|
|
103
|
+
case utils_1.AST_NODE_TYPES.ExpressionStatement:
|
|
104
|
+
walk(node.expression);
|
|
105
|
+
break;
|
|
106
|
+
case utils_1.AST_NODE_TYPES.ReturnStatement:
|
|
107
|
+
if (node.argument) {
|
|
108
|
+
walk(node.argument);
|
|
109
|
+
}
|
|
110
|
+
break;
|
|
111
|
+
case utils_1.AST_NODE_TYPES.AwaitExpression:
|
|
112
|
+
walk(node.argument);
|
|
113
|
+
break;
|
|
114
|
+
case utils_1.AST_NODE_TYPES.VariableDeclaration:
|
|
115
|
+
node.declarations.forEach((decl) => walk(decl));
|
|
116
|
+
break;
|
|
117
|
+
case utils_1.AST_NODE_TYPES.VariableDeclarator:
|
|
118
|
+
if (node.init) {
|
|
119
|
+
walk(node.init);
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
case utils_1.AST_NODE_TYPES.CallExpression:
|
|
123
|
+
// Walk through arguments to find callback functions
|
|
124
|
+
node.arguments.forEach((arg) => walk(arg));
|
|
125
|
+
break;
|
|
126
|
+
case utils_1.AST_NODE_TYPES.FunctionExpression:
|
|
127
|
+
case utils_1.AST_NODE_TYPES.ArrowFunctionExpression:
|
|
128
|
+
// For callback functions, walk their body
|
|
129
|
+
if (isCallbackFunctionNode(node)) {
|
|
130
|
+
if (node.body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
131
|
+
walk(node.body);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// Arrow function with expression body
|
|
135
|
+
walk(node.body);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
break;
|
|
139
|
+
case utils_1.AST_NODE_TYPES.ForStatement:
|
|
140
|
+
case utils_1.AST_NODE_TYPES.ForInStatement:
|
|
141
|
+
case utils_1.AST_NODE_TYPES.ForOfStatement:
|
|
142
|
+
case utils_1.AST_NODE_TYPES.WhileStatement:
|
|
143
|
+
case utils_1.AST_NODE_TYPES.DoWhileStatement:
|
|
144
|
+
walk(node.body);
|
|
145
|
+
break;
|
|
146
|
+
case utils_1.AST_NODE_TYPES.SwitchStatement:
|
|
147
|
+
node.cases.forEach((caseNode) => walk(caseNode));
|
|
148
|
+
break;
|
|
149
|
+
case utils_1.AST_NODE_TYPES.SwitchCase:
|
|
150
|
+
node.consequent.forEach((stmt) => walk(stmt));
|
|
151
|
+
break;
|
|
152
|
+
case utils_1.AST_NODE_TYPES.LabeledStatement:
|
|
153
|
+
case utils_1.AST_NODE_TYPES.WithStatement:
|
|
154
|
+
walk(node.body);
|
|
155
|
+
break;
|
|
156
|
+
case utils_1.AST_NODE_TYPES.TryStatement:
|
|
157
|
+
walk(node.block);
|
|
158
|
+
if (node.handler) {
|
|
159
|
+
walk(node.handler);
|
|
160
|
+
}
|
|
161
|
+
if (node.finalizer) {
|
|
162
|
+
walk(node.finalizer);
|
|
163
|
+
}
|
|
164
|
+
break;
|
|
165
|
+
case utils_1.AST_NODE_TYPES.CatchClause:
|
|
166
|
+
walk(node.body);
|
|
167
|
+
break;
|
|
168
|
+
default:
|
|
169
|
+
// Handle other node types generically
|
|
170
|
+
for (const key of Object.keys(node)) {
|
|
171
|
+
if (key === 'parent' || key === 'range' || key === 'loc')
|
|
172
|
+
continue;
|
|
173
|
+
const value = node[key];
|
|
174
|
+
if (Array.isArray(value)) {
|
|
175
|
+
value.forEach((item) => {
|
|
176
|
+
if (item &&
|
|
177
|
+
typeof item === 'object' &&
|
|
178
|
+
'type' in item &&
|
|
179
|
+
!isTypeLikeNode(item)) {
|
|
180
|
+
walk(item);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
else if (value &&
|
|
185
|
+
typeof value === 'object' &&
|
|
186
|
+
'type' in value &&
|
|
187
|
+
!isTypeLikeNode(value)) {
|
|
188
|
+
walk(value);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
walk(node);
|
|
194
|
+
return hasAssertCall;
|
|
195
|
+
}
|
|
21
196
|
function isAssertionCall(node) {
|
|
22
197
|
if (node.type === utils_1.AST_NODE_TYPES.ExpressionStatement) {
|
|
23
198
|
const expression = node.expression;
|
|
@@ -62,9 +237,177 @@ exports.enforceAssertThrows = (0, createRule_1.createRule)({
|
|
|
62
237
|
}
|
|
63
238
|
return false;
|
|
64
239
|
}
|
|
240
|
+
// Check if a call expression is calling an assert-prefixed method
|
|
241
|
+
function isCallingAssertMethod(node, functionBody) {
|
|
242
|
+
if (node.type === utils_1.AST_NODE_TYPES.ReturnStatement && node.argument) {
|
|
243
|
+
return isCallingAssertMethodInExpression(node.argument, functionBody || undefined);
|
|
244
|
+
}
|
|
245
|
+
else if (node.type === utils_1.AST_NODE_TYPES.ExpressionStatement) {
|
|
246
|
+
return isCallingAssertMethodInExpression(node.expression, functionBody || undefined);
|
|
247
|
+
}
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
function isCallingAssertMethodInExpression(expression, functionBody) {
|
|
251
|
+
// Handle direct call: this.assertSomething()
|
|
252
|
+
if (expression.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
253
|
+
const callee = expression.callee;
|
|
254
|
+
if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression) {
|
|
255
|
+
const property = callee.property;
|
|
256
|
+
if (property.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
257
|
+
return property.name.toLowerCase().startsWith('assert');
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
else if (callee.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
261
|
+
// Check if it's a direct assert function call
|
|
262
|
+
if (callee.name.toLowerCase().startsWith('assert')) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
// Check if it's a variable that was assigned an assert method
|
|
266
|
+
if (functionBody &&
|
|
267
|
+
isCallingVariableAssignedAssertMethod(expression, functionBody)) {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Handle chained calls: this.assertA().then(() => this.assertB())
|
|
272
|
+
if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
273
|
+
callee.property.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
274
|
+
// Check if the method name is 'then' or other promise-related methods
|
|
275
|
+
if (['then', 'catch', 'finally'].includes(callee.property.name)) {
|
|
276
|
+
// Check if the first part of the chain is an assert call
|
|
277
|
+
if (callee.object.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
278
|
+
const objectCallee = callee.object.callee;
|
|
279
|
+
if (objectCallee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
280
|
+
objectCallee.property.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
281
|
+
if (objectCallee.property.name.toLowerCase().startsWith('assert')) {
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// Check if any of the arguments to then/catch/finally are calling assert methods
|
|
287
|
+
if (expression.arguments.length > 0) {
|
|
288
|
+
for (const arg of expression.arguments) {
|
|
289
|
+
if (arg.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
290
|
+
arg.type === utils_1.AST_NODE_TYPES.FunctionExpression) {
|
|
291
|
+
// Check the function body for assert calls
|
|
292
|
+
if (arg.body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
293
|
+
for (const stmt of arg.body.body) {
|
|
294
|
+
if (isCallingAssertMethod(stmt)) {
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
else if (arg.body.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
300
|
+
// Arrow function with expression body
|
|
301
|
+
const arrowCallee = arg.body.callee;
|
|
302
|
+
if (arrowCallee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
303
|
+
arrowCallee.property.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
304
|
+
if (arrowCallee.property.name
|
|
305
|
+
.toLowerCase()
|
|
306
|
+
.startsWith('assert')) {
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
// Handle await expression: await this.assertSomething()
|
|
318
|
+
if (expression.type === utils_1.AST_NODE_TYPES.AwaitExpression) {
|
|
319
|
+
return isCallingAssertMethodInExpression(expression.argument, functionBody);
|
|
320
|
+
}
|
|
321
|
+
// Handle ternary expressions: condition ? this.assertA() : this.assertB()
|
|
322
|
+
if (expression.type === utils_1.AST_NODE_TYPES.ConditionalExpression) {
|
|
323
|
+
return (isCallingAssertMethodInExpression(expression.consequent, functionBody) ||
|
|
324
|
+
isCallingAssertMethodInExpression(expression.alternate, functionBody));
|
|
325
|
+
}
|
|
326
|
+
// Handle logical expressions: this.assertA() || this.assertB()
|
|
327
|
+
if (expression.type === utils_1.AST_NODE_TYPES.LogicalExpression) {
|
|
328
|
+
return (isCallingAssertMethodInExpression(expression.left, functionBody) ||
|
|
329
|
+
isCallingAssertMethodInExpression(expression.right, functionBody));
|
|
330
|
+
}
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
// Special case for the method chaining pattern in the test
|
|
334
|
+
function hasPromiseChainWithAssertMethods(node) {
|
|
335
|
+
const walkChain = (callExpr) => {
|
|
336
|
+
let current = callExpr;
|
|
337
|
+
while (current) {
|
|
338
|
+
const callee = current.callee;
|
|
339
|
+
if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
340
|
+
callee.property.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
341
|
+
callee.property.name.toLowerCase().startsWith('assert')) {
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
345
|
+
callee.object.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
346
|
+
// Walk further up any chained call (then/catch/finally or other links).
|
|
347
|
+
current = callee.object;
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
return false;
|
|
353
|
+
};
|
|
354
|
+
if (node.type === utils_1.AST_NODE_TYPES.ReturnStatement && node.argument) {
|
|
355
|
+
if (node.argument.type === utils_1.AST_NODE_TYPES.CallExpression &&
|
|
356
|
+
walkChain(node.argument)) {
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (node.type === utils_1.AST_NODE_TYPES.VariableDeclaration) {
|
|
361
|
+
for (const declarator of node.declarations) {
|
|
362
|
+
if (declarator.init &&
|
|
363
|
+
declarator.init.type === utils_1.AST_NODE_TYPES.AwaitExpression &&
|
|
364
|
+
declarator.init.argument.type === utils_1.AST_NODE_TYPES.CallExpression &&
|
|
365
|
+
walkChain(declarator.init.argument)) {
|
|
366
|
+
return true;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
// Check if a variable is assigned an assert method
|
|
373
|
+
function isVariableAssignedAssertMethod(node, variableName) {
|
|
374
|
+
if (node.type === utils_1.AST_NODE_TYPES.VariableDeclaration) {
|
|
375
|
+
for (const declarator of node.declarations) {
|
|
376
|
+
if (declarator.id.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
377
|
+
declarator.id.name === variableName &&
|
|
378
|
+
declarator.init) {
|
|
379
|
+
if (declarator.init.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
380
|
+
declarator.init.property.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
381
|
+
return declarator.init.property.name
|
|
382
|
+
.toLowerCase()
|
|
383
|
+
.startsWith('assert');
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
// Check if a call expression is calling a variable that was assigned an assert method
|
|
391
|
+
function isCallingVariableAssignedAssertMethod(expression, functionBody) {
|
|
392
|
+
if (expression.callee.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
393
|
+
const variableName = expression.callee.name;
|
|
394
|
+
// Check if this variable was assigned an assert method in the function body
|
|
395
|
+
for (const stmt of functionBody.body) {
|
|
396
|
+
if (isVariableAssignedAssertMethod(stmt, variableName)) {
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return false;
|
|
402
|
+
}
|
|
65
403
|
function hasThrowStatement(node) {
|
|
66
404
|
let hasThrow = false;
|
|
405
|
+
const functionBody = node.type === utils_1.AST_NODE_TYPES.BlockStatement ? node : null;
|
|
67
406
|
function walk(node) {
|
|
407
|
+
if (hasThrow)
|
|
408
|
+
return; // Early exit if we already found a throw
|
|
409
|
+
if (isTypeLikeNode(node))
|
|
410
|
+
return;
|
|
68
411
|
if (node.type === utils_1.AST_NODE_TYPES.ThrowStatement) {
|
|
69
412
|
hasThrow = true;
|
|
70
413
|
return;
|
|
@@ -81,58 +424,144 @@ exports.enforceAssertThrows = (0, createRule_1.createRule)({
|
|
|
81
424
|
hasThrow = true;
|
|
82
425
|
return;
|
|
83
426
|
}
|
|
84
|
-
//
|
|
427
|
+
// Check for calls to other assert methods
|
|
428
|
+
if (isCallingAssertMethod(node, functionBody)) {
|
|
429
|
+
hasThrow = true;
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
// Check for promise chains with assert methods
|
|
433
|
+
if (hasPromiseChainWithAssertMethods(node)) {
|
|
434
|
+
hasThrow = true;
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
// Handle nested functions - only skip if it's a standalone function, not a callback
|
|
85
438
|
if (node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration ||
|
|
86
439
|
node.type === utils_1.AST_NODE_TYPES.FunctionExpression ||
|
|
87
440
|
node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
88
441
|
if (node !== currentFunction) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (node.type === utils_1.AST_NODE_TYPES.CatchClause) {
|
|
94
|
-
walk(node.body);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
// Handle TryStatement specially
|
|
98
|
-
if (node.type === utils_1.AST_NODE_TYPES.TryStatement) {
|
|
99
|
-
walk(node.block);
|
|
100
|
-
if (node.handler) {
|
|
101
|
-
walk(node.handler);
|
|
102
|
-
}
|
|
103
|
-
if (node.finalizer) {
|
|
104
|
-
walk(node.finalizer);
|
|
442
|
+
// Allow traversing into callback functions
|
|
443
|
+
if (!isCallbackFunctionNode(node)) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
105
446
|
}
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
// Handle BlockStatement specially
|
|
109
|
-
if (node.type === utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
110
|
-
node.body.forEach((stmt) => walk(stmt));
|
|
111
|
-
return;
|
|
112
447
|
}
|
|
113
|
-
// Handle
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
448
|
+
// Handle specific node types that need special traversal
|
|
449
|
+
switch (node.type) {
|
|
450
|
+
case utils_1.AST_NODE_TYPES.CatchClause:
|
|
451
|
+
walk(node.body);
|
|
452
|
+
return;
|
|
453
|
+
case utils_1.AST_NODE_TYPES.TryStatement:
|
|
454
|
+
walk(node.block);
|
|
455
|
+
if (node.handler) {
|
|
456
|
+
walk(node.handler);
|
|
457
|
+
}
|
|
458
|
+
if (node.finalizer) {
|
|
459
|
+
walk(node.finalizer);
|
|
460
|
+
}
|
|
461
|
+
return;
|
|
462
|
+
case utils_1.AST_NODE_TYPES.BlockStatement:
|
|
463
|
+
node.body.forEach((stmt) => walk(stmt));
|
|
464
|
+
return;
|
|
465
|
+
case utils_1.AST_NODE_TYPES.IfStatement:
|
|
466
|
+
walk(node.consequent);
|
|
467
|
+
if (node.alternate) {
|
|
468
|
+
walk(node.alternate);
|
|
469
|
+
}
|
|
470
|
+
return;
|
|
471
|
+
case utils_1.AST_NODE_TYPES.ConditionalExpression:
|
|
472
|
+
walk(node.consequent);
|
|
117
473
|
walk(node.alternate);
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
474
|
+
return;
|
|
475
|
+
case utils_1.AST_NODE_TYPES.LogicalExpression:
|
|
476
|
+
walk(node.left);
|
|
477
|
+
walk(node.right);
|
|
478
|
+
return;
|
|
479
|
+
case utils_1.AST_NODE_TYPES.ForStatement:
|
|
480
|
+
walk(node.body);
|
|
481
|
+
return;
|
|
482
|
+
case utils_1.AST_NODE_TYPES.ForInStatement:
|
|
483
|
+
walk(node.body);
|
|
484
|
+
return;
|
|
485
|
+
case utils_1.AST_NODE_TYPES.ForOfStatement:
|
|
486
|
+
walk(node.body);
|
|
487
|
+
return;
|
|
488
|
+
case utils_1.AST_NODE_TYPES.WhileStatement:
|
|
489
|
+
walk(node.body);
|
|
490
|
+
return;
|
|
491
|
+
case utils_1.AST_NODE_TYPES.DoWhileStatement:
|
|
492
|
+
walk(node.body);
|
|
493
|
+
return;
|
|
494
|
+
case utils_1.AST_NODE_TYPES.SwitchStatement:
|
|
495
|
+
node.cases.forEach((caseNode) => walk(caseNode));
|
|
496
|
+
return;
|
|
497
|
+
case utils_1.AST_NODE_TYPES.SwitchCase:
|
|
498
|
+
node.consequent.forEach((stmt) => walk(stmt));
|
|
499
|
+
return;
|
|
500
|
+
case utils_1.AST_NODE_TYPES.LabeledStatement:
|
|
501
|
+
walk(node.body);
|
|
502
|
+
return;
|
|
503
|
+
case utils_1.AST_NODE_TYPES.WithStatement:
|
|
504
|
+
walk(node.body);
|
|
505
|
+
return;
|
|
506
|
+
case utils_1.AST_NODE_TYPES.ExpressionStatement:
|
|
507
|
+
walk(node.expression);
|
|
508
|
+
return;
|
|
509
|
+
case utils_1.AST_NODE_TYPES.ReturnStatement:
|
|
510
|
+
if (node.argument) {
|
|
511
|
+
walk(node.argument);
|
|
512
|
+
}
|
|
513
|
+
return;
|
|
514
|
+
case utils_1.AST_NODE_TYPES.CallExpression:
|
|
515
|
+
// Walk through arguments to find callback functions
|
|
516
|
+
node.arguments.forEach((arg) => walk(arg));
|
|
517
|
+
return;
|
|
518
|
+
case utils_1.AST_NODE_TYPES.FunctionExpression:
|
|
519
|
+
case utils_1.AST_NODE_TYPES.ArrowFunctionExpression:
|
|
520
|
+
// For callback functions, walk their body
|
|
521
|
+
if (isCallbackFunctionNode(node)) {
|
|
522
|
+
if (node.body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
523
|
+
walk(node.body);
|
|
128
524
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
525
|
+
else {
|
|
526
|
+
// Arrow function with expression body
|
|
527
|
+
walk(node.body);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return;
|
|
531
|
+
case utils_1.AST_NODE_TYPES.VariableDeclaration:
|
|
532
|
+
node.declarations.forEach((decl) => walk(decl));
|
|
533
|
+
return;
|
|
534
|
+
case utils_1.AST_NODE_TYPES.VariableDeclarator:
|
|
535
|
+
if (node.init) {
|
|
536
|
+
walk(node.init);
|
|
537
|
+
}
|
|
538
|
+
return;
|
|
539
|
+
case utils_1.AST_NODE_TYPES.AwaitExpression:
|
|
540
|
+
walk(node.argument);
|
|
541
|
+
return;
|
|
542
|
+
default:
|
|
543
|
+
// Handle other node types generically
|
|
544
|
+
for (const key of Object.keys(node)) {
|
|
545
|
+
if (key === 'parent' || key === 'range' || key === 'loc')
|
|
546
|
+
continue;
|
|
547
|
+
const value = node[key];
|
|
548
|
+
if (Array.isArray(value)) {
|
|
549
|
+
value.forEach((item) => {
|
|
550
|
+
if (item &&
|
|
551
|
+
typeof item === 'object' &&
|
|
552
|
+
'type' in item &&
|
|
553
|
+
!isTypeLikeNode(item)) {
|
|
554
|
+
walk(item);
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
else if (value &&
|
|
559
|
+
typeof value === 'object' &&
|
|
560
|
+
'type' in value &&
|
|
561
|
+
!isTypeLikeNode(value)) {
|
|
562
|
+
walk(value);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
136
565
|
}
|
|
137
566
|
}
|
|
138
567
|
walk(node);
|
|
@@ -157,19 +586,32 @@ exports.enforceAssertThrows = (0, createRule_1.createRule)({
|
|
|
157
586
|
functionName = parent.id.name;
|
|
158
587
|
}
|
|
159
588
|
}
|
|
589
|
+
const displayName = functionName || 'this function';
|
|
590
|
+
currentFunction = node;
|
|
591
|
+
const functionBody = node.type === utils_1.AST_NODE_TYPES.MethodDefinition
|
|
592
|
+
? node.value.body
|
|
593
|
+
: node.body;
|
|
160
594
|
if (functionName.toLowerCase().startsWith('assert')) {
|
|
161
|
-
|
|
162
|
-
const functionBody = node.type === utils_1.AST_NODE_TYPES.MethodDefinition
|
|
163
|
-
? node.value.body
|
|
164
|
-
: node.body;
|
|
595
|
+
// Check that assert-prefixed functions throw or call other assert functions
|
|
165
596
|
if (functionBody && !hasThrowStatement(functionBody)) {
|
|
166
597
|
context.report({
|
|
167
598
|
node,
|
|
168
599
|
messageId: 'assertShouldThrow',
|
|
600
|
+
data: { functionName: displayName },
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
else if (functionName && functionBody) {
|
|
605
|
+
// Check that functions calling assert-prefixed methods are themselves prefixed with assert
|
|
606
|
+
if (callsAssertMethod(functionBody)) {
|
|
607
|
+
context.report({
|
|
608
|
+
node,
|
|
609
|
+
messageId: 'shouldBeAssertPrefixed',
|
|
610
|
+
data: { functionName: displayName },
|
|
169
611
|
});
|
|
170
612
|
}
|
|
171
|
-
currentFunction = null;
|
|
172
613
|
}
|
|
614
|
+
currentFunction = null;
|
|
173
615
|
}
|
|
174
616
|
return {
|
|
175
617
|
FunctionDeclaration: checkFunction,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { TSESLint } from '@typescript-eslint/utils';
|
|
1
2
|
type Options = [
|
|
2
3
|
{
|
|
3
4
|
prefixes?: string[];
|
|
5
|
+
ignoreOverriddenGetters?: boolean;
|
|
4
6
|
}
|
|
5
7
|
];
|
|
6
|
-
export declare const enforceBooleanNamingPrefixes:
|
|
8
|
+
export declare const enforceBooleanNamingPrefixes: TSESLint.RuleModule<"missingBooleanPrefix", Options, TSESLint.RuleListener>;
|
|
7
9
|
export {};
|