@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,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.jsdocAboveField = void 0;
|
|
4
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
5
|
+
const createRule_1 = require("../utils/createRule");
|
|
6
|
+
const defaultOptions = [{ checkObjectLiterals: false }];
|
|
7
|
+
exports.jsdocAboveField = (0, createRule_1.createRule)({
|
|
8
|
+
name: 'jsdoc-above-field',
|
|
9
|
+
meta: {
|
|
10
|
+
type: 'suggestion',
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Require JSDoc blocks to sit above fields instead of trailing inline so IDE hovers surface the documentation.',
|
|
13
|
+
recommended: 'error',
|
|
14
|
+
},
|
|
15
|
+
fixable: 'code',
|
|
16
|
+
schema: [
|
|
17
|
+
{
|
|
18
|
+
type: 'object',
|
|
19
|
+
properties: {
|
|
20
|
+
checkObjectLiterals: {
|
|
21
|
+
type: 'boolean',
|
|
22
|
+
description: 'Also enforce JSDoc placement for object literal properties.',
|
|
23
|
+
default: false,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
additionalProperties: false,
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
messages: {
|
|
30
|
+
moveJsdocAbove: 'Inline JSDoc for "{{name}}" sits after the {{kind}} → IDE hovers and autocomplete skip trailing inline JSDoc, so tags like @deprecated/@default never surface when developers hover → Move the JSDoc block above the {{kind}} (and above any decorators or modifiers) so the documentation stays visible where it is needed.',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
defaultOptions,
|
|
34
|
+
create(context, [options = defaultOptions[0]]) {
|
|
35
|
+
const sourceCode = context.getSourceCode();
|
|
36
|
+
const { checkObjectLiterals = false } = options;
|
|
37
|
+
const allComments = sourceCode.getAllComments();
|
|
38
|
+
const isRelevantNode = (node) => {
|
|
39
|
+
if (node.type === utils_1.AST_NODE_TYPES.TSPropertySignature) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
if (node.type === utils_1.AST_NODE_TYPES.PropertyDefinition) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
if (checkObjectLiterals &&
|
|
46
|
+
node.type === utils_1.AST_NODE_TYPES.Property &&
|
|
47
|
+
node.parent?.type === utils_1.AST_NODE_TYPES.ObjectExpression) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
};
|
|
52
|
+
const isJSDocBlock = (comment) => comment.type === 'Block' && comment.value.startsWith('*');
|
|
53
|
+
const getPropertyName = (node) => {
|
|
54
|
+
const key = node.key;
|
|
55
|
+
if (key.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
56
|
+
return key.name;
|
|
57
|
+
}
|
|
58
|
+
if (key.type === utils_1.AST_NODE_TYPES.Literal &&
|
|
59
|
+
typeof key.value === 'string') {
|
|
60
|
+
return key.value;
|
|
61
|
+
}
|
|
62
|
+
return 'computed property';
|
|
63
|
+
};
|
|
64
|
+
const getKind = (node) => {
|
|
65
|
+
if (node.type === utils_1.AST_NODE_TYPES.PropertyDefinition) {
|
|
66
|
+
return 'class field';
|
|
67
|
+
}
|
|
68
|
+
if (node.type === utils_1.AST_NODE_TYPES.Property) {
|
|
69
|
+
return 'object property';
|
|
70
|
+
}
|
|
71
|
+
return 'type field';
|
|
72
|
+
};
|
|
73
|
+
const inlineJSDocOnSameLine = (node) => {
|
|
74
|
+
return allComments.find((comment) => {
|
|
75
|
+
if (!isJSDocBlock(comment)) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
if (comment.loc.start.line !== node.loc.end.line) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
if (comment.range[0] < node.range[1]) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
const between = sourceCode.text.slice(node.range[1], comment.range[0]);
|
|
85
|
+
return /^[\s;,]*$/.test(between);
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
const indentForNode = (node) => {
|
|
89
|
+
const line = sourceCode.lines[node.loc.start.line - 1] ?? '';
|
|
90
|
+
const beforeColumn = line.slice(0, node.loc.start.column);
|
|
91
|
+
const trailingWhitespace = beforeColumn.match(/\s*$/);
|
|
92
|
+
return trailingWhitespace?.[0] ?? '';
|
|
93
|
+
};
|
|
94
|
+
const formatCommentWithIndent = (comment, indent) => {
|
|
95
|
+
const rawText = sourceCode.getText(comment);
|
|
96
|
+
const rawLines = rawText.split('\n');
|
|
97
|
+
let minIndentAfterStar;
|
|
98
|
+
// Calculate minimum indentation across all lines (excluding the first line and standard closing line)
|
|
99
|
+
rawLines.slice(1).forEach((line, index, arr) => {
|
|
100
|
+
const isLastLine = index === arr.length - 1;
|
|
101
|
+
const starMatch = line.match(/^\s*\*(.*)$/);
|
|
102
|
+
if (!starMatch) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const afterStar = starMatch[1];
|
|
106
|
+
// Skip the standard " */" closing line
|
|
107
|
+
if (isLastLine && afterStar.trim() === '/') {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const contentIndent = afterStar.match(/^([ \t]*)\S/);
|
|
111
|
+
if (contentIndent) {
|
|
112
|
+
const indentLength = contentIndent[1].length;
|
|
113
|
+
minIndentAfterStar =
|
|
114
|
+
minIndentAfterStar === undefined
|
|
115
|
+
? indentLength
|
|
116
|
+
: Math.min(minIndentAfterStar, indentLength);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
// Normalize indentation: we want the minimum indentation after '*' to be exactly 1 space.
|
|
120
|
+
// (e.g., if min indent is 3, we strip 2; if min indent is 0, we add 1).
|
|
121
|
+
const indentToAdjustment = minIndentAfterStar === undefined ? 0 : minIndentAfterStar - 1;
|
|
122
|
+
const normalize = (text) => {
|
|
123
|
+
if (indentToAdjustment > 0) {
|
|
124
|
+
return text.replace(new RegExp(`^[ \\t]{0,${indentToAdjustment}}`), '');
|
|
125
|
+
}
|
|
126
|
+
if (indentToAdjustment < 0) {
|
|
127
|
+
return ' '.repeat(-indentToAdjustment) + text;
|
|
128
|
+
}
|
|
129
|
+
return text;
|
|
130
|
+
};
|
|
131
|
+
const normalizedLines = rawLines.map((line, index) => {
|
|
132
|
+
if (index === 0) {
|
|
133
|
+
return line.trimStart();
|
|
134
|
+
}
|
|
135
|
+
const starMatch = line.match(/^\s*\*(.*)$/);
|
|
136
|
+
if (!starMatch) {
|
|
137
|
+
return line.trimStart();
|
|
138
|
+
}
|
|
139
|
+
const afterStar = normalize(starMatch[1]);
|
|
140
|
+
if (afterStar.trim() === '/') {
|
|
141
|
+
return ' */';
|
|
142
|
+
}
|
|
143
|
+
if (afterStar.trim() === '') {
|
|
144
|
+
return ' *';
|
|
145
|
+
}
|
|
146
|
+
const needsSpace = !afterStar.startsWith(' ') && !afterStar.startsWith('\t');
|
|
147
|
+
const content = needsSpace ? ` ${afterStar}` : afterStar;
|
|
148
|
+
return ` *${content}`;
|
|
149
|
+
});
|
|
150
|
+
return normalizedLines.map((line) => `${indent}${line}`).join('\n');
|
|
151
|
+
};
|
|
152
|
+
const reportInlineJSDoc = (node, comment) => {
|
|
153
|
+
const insertTarget = node.type === utils_1.AST_NODE_TYPES.PropertyDefinition &&
|
|
154
|
+
node.decorators &&
|
|
155
|
+
node.decorators.length > 0
|
|
156
|
+
? node.decorators[0]
|
|
157
|
+
: node;
|
|
158
|
+
const indent = indentForNode(insertTarget);
|
|
159
|
+
const commentText = formatCommentWithIndent(comment, indent);
|
|
160
|
+
let removalStart = comment.range[0];
|
|
161
|
+
const removalEnd = comment.range[1];
|
|
162
|
+
const lineStart = insertTarget.range[0] - insertTarget.loc.start.column;
|
|
163
|
+
const textBeforeNode = sourceCode.text.slice(lineStart, insertTarget.range[0]);
|
|
164
|
+
const hasCodeBeforeNode = /\S/.test(textBeforeNode);
|
|
165
|
+
const insertionPoint = hasCodeBeforeNode
|
|
166
|
+
? insertTarget.range[0]
|
|
167
|
+
: lineStart;
|
|
168
|
+
const insertionText = hasCodeBeforeNode
|
|
169
|
+
? `\n${commentText}\n${indent}`
|
|
170
|
+
: `${commentText}\n`;
|
|
171
|
+
while (removalStart > node.range[1] &&
|
|
172
|
+
/\s/.test(sourceCode.text[removalStart - 1])) {
|
|
173
|
+
removalStart -= 1;
|
|
174
|
+
}
|
|
175
|
+
context.report({
|
|
176
|
+
node,
|
|
177
|
+
loc: comment.loc,
|
|
178
|
+
messageId: 'moveJsdocAbove',
|
|
179
|
+
data: {
|
|
180
|
+
name: getPropertyName(node),
|
|
181
|
+
kind: getKind(node),
|
|
182
|
+
},
|
|
183
|
+
fix(fixer) {
|
|
184
|
+
return [
|
|
185
|
+
fixer.insertTextBeforeRange([insertionPoint, insertionPoint], insertionText),
|
|
186
|
+
fixer.removeRange([removalStart, removalEnd]),
|
|
187
|
+
];
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
const checkNode = (node) => {
|
|
192
|
+
if (!isRelevantNode(node)) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const jsdocComment = inlineJSDocOnSameLine(node);
|
|
196
|
+
if (!jsdocComment) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
reportInlineJSDoc(node, jsdocComment);
|
|
200
|
+
};
|
|
201
|
+
return {
|
|
202
|
+
TSPropertySignature: checkNode,
|
|
203
|
+
PropertyDefinition: checkNode,
|
|
204
|
+
...(checkObjectLiterals && { Property: checkNode }),
|
|
205
|
+
};
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
//# sourceMappingURL=jsdoc-above-field.js.map
|
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.keyOnlyOutermostElement = void 0;
|
|
4
4
|
const createRule_1 = require("../utils/createRule");
|
|
5
|
+
const getJSXElementName = (name) => {
|
|
6
|
+
if (name.type === 'JSXIdentifier') {
|
|
7
|
+
return name.name;
|
|
8
|
+
}
|
|
9
|
+
if (name.type === 'JSXMemberExpression') {
|
|
10
|
+
const objectName = name.object.type === 'JSXIdentifier'
|
|
11
|
+
? name.object.name
|
|
12
|
+
: getJSXElementName(name.object);
|
|
13
|
+
return `${objectName}.${name.property.name}`;
|
|
14
|
+
}
|
|
15
|
+
if (name.type === 'JSXNamespacedName') {
|
|
16
|
+
return `${name.namespace.name}:${name.name.name}`;
|
|
17
|
+
}
|
|
18
|
+
return 'element';
|
|
19
|
+
};
|
|
5
20
|
exports.keyOnlyOutermostElement = (0, createRule_1.createRule)({
|
|
6
21
|
name: 'key-only-outermost-element',
|
|
7
22
|
meta: {
|
|
@@ -11,8 +26,8 @@ exports.keyOnlyOutermostElement = (0, createRule_1.createRule)({
|
|
|
11
26
|
recommended: 'error',
|
|
12
27
|
},
|
|
13
28
|
messages: {
|
|
14
|
-
keyOnlyOutermostElement: '
|
|
15
|
-
fragmentShouldHaveKey: '
|
|
29
|
+
keyOnlyOutermostElement: 'Nested element "{{elementName}}" has a key even though the list item already owns the identity. React reconciles list items using the key on the outermost element; nested keys create redundant identities and can mask ordering bugs. Remove this nested key and keep the key only on the element returned from map().',
|
|
30
|
+
fragmentShouldHaveKey: 'List items returned as fragments need a key on the fragment. Shorthand fragments (<></>) cannot accept keys, so React cannot track each item when the list reorders. Replace the shorthand with <React.Fragment key={...}> or another keyed wrapper so every list item has a stable identity.',
|
|
16
31
|
},
|
|
17
32
|
schema: [],
|
|
18
33
|
fixable: 'code',
|
|
@@ -104,10 +119,13 @@ exports.keyOnlyOutermostElement = (0, createRule_1.createRule)({
|
|
|
104
119
|
if (isNestedInMapCallback) {
|
|
105
120
|
// Mark this attribute as reported to avoid duplicate reports
|
|
106
121
|
reportedAttributes.add(attr);
|
|
107
|
-
const sourceCode = context.
|
|
122
|
+
const sourceCode = context.sourceCode;
|
|
108
123
|
context.report({
|
|
109
124
|
node: attr,
|
|
110
125
|
messageId: 'keyOnlyOutermostElement',
|
|
126
|
+
data: {
|
|
127
|
+
elementName: getJSXElementName(openingElement.name),
|
|
128
|
+
},
|
|
111
129
|
fix(fixer) {
|
|
112
130
|
// Find the exact range of the attribute in the source code
|
|
113
131
|
const startPos = attr.range[0];
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
type MessageIds = 'moveGuardUp' | 'groupDerived' | 'moveDeclarationCloser' | 'moveSideEffect';
|
|
3
|
+
type Options = [];
|
|
4
|
+
export declare const logicalTopToBottomGrouping: TSESLint.RuleModule<MessageIds, Options>;
|
|
5
|
+
export {};
|