@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,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.extractGlobalConstants = void 0;
|
|
4
4
|
const ASTHelpers_1 = require("../utils/ASTHelpers");
|
|
5
5
|
const createRule_1 = require("../utils/createRule");
|
|
6
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
6
7
|
function isInsideFunction(node) {
|
|
7
8
|
let current = node;
|
|
8
9
|
while (current) {
|
|
@@ -19,53 +20,61 @@ function isFunctionDefinition(node) {
|
|
|
19
20
|
return (node?.type === 'FunctionExpression' ||
|
|
20
21
|
node?.type === 'ArrowFunctionExpression');
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
+
const unwrapOnce = (node) => {
|
|
23
24
|
if (!node)
|
|
24
|
-
return
|
|
25
|
+
return null;
|
|
26
|
+
const maybeParen = node;
|
|
27
|
+
if (maybeParen.type === 'ParenthesizedExpression') {
|
|
28
|
+
return maybeParen.expression ?? null;
|
|
29
|
+
}
|
|
25
30
|
switch (node.type) {
|
|
26
|
-
case
|
|
27
|
-
|
|
28
|
-
case
|
|
29
|
-
|
|
30
|
-
case
|
|
31
|
-
return
|
|
32
|
-
case 'BinaryExpression':
|
|
33
|
-
if (node.left.type === 'PrivateIdentifier')
|
|
34
|
-
return false;
|
|
35
|
-
return isImmutableValue(node.left) && isImmutableValue(node.right);
|
|
31
|
+
case utils_1.AST_NODE_TYPES.TSAsExpression:
|
|
32
|
+
case utils_1.AST_NODE_TYPES.TSSatisfiesExpression:
|
|
33
|
+
case utils_1.AST_NODE_TYPES.TSNonNullExpression:
|
|
34
|
+
case utils_1.AST_NODE_TYPES.ChainExpression:
|
|
35
|
+
case utils_1.AST_NODE_TYPES.TSTypeAssertion:
|
|
36
|
+
return node.expression;
|
|
36
37
|
default:
|
|
37
|
-
return
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
function unwrapExpression(node) {
|
|
42
|
+
let current = node;
|
|
43
|
+
while (current) {
|
|
44
|
+
const inner = unwrapOnce(current);
|
|
45
|
+
if (!inner)
|
|
46
|
+
break;
|
|
47
|
+
current = inner;
|
|
38
48
|
}
|
|
49
|
+
return current;
|
|
39
50
|
}
|
|
40
51
|
function isMutableValue(node) {
|
|
41
|
-
|
|
52
|
+
const unwrapped = unwrapExpression(node);
|
|
53
|
+
if (!unwrapped)
|
|
54
|
+
return false;
|
|
55
|
+
// If explicitly marked readonly with `as const`, treat as immutable
|
|
56
|
+
if (node && isAsConstExpression(node)) {
|
|
42
57
|
return false;
|
|
58
|
+
}
|
|
43
59
|
// Check for JSX elements (always mutable due to props/context)
|
|
44
|
-
if (
|
|
60
|
+
if (unwrapped.type === 'JSXElement' || unwrapped.type === 'JSXFragment') {
|
|
45
61
|
return true;
|
|
46
62
|
}
|
|
47
63
|
// Check for object expressions (always mutable)
|
|
48
|
-
if (
|
|
64
|
+
if (unwrapped.type === 'ObjectExpression') {
|
|
49
65
|
return true;
|
|
50
66
|
}
|
|
51
|
-
//
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
if (node.elements.length === 0)
|
|
55
|
-
return true;
|
|
56
|
-
// Arrays with spread elements are mutable
|
|
57
|
-
if (node.elements.some((element) => !element || element.type === 'SpreadElement'))
|
|
58
|
-
return true;
|
|
59
|
-
// Arrays with non-immutable values are mutable
|
|
60
|
-
return node.elements.some((element) => !isImmutableValue(element));
|
|
67
|
+
// Arrays are mutable objects unless explicitly narrowed with `as const`.
|
|
68
|
+
if (unwrapped.type === 'ArrayExpression') {
|
|
69
|
+
return true;
|
|
61
70
|
}
|
|
62
71
|
// Check for new expressions (e.g., new Map(), new Set())
|
|
63
|
-
if (
|
|
72
|
+
if (unwrapped.type === 'NewExpression') {
|
|
64
73
|
return true;
|
|
65
74
|
}
|
|
66
75
|
// Check for array/object methods that return mutable values
|
|
67
|
-
if (
|
|
68
|
-
const callee =
|
|
76
|
+
if (unwrapped.type === 'CallExpression') {
|
|
77
|
+
const callee = unwrapped.callee;
|
|
69
78
|
if (callee.type === 'MemberExpression') {
|
|
70
79
|
// Handle both Identifier and non-Identifier property nodes
|
|
71
80
|
if (callee.property.type !== 'Identifier') {
|
|
@@ -103,17 +112,31 @@ function isZeroOrOne(node) {
|
|
|
103
112
|
return value === 0 || value === 1;
|
|
104
113
|
}
|
|
105
114
|
function isAsConstExpression(node) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
115
|
+
let current = node;
|
|
116
|
+
while (current) {
|
|
117
|
+
if (current.type === 'TSAsExpression' &&
|
|
118
|
+
current.typeAnnotation.type === 'TSTypeReference' &&
|
|
119
|
+
current.typeAnnotation.typeName.type === 'Identifier' &&
|
|
120
|
+
current.typeAnnotation.typeName.name === 'const') {
|
|
112
121
|
return true;
|
|
113
122
|
}
|
|
123
|
+
current = unwrapOnce(current);
|
|
114
124
|
}
|
|
115
125
|
return false;
|
|
116
126
|
}
|
|
127
|
+
function analyzeDeclarator(declaration) {
|
|
128
|
+
const init = declaration.init ?? null;
|
|
129
|
+
const isFunctionOrMutable = isFunctionDefinition(init) || isMutableValue(init);
|
|
130
|
+
return {
|
|
131
|
+
isFunctionOrMutable,
|
|
132
|
+
hasDependencies: !isFunctionOrMutable && init
|
|
133
|
+
? ASTHelpers_1.ASTHelpers.declarationIncludesIdentifier(init)
|
|
134
|
+
: false,
|
|
135
|
+
hasAsConstAssertion: !isFunctionOrMutable && init ? isAsConstExpression(init) : false,
|
|
136
|
+
hasReportableIdentifier: declaration.id?.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
137
|
+
!isFunctionOrMutable,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
117
140
|
exports.extractGlobalConstants = (0, createRule_1.createRule)({
|
|
118
141
|
create(context) {
|
|
119
142
|
return {
|
|
@@ -121,29 +144,45 @@ exports.extractGlobalConstants = (0, createRule_1.createRule)({
|
|
|
121
144
|
if (node.kind !== 'const') {
|
|
122
145
|
return;
|
|
123
146
|
}
|
|
124
|
-
|
|
125
|
-
if (
|
|
147
|
+
const declarations = node.declarations.filter((declaration) => declaration !== null && declaration !== undefined);
|
|
148
|
+
if (declarations.length === 0) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
let hasFunctionOrMutableValue = false;
|
|
152
|
+
let hasDependencies = false;
|
|
153
|
+
let hasAsConstAssertion = false;
|
|
154
|
+
let hasReportableIdentifierDeclaration = false;
|
|
155
|
+
for (const declaration of declarations) {
|
|
156
|
+
const analysis = analyzeDeclarator(declaration);
|
|
157
|
+
if (analysis.isFunctionOrMutable) {
|
|
158
|
+
hasFunctionOrMutableValue = true;
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
hasDependencies ||= analysis.hasDependencies;
|
|
162
|
+
hasAsConstAssertion ||= analysis.hasAsConstAssertion;
|
|
163
|
+
hasReportableIdentifierDeclaration ||=
|
|
164
|
+
analysis.hasReportableIdentifier;
|
|
165
|
+
}
|
|
166
|
+
if (hasFunctionOrMutableValue) {
|
|
126
167
|
return;
|
|
127
168
|
}
|
|
128
169
|
const scope = context.getScope();
|
|
129
|
-
const hasDependencies = node.declarations.some((declaration) => declaration.init &&
|
|
130
|
-
ASTHelpers_1.ASTHelpers.declarationIncludesIdentifier(declaration.init));
|
|
131
|
-
// Skip constants with 'as const' type assertions used in loops
|
|
132
|
-
const hasAsConstAssertion = node.declarations.some((declaration) => declaration.init && isAsConstExpression(declaration.init));
|
|
133
170
|
// Only check function/block scoped constants without dependencies
|
|
134
171
|
if (!hasDependencies &&
|
|
135
172
|
!hasAsConstAssertion &&
|
|
136
173
|
(scope.type === 'function' || scope.type === 'block') &&
|
|
137
|
-
isInsideFunction(node)
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
174
|
+
isInsideFunction(node) &&
|
|
175
|
+
hasReportableIdentifierDeclaration) {
|
|
176
|
+
for (const declaration of declarations) {
|
|
177
|
+
if (declaration.id?.type !== utils_1.AST_NODE_TYPES.Identifier)
|
|
178
|
+
continue;
|
|
179
|
+
const constName = declaration.id.name;
|
|
180
|
+
context.report({
|
|
181
|
+
node: declaration,
|
|
182
|
+
messageId: 'extractGlobalConstants',
|
|
183
|
+
data: { declarationName: constName },
|
|
184
|
+
});
|
|
185
|
+
}
|
|
147
186
|
}
|
|
148
187
|
},
|
|
149
188
|
FunctionDeclaration(node) {
|
|
@@ -271,8 +310,8 @@ exports.extractGlobalConstants = (0, createRule_1.createRule)({
|
|
|
271
310
|
},
|
|
272
311
|
schema: [],
|
|
273
312
|
messages: {
|
|
274
|
-
extractGlobalConstants: '
|
|
275
|
-
requireAsConst: 'Numeric literal {{
|
|
313
|
+
extractGlobalConstants: 'What\'s wrong: Declaration "{{declarationName}}" does not reference values from this scope.\nWhy it matters: Keeping it nested recreates the same constant/helper on every call, which adds avoidable allocations and obscures that the value can be shared.\nHow to fix: Hoist it to module scope (use UPPER_SNAKE_CASE for immutable constants) so it is created once and can be imported.',
|
|
314
|
+
requireAsConst: 'What\'s wrong: Numeric literal {{value}} is used directly as a loop boundary.\nWhy it matters: Without "as const", TypeScript widens it to number, so if you later extract or reuse the value you lose the literal-type boundary and it is easier for related loops to drift out of sync.\nHow to fix: Extract it to a named constant with "as const" (or add "as const" inline) to keep the boundary explicit and reusable.',
|
|
276
315
|
},
|
|
277
316
|
},
|
|
278
317
|
defaultOptions: [],
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TSESLint } from '@typescript-eslint/utils';
|
|
1
2
|
type MessageIds = 'useFastDeepEqual' | 'addFastDeepEqualImport';
|
|
2
|
-
export declare const fastDeepEqualOverMicrodiff:
|
|
3
|
+
export declare const fastDeepEqualOverMicrodiff: TSESLint.RuleModule<MessageIds, [], TSESLint.RuleListener>;
|
|
3
4
|
export {};
|