eslint-plugin-ts-data-forge 0.6.0 → 0.7.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.
Files changed (77) hide show
  1. package/README.md +1 -0
  2. package/dist/index.mjs +2 -2
  3. package/dist/index.mjs.map +1 -1
  4. package/dist/plugin.d.mts +2 -0
  5. package/dist/plugin.d.mts.map +1 -1
  6. package/dist/plugin.mjs +45 -41
  7. package/dist/plugin.mjs.map +1 -1
  8. package/dist/rule-types.d.mts +15 -0
  9. package/dist/rule-types.d.mts.map +1 -1
  10. package/dist/rule-types.mjs +6 -2
  11. package/dist/rule-types.mjs.map +1 -1
  12. package/dist/rules/ast-utils.mjs +107 -50
  13. package/dist/rules/ast-utils.mjs.map +1 -1
  14. package/dist/rules/branded-number-types.mjs +41 -37
  15. package/dist/rules/branded-number-types.mjs.map +1 -1
  16. package/dist/rules/constants.mjs +2 -4
  17. package/dist/rules/constants.mjs.map +1 -1
  18. package/dist/rules/import-utils.mjs +80 -56
  19. package/dist/rules/import-utils.mjs.map +1 -1
  20. package/dist/rules/index.mjs +2 -2
  21. package/dist/rules/index.mjs.map +1 -1
  22. package/dist/rules/no-side-effect-import.mjs +46 -34
  23. package/dist/rules/no-side-effect-import.mjs.map +1 -1
  24. package/dist/rules/no-unnecessary-type-guard.mjs +376 -265
  25. package/dist/rules/no-unnecessary-type-guard.mjs.map +1 -1
  26. package/dist/rules/prefer-arr-is-array.mjs +64 -52
  27. package/dist/rules/prefer-arr-is-array.mjs.map +1 -1
  28. package/dist/rules/prefer-arr-is-bounded-length-array.mjs +91 -85
  29. package/dist/rules/prefer-arr-is-bounded-length-array.mjs.map +1 -1
  30. package/dist/rules/prefer-arr-is-fixed-length-array.mjs +92 -83
  31. package/dist/rules/prefer-arr-is-fixed-length-array.mjs.map +1 -1
  32. package/dist/rules/prefer-arr-is-max-length-array.mjs +92 -80
  33. package/dist/rules/prefer-arr-is-max-length-array.mjs.map +1 -1
  34. package/dist/rules/prefer-arr-is-min-length-array.mjs +92 -80
  35. package/dist/rules/prefer-arr-is-min-length-array.mjs.map +1 -1
  36. package/dist/rules/prefer-arr-is-non-empty.mjs +85 -77
  37. package/dist/rules/prefer-arr-is-non-empty.mjs.map +1 -1
  38. package/dist/rules/prefer-arr-scan.d.mts +96 -0
  39. package/dist/rules/prefer-arr-scan.d.mts.map +1 -0
  40. package/dist/rules/prefer-arr-scan.mjs +482 -0
  41. package/dist/rules/prefer-arr-scan.mjs.map +1 -0
  42. package/dist/rules/prefer-arr-sum.mjs +176 -132
  43. package/dist/rules/prefer-arr-sum.mjs.map +1 -1
  44. package/dist/rules/prefer-as-int.mjs +77 -71
  45. package/dist/rules/prefer-as-int.mjs.map +1 -1
  46. package/dist/rules/prefer-canonical-array-slicing.mjs +503 -343
  47. package/dist/rules/prefer-canonical-array-slicing.mjs.map +1 -1
  48. package/dist/rules/prefer-canonical-length-cast.mjs +217 -144
  49. package/dist/rules/prefer-canonical-length-cast.mjs.map +1 -1
  50. package/dist/rules/prefer-canonical-length-guard.mjs +160 -109
  51. package/dist/rules/prefer-canonical-length-guard.mjs.map +1 -1
  52. package/dist/rules/prefer-comparison-over-nullish-guard.mjs +89 -71
  53. package/dist/rules/prefer-comparison-over-nullish-guard.mjs.map +1 -1
  54. package/dist/rules/prefer-is-non-null-object.mjs +91 -72
  55. package/dist/rules/prefer-is-non-null-object.mjs.map +1 -1
  56. package/dist/rules/prefer-is-record-and-has-key.mjs +148 -105
  57. package/dist/rules/prefer-is-record-and-has-key.mjs.map +1 -1
  58. package/dist/rules/prefer-num-safe-parse-float.mjs +101 -77
  59. package/dist/rules/prefer-num-safe-parse-float.mjs.map +1 -1
  60. package/dist/rules/prefer-num-safe-parse-int.mjs +103 -81
  61. package/dist/rules/prefer-num-safe-parse-int.mjs.map +1 -1
  62. package/dist/rules/prefer-obj-over-entries-round-trip.mjs +299 -194
  63. package/dist/rules/prefer-obj-over-entries-round-trip.mjs.map +1 -1
  64. package/dist/rules/prefer-range-for-loop.mjs +121 -99
  65. package/dist/rules/prefer-range-for-loop.mjs.map +1 -1
  66. package/dist/rules/rules.d.mts +1 -0
  67. package/dist/rules/rules.d.mts.map +1 -1
  68. package/dist/rules/rules.mjs +19 -20
  69. package/dist/rules/rules.mjs.map +1 -1
  70. package/dist/types.mjs +2 -2
  71. package/dist/types.mjs.map +1 -1
  72. package/package.json +6 -7
  73. package/src/plugin.mts +1 -0
  74. package/src/rule-types.mts +16 -0
  75. package/src/rules/prefer-arr-scan.mts +693 -0
  76. package/src/rules/prefer-arr-scan.test.mts +295 -0
  77. package/src/rules/rules.mts +2 -0
@@ -1,81 +1,100 @@
1
- import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
- import { getTsDataForgeImport, getNamedImports, buildImportFixes } from './import-utils.mjs';
1
+ import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
2
+ import { buildImportFixes, getNamedImports, getTsDataForgeImport, } from './import-utils.mjs';
3
+ export const preferIsNonNullObject = {
4
+ meta: {
5
+ type: 'suggestion',
6
+ docs: {
7
+ description: 'Replace `typeof u === "object" && u !== null` with `isNonNullObject(u)` from ts-data-forge.',
8
+ },
9
+ fixable: 'code',
10
+ schema: [],
11
+ messages: {
12
+ useIsNonNullObject: 'Replace the object/null check with `isNonNullObject()` from ts-data-forge.',
13
+ },
14
+ },
15
+ create: (context) => {
16
+ const sourceCode = context.sourceCode;
17
+ const program = sourceCode.ast;
18
+ const tsDataForgeImport = getTsDataForgeImport(program);
19
+ const mut_nodesToFix = [];
20
+ return {
21
+ LogicalExpression: (node) => {
22
+ const identifierName = getNonNullObjectIdentifierName(node);
23
+ if (identifierName === undefined)
24
+ return;
25
+ mut_nodesToFix.push({ node, identifierName });
26
+ },
27
+ 'Program:exit': () => {
28
+
29
+ const hasIsNonNullObjectImport = getNamedImports(tsDataForgeImport).includes('isNonNullObject');
30
+
31
+
3
32
 
4
- const preferIsNonNullObject = {
5
- meta: {
6
- type: "suggestion",
7
- docs: {
8
- description: 'Replace `typeof u === "object" && u !== null` with `isNonNullObject(u)` from ts-data-forge.'
33
+
34
+ for (const [index, { node, identifierName },] of mut_nodesToFix.entries()) {
35
+ context.report({
36
+ node,
37
+ messageId: 'useIsNonNullObject',
38
+ fix: (fixer) => {
39
+ const replacement = `isNonNullObject(${identifierName})`;
40
+
41
+ const importFixes = index === 0 && !hasIsNonNullObjectImport
42
+ ? buildImportFixes(fixer, program, tsDataForgeImport, [
43
+ 'isNonNullObject',
44
+ ])
45
+ : [];
46
+ return [...importFixes, fixer.replaceText(node, replacement)];
47
+ },
48
+ });
49
+ }
50
+ },
51
+ };
9
52
  },
10
- fixable: "code",
11
- schema: [],
12
- messages: {
13
- useIsNonNullObject: "Replace the object/null check with `isNonNullObject()` from ts-data-forge."
14
- }
15
- },
16
- create: (context) => {
17
- const sourceCode = context.sourceCode;
18
- const program = sourceCode.ast;
19
- const tsDataForgeImport = getTsDataForgeImport(program);
20
- const mut_nodesToFix = [];
21
- return {
22
- LogicalExpression: (node) => {
23
- const identifierName = getNonNullObjectIdentifierName(node);
24
- if (identifierName === void 0) return;
25
- mut_nodesToFix.push({ node, identifierName });
26
- },
27
- "Program:exit": () => {
28
- const hasIsNonNullObjectImport = getNamedImports(tsDataForgeImport).includes("isNonNullObject");
29
- for (const [
30
- index,
31
- { node, identifierName }
32
- ] of mut_nodesToFix.entries()) {
33
- context.report({
34
- node,
35
- messageId: "useIsNonNullObject",
36
- fix: (fixer) => {
37
- const replacement = `isNonNullObject(${identifierName})`;
38
- const importFixes = index === 0 && !hasIsNonNullObjectImport ? buildImportFixes(fixer, program, tsDataForgeImport, [
39
- "isNonNullObject"
40
- ]) : [];
41
- return [...importFixes, fixer.replaceText(node, replacement)];
42
- }
43
- });
44
- }
45
- }
46
- };
47
- },
48
- defaultOptions: []
53
+ defaultOptions: [],
49
54
  };
50
55
  const getNonNullObjectIdentifierName = (node) => {
51
- if (node.operator !== "&&") return void 0;
52
- const leftIdentifierName = getTypeofObjectIdentifierName(node.left);
53
- const rightIdentifierName = getNonNullCheckIdentifierName(node.right);
54
- if (leftIdentifierName === void 0) return void 0;
55
- if (rightIdentifierName === void 0) return void 0;
56
- if (leftIdentifierName !== rightIdentifierName) return void 0;
57
- return leftIdentifierName;
56
+ if (node.operator !== '&&')
57
+ return undefined;
58
+ const leftIdentifierName = getTypeofObjectIdentifierName(node.left);
59
+ const rightIdentifierName = getNonNullCheckIdentifierName(node.right);
60
+ if (leftIdentifierName === undefined)
61
+ return undefined;
62
+ if (rightIdentifierName === undefined)
63
+ return undefined;
64
+ if (leftIdentifierName !== rightIdentifierName)
65
+ return undefined;
66
+ return leftIdentifierName;
58
67
  };
59
68
  const getTypeofObjectIdentifierName = (node) => {
60
- if (node.type !== AST_NODE_TYPES.BinaryExpression) return void 0;
61
- if (node.operator !== "===") return void 0;
62
- const { left, right } = node;
63
- if (left.type !== AST_NODE_TYPES.UnaryExpression) return void 0;
64
- if (left.operator !== "typeof") return void 0;
65
- if (right.type !== AST_NODE_TYPES.Literal) return void 0;
66
- if (right.value !== "object") return void 0;
67
- if (left.argument.type !== AST_NODE_TYPES.Identifier) return void 0;
68
- return left.argument.name;
69
+ if (node.type !== AST_NODE_TYPES.BinaryExpression)
70
+ return undefined;
71
+ if (node.operator !== '===')
72
+ return undefined;
73
+ const { left, right } = node;
74
+ if (left.type !== AST_NODE_TYPES.UnaryExpression)
75
+ return undefined;
76
+ if (left.operator !== 'typeof')
77
+ return undefined;
78
+ if (right.type !== AST_NODE_TYPES.Literal)
79
+ return undefined;
80
+ if (right.value !== 'object')
81
+ return undefined;
82
+ if (left.argument.type !== AST_NODE_TYPES.Identifier)
83
+ return undefined;
84
+ return left.argument.name;
69
85
  };
70
86
  const getNonNullCheckIdentifierName = (node) => {
71
- if (node.type !== AST_NODE_TYPES.BinaryExpression) return void 0;
72
- if (node.operator !== "!==") return void 0;
73
- const { left, right } = node;
74
- if (left.type !== AST_NODE_TYPES.Identifier) return void 0;
75
- if (right.type !== AST_NODE_TYPES.Literal) return void 0;
76
- if (right.value !== null) return void 0;
77
- return left.name;
87
+ if (node.type !== AST_NODE_TYPES.BinaryExpression)
88
+ return undefined;
89
+ if (node.operator !== '!==')
90
+ return undefined;
91
+ const { left, right } = node;
92
+ if (left.type !== AST_NODE_TYPES.Identifier)
93
+ return undefined;
94
+ if (right.type !== AST_NODE_TYPES.Literal)
95
+ return undefined;
96
+ if (right.value !== null)
97
+ return undefined;
98
+ return left.name;
78
99
  };
79
-
80
- export { preferIsNonNullObject };
81
- //# sourceMappingURL=prefer-is-non-null-object.mjs.map
100
+ //# sourceMappingURL=prefer-is-non-null-object.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-is-non-null-object.mjs","sources":["../../src/rules/prefer-is-non-null-object.mts"],"sourcesContent":["import {\n AST_NODE_TYPES,\n type TSESLint,\n type TSESTree,\n} from '@typescript-eslint/utils';\nimport { type DeepReadonly } from 'ts-type-forge';\nimport {\n buildImportFixes,\n getNamedImports,\n getTsDataForgeImport,\n} from './import-utils.mjs';\n\ntype Options = readonly [];\n\ntype MessageIds = 'useIsNonNullObject';\n\nexport const preferIsNonNullObject: TSESLint.RuleModule<MessageIds, Options> = {\n meta: {\n type: 'suggestion',\n docs: {\n description:\n 'Replace `typeof u === \"object\" && u !== null` with `isNonNullObject(u)` from ts-data-forge.',\n },\n fixable: 'code',\n schema: [],\n messages: {\n useIsNonNullObject:\n 'Replace the object/null check with `isNonNullObject()` from ts-data-forge.',\n },\n },\n\n create: (context) => {\n const sourceCode = context.sourceCode;\n\n const program = sourceCode.ast;\n\n const tsDataForgeImport = getTsDataForgeImport(program);\n\n const mut_nodesToFix: {\n node: TSESTree.LogicalExpression;\n identifierName: string;\n }[] = [];\n\n return {\n LogicalExpression: (node) => {\n const identifierName = getNonNullObjectIdentifierName(node);\n\n if (identifierName === undefined) return;\n\n mut_nodesToFix.push({ node, identifierName });\n },\n 'Program:exit': () => {\n // Check if isNonNullObject is already imported\n const hasIsNonNullObjectImport =\n getNamedImports(tsDataForgeImport).includes('isNonNullObject');\n\n // Note: We add import only for the first node to avoid conflicts when\n // multiple fixes try to insert at the same position. This means if the\n // first node is disabled via eslint-disable comment, no import will be\n // added.\n for (const [\n index,\n { node, identifierName },\n ] of mut_nodesToFix.entries()) {\n context.report({\n node,\n messageId: 'useIsNonNullObject',\n fix: (fixer) => {\n const replacement = `isNonNullObject(${identifierName})`;\n\n // Add import only for the first node and only if not already imported\n const importFixes =\n index === 0 && !hasIsNonNullObjectImport\n ? buildImportFixes(fixer, program, tsDataForgeImport, [\n 'isNonNullObject',\n ])\n : [];\n\n return [...importFixes, fixer.replaceText(node, replacement)];\n },\n });\n }\n },\n };\n },\n defaultOptions: [],\n} as const;\n\nconst getNonNullObjectIdentifierName = (\n node: DeepReadonly<TSESTree.LogicalExpression>,\n): string | undefined => {\n if (node.operator !== '&&') return undefined;\n\n const leftIdentifierName = getTypeofObjectIdentifierName(node.left);\n\n const rightIdentifierName = getNonNullCheckIdentifierName(node.right);\n\n if (leftIdentifierName === undefined) return undefined;\n\n if (rightIdentifierName === undefined) return undefined;\n\n if (leftIdentifierName !== rightIdentifierName) return undefined;\n\n return leftIdentifierName;\n};\n\nconst getTypeofObjectIdentifierName = (\n node: DeepReadonly<TSESTree.Expression>,\n): string | undefined => {\n if (node.type !== AST_NODE_TYPES.BinaryExpression) return undefined;\n\n if (node.operator !== '===') return undefined;\n\n const { left, right } = node;\n\n if (left.type !== AST_NODE_TYPES.UnaryExpression) return undefined;\n\n if (left.operator !== 'typeof') return undefined;\n\n if (right.type !== AST_NODE_TYPES.Literal) return undefined;\n\n if (right.value !== 'object') return undefined;\n\n if (left.argument.type !== AST_NODE_TYPES.Identifier) return undefined;\n\n return left.argument.name;\n};\n\nconst getNonNullCheckIdentifierName = (\n node: DeepReadonly<TSESTree.Expression>,\n): string | undefined => {\n if (node.type !== AST_NODE_TYPES.BinaryExpression) return undefined;\n\n if (node.operator !== '!==') return undefined;\n\n const { left, right } = node;\n\n if (left.type !== AST_NODE_TYPES.Identifier) return undefined;\n\n if (right.type !== AST_NODE_TYPES.Literal) return undefined;\n\n if (right.value !== null) return undefined;\n\n return left.name;\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prefer-is-non-null-object.mjs","sourceRoot":"","sources":["../../src/rules/prefer-is-non-null-object.mts"],"names":[],"mappings":"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"}
@@ -1,111 +1,154 @@
1
- import { AST_NODE_TYPES } from '@typescript-eslint/utils';
1
+ import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
2
2
  import { Arr } from 'ts-data-forge';
3
3
  import * as ts from 'typescript';
4
- import { getTsDataForgeImport, getNamedImports, buildImportFixes } from './import-utils.mjs';
5
-
6
- const preferIsRecordAndHasKey = {
7
- meta: {
8
- type: "suggestion",
9
- docs: {
10
- description: "Replace `Object.hasOwn(obj, key)` or `key in obj` with `isRecord(obj) && hasKey(obj, key)` from ts-data-forge"
4
+ import { buildImportFixes, getNamedImports, getTsDataForgeImport, } from './import-utils.mjs';
5
+ export const preferIsRecordAndHasKey = {
6
+ meta: {
7
+ type: 'suggestion',
8
+ docs: {
9
+ description: 'Replace `Object.hasOwn(obj, key)` or `key in obj` with `isRecord(obj) && hasKey(obj, key)` from ts-data-forge',
10
+ },
11
+ fixable: 'code',
12
+ schema: [],
13
+ messages: {
14
+ useIsRecordAndHasKey: 'Replace `{{original}}` with `isRecord({{objName}}) && hasKey({{objName}}, {{keyName}})` from ts-data-forge.',
15
+ useHasKey: 'Replace `{{original}}` with `hasKey({{objName}}, {{keyName}})` from ts-data-forge.',
16
+ },
11
17
  },
12
- fixable: "code",
13
- schema: [],
14
- messages: {
15
- useIsRecordAndHasKey: "Replace `{{original}}` with `isRecord({{objName}}) && hasKey({{objName}}, {{keyName}})` from ts-data-forge.",
16
- useHasKey: "Replace `{{original}}` with `hasKey({{objName}}, {{keyName}})` from ts-data-forge."
17
- }
18
- },
19
- create: (context) => {
20
- const sourceCode = context.sourceCode;
21
- const program = sourceCode.ast;
22
- const tsDataForgeImport = getTsDataForgeImport(program);
23
- const services = sourceCode.parserServices;
24
- const checker = services?.program?.getTypeChecker();
25
- const isKnownRecord = (expression) => {
26
- if (checker === void 0) return false;
27
- const tsNode = services?.esTreeNodeToTSNodeMap?.get(expression);
28
- return tsNode !== void 0 && isAlreadyRecordType(checker, checker.getTypeAtLocation(tsNode));
29
- };
30
- const mut_nodesToFix = [];
31
- return {
32
- // Handle Object.hasOwn(obj, key)
33
- CallExpression: (node) => {
34
- if (node.callee.type !== AST_NODE_TYPES.MemberExpression || node.callee.object.type !== AST_NODE_TYPES.Identifier || node.callee.object.name !== "Object" || node.callee.property.type !== AST_NODE_TYPES.Identifier || node.callee.property.name !== "hasOwn") {
35
- return;
36
- }
37
- if (node.arguments.length !== 2) return;
38
- const objArg = node.arguments[0];
39
- const keyArg = node.arguments[1];
40
- if (objArg === void 0 || keyArg === void 0) return;
41
- if (objArg.type === AST_NODE_TYPES.SpreadElement || keyArg.type === AST_NODE_TYPES.SpreadElement) {
42
- return;
43
- }
44
- mut_nodesToFix.push({
45
- node,
46
- objExpression: objArg,
47
- keyExpression: keyArg
48
- });
49
- },
50
- // Handle key in obj
51
- BinaryExpression: (node) => {
52
- if (node.operator !== "in") return;
53
- const keyExpression = node.left;
54
- const objExpression = node.right;
55
- if (keyExpression.type === AST_NODE_TYPES.PrivateIdentifier) return;
56
- mut_nodesToFix.push({
57
- node,
58
- objExpression,
59
- keyExpression
60
- });
61
- },
62
- "Program:exit": () => {
63
- const namedImports = getNamedImports(tsDataForgeImport);
64
- const rewrites = mut_nodesToFix.map((entry) => ({
65
- ...entry,
66
- // A record-typed object makes the `isRecord(...)` conjunct always
67
- // true, so it is left out of the replacement entirely.
68
- needsIsRecord: !isKnownRecord(entry.objExpression)
69
- }));
70
- const importsToAdd = [
71
- ...rewrites.some(({ needsIsRecord }) => needsIsRecord) && !namedImports.includes("isRecord") ? ["isRecord"] : [],
72
- ...namedImports.includes("hasKey") ? [] : ["hasKey"]
73
- ];
74
- for (const [
75
- index,
76
- { node, objExpression, keyExpression, needsIsRecord }
77
- ] of rewrites.entries()) {
78
- const objText = sourceCode.getText(objExpression);
79
- const keyText = sourceCode.getText(keyExpression);
80
- const originalText = sourceCode.getText(node);
81
- context.report({
82
- node,
83
- messageId: needsIsRecord ? "useIsRecordAndHasKey" : "useHasKey",
84
- data: {
85
- original: originalText,
86
- objName: objText,
87
- keyName: keyText
18
+ create: (context) => {
19
+ const sourceCode = context.sourceCode;
20
+ const program = sourceCode.ast;
21
+ const tsDataForgeImport = getTsDataForgeImport(program);
22
+ const services = sourceCode.parserServices;
23
+ const checker = services?.program?.getTypeChecker();
24
+
25
+
26
+
27
+
28
+
29
+
30
+ const isKnownRecord = (
31
+
32
+ expression) => {
33
+ if (checker === undefined)
34
+ return false;
35
+ const tsNode = services?.esTreeNodeToTSNodeMap?.get(expression);
36
+ return (tsNode !== undefined &&
37
+ isAlreadyRecordType(checker, checker.getTypeAtLocation(tsNode)));
38
+ };
39
+ const mut_nodesToFix = [];
40
+ return {
41
+
42
+ CallExpression: (node) => {
43
+ if (node.callee.type !== AST_NODE_TYPES.MemberExpression ||
44
+ node.callee.object.type !== AST_NODE_TYPES.Identifier ||
45
+ node.callee.object.name !== 'Object' ||
46
+ node.callee.property.type !== AST_NODE_TYPES.Identifier ||
47
+ node.callee.property.name !== 'hasOwn') {
48
+ return;
49
+ }
50
+
51
+ if (node.arguments.length !== 2)
52
+ return;
53
+ const objArg = node.arguments[0];
54
+ const keyArg = node.arguments[1];
55
+ if (objArg === undefined || keyArg === undefined)
56
+ return;
57
+
58
+ if (objArg.type === AST_NODE_TYPES.SpreadElement ||
59
+ keyArg.type === AST_NODE_TYPES.SpreadElement) {
60
+ return;
61
+ }
62
+ mut_nodesToFix.push({
63
+ node,
64
+ objExpression: objArg,
65
+ keyExpression: keyArg,
66
+ });
67
+ },
68
+
69
+ BinaryExpression: (node) => {
70
+ if (node.operator !== 'in')
71
+ return;
72
+ const keyExpression = node.left;
73
+ const objExpression = node.right;
74
+
75
+ if (keyExpression.type === AST_NODE_TYPES.PrivateIdentifier)
76
+ return;
77
+ mut_nodesToFix.push({
78
+ node,
79
+ objExpression,
80
+ keyExpression,
81
+ });
82
+ },
83
+ 'Program:exit': () => {
84
+ const namedImports = getNamedImports(tsDataForgeImport);
85
+ const rewrites = mut_nodesToFix.map((entry) => ({
86
+ ...entry,
87
+
88
+
89
+ needsIsRecord: !isKnownRecord(entry.objExpression),
90
+ }));
91
+ const importsToAdd = [
92
+ ...(rewrites.some(({ needsIsRecord }) => needsIsRecord) &&
93
+ !namedImports.includes('isRecord')
94
+ ? ['isRecord']
95
+ : []),
96
+ ...(namedImports.includes('hasKey') ? [] : ['hasKey']),
97
+ ];
98
+ for (const [index, { node, objExpression, keyExpression, needsIsRecord },] of rewrites.entries()) {
99
+ const objText = sourceCode.getText(objExpression);
100
+ const keyText = sourceCode.getText(keyExpression);
101
+ const originalText = sourceCode.getText(node);
102
+ context.report({
103
+ node,
104
+ messageId: needsIsRecord ? 'useIsRecordAndHasKey' : 'useHasKey',
105
+ data: {
106
+ original: originalText,
107
+ objName: objText,
108
+ keyName: keyText,
109
+ },
110
+ fix: (fixer) => {
111
+ const replacement = needsIsRecord
112
+ ? `(isRecord(${objText}) && hasKey(${objText}, ${keyText}))`
113
+ : `hasKey(${objText}, ${keyText})`;
114
+
115
+
116
+
117
+ const importFixes = index === 0 && importsToAdd.length > 0
118
+ ? buildImportFixes(fixer, program, tsDataForgeImport, importsToAdd)
119
+ : [];
120
+ return [...importFixes, fixer.replaceText(node, replacement)];
121
+ },
122
+ });
123
+ }
88
124
  },
89
- fix: (fixer) => {
90
- const replacement = needsIsRecord ? `(isRecord(${objText}) && hasKey(${objText}, ${keyText}))` : `hasKey(${objText}, ${keyText})`;
91
- const importFixes = index === 0 && importsToAdd.length > 0 ? buildImportFixes(
92
- fixer,
93
- program,
94
- tsDataForgeImport,
95
- importsToAdd
96
- ) : [];
97
- return [...importFixes, fixer.replaceText(node, replacement)];
98
- }
99
- });
100
- }
101
- }
102
- };
103
- },
104
- defaultOptions: []
125
+ };
126
+ },
127
+ defaultOptions: [],
105
128
  };
106
- const isAlreadyRecordType = (checker, type) => type.isUnion() ? type.types.every((member) => isAlreadyRecordType(checker, member)) : checker.getIndexInfoOfType(type, ts.IndexKind.String) !== void 0 && Arr.isEmpty(checker.getSignaturesOfType(type, ts.SignatureKind.Call)) && Arr.isEmpty(
107
- checker.getSignaturesOfType(type, ts.SignatureKind.Construct)
108
- ) && !checker.isArrayType(type) && !checker.isTupleType(type);
109
129
 
110
- export { preferIsRecordAndHasKey };
111
- //# sourceMappingURL=prefer-is-record-and-has-key.mjs.map
130
+
131
+
132
+
133
+
134
+
135
+
136
+
137
+
138
+
139
+
140
+
141
+
142
+
143
+ const isAlreadyRecordType = (
144
+
145
+ checker,
146
+
147
+ type) => type.isUnion()
148
+ ? type.types.every((member) => isAlreadyRecordType(checker, member))
149
+ : checker.getIndexInfoOfType(type, ts.IndexKind.String) !== undefined &&
150
+ Arr.isEmpty(checker.getSignaturesOfType(type, ts.SignatureKind.Call)) &&
151
+ Arr.isEmpty(checker.getSignaturesOfType(type, ts.SignatureKind.Construct)) &&
152
+ !checker.isArrayType(type) &&
153
+ !checker.isTupleType(type);
154
+ //# sourceMappingURL=prefer-is-record-and-has-key.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-is-record-and-has-key.mjs","sources":["../../src/rules/prefer-is-record-and-has-key.mts"],"sourcesContent":["import {\n AST_NODE_TYPES,\n type TSESLint,\n type TSESTree,\n} from '@typescript-eslint/utils';\nimport { Arr } from 'ts-data-forge';\nimport * as ts from 'typescript';\nimport {\n buildImportFixes,\n getNamedImports,\n getTsDataForgeImport,\n} from './import-utils.mjs';\n\ntype Options = readonly [];\n\ntype MessageIds = 'useIsRecordAndHasKey' | 'useHasKey';\n\nexport const preferIsRecordAndHasKey: TSESLint.RuleModule<MessageIds, Options> =\n {\n meta: {\n type: 'suggestion',\n docs: {\n description:\n 'Replace `Object.hasOwn(obj, key)` or `key in obj` with `isRecord(obj) && hasKey(obj, key)` from ts-data-forge',\n },\n fixable: 'code',\n schema: [],\n messages: {\n useIsRecordAndHasKey:\n 'Replace `{{original}}` with `isRecord({{objName}}) && hasKey({{objName}}, {{keyName}})` from ts-data-forge.',\n useHasKey:\n 'Replace `{{original}}` with `hasKey({{objName}}, {{keyName}})` from ts-data-forge.',\n },\n },\n\n create: (context) => {\n const sourceCode = context.sourceCode;\n\n const program = sourceCode.ast;\n\n const tsDataForgeImport = getTsDataForgeImport(program);\n\n const services = sourceCode.parserServices;\n\n const checker = services?.program?.getTypeChecker();\n\n /**\n * Whether the `isRecord(...)` half of the rewrite would be dead code\n * because the object already satisfies `hasKey`'s\n * `R extends UnknownRecord` constraint. Without type information nothing\n * is known, so the guard is kept.\n */\n const isKnownRecord = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n expression: TSESTree.Expression,\n ): boolean => {\n if (checker === undefined) return false;\n\n const tsNode = services?.esTreeNodeToTSNodeMap?.get(expression);\n\n return (\n tsNode !== undefined &&\n isAlreadyRecordType(checker, checker.getTypeAtLocation(tsNode))\n );\n };\n\n const mut_nodesToFix: {\n node: TSESTree.CallExpression | TSESTree.BinaryExpression;\n objExpression: TSESTree.Expression;\n keyExpression: TSESTree.Expression;\n }[] = [];\n\n return {\n // Handle Object.hasOwn(obj, key)\n CallExpression: (node) => {\n if (\n node.callee.type !== AST_NODE_TYPES.MemberExpression ||\n node.callee.object.type !== AST_NODE_TYPES.Identifier ||\n node.callee.object.name !== 'Object' ||\n node.callee.property.type !== AST_NODE_TYPES.Identifier ||\n node.callee.property.name !== 'hasOwn'\n ) {\n return;\n }\n\n // Check arguments: Object.hasOwn(obj, key)\n if (node.arguments.length !== 2) return;\n\n const objArg = node.arguments[0];\n\n const keyArg = node.arguments[1];\n\n if (objArg === undefined || keyArg === undefined) return;\n\n // Type guard: ensure arguments are Expressions (not SpreadElement)\n if (\n objArg.type === AST_NODE_TYPES.SpreadElement ||\n keyArg.type === AST_NODE_TYPES.SpreadElement\n ) {\n return;\n }\n\n mut_nodesToFix.push({\n node,\n objExpression: objArg,\n keyExpression: keyArg,\n });\n },\n\n // Handle key in obj\n BinaryExpression: (node) => {\n if (node.operator !== 'in') return;\n\n const keyExpression = node.left;\n\n const objExpression = node.right;\n\n // Type guard: ensure keyExpression is Expression (not PrivateIdentifier)\n if (keyExpression.type === AST_NODE_TYPES.PrivateIdentifier) return;\n\n mut_nodesToFix.push({\n node,\n objExpression,\n keyExpression,\n });\n },\n\n 'Program:exit': () => {\n const namedImports = getNamedImports(tsDataForgeImport);\n\n const rewrites = mut_nodesToFix.map((entry) => ({\n ...entry,\n // A record-typed object makes the `isRecord(...)` conjunct always\n // true, so it is left out of the replacement entirely.\n needsIsRecord: !isKnownRecord(entry.objExpression),\n }));\n\n const importsToAdd: readonly string[] = [\n ...(rewrites.some(({ needsIsRecord }) => needsIsRecord) &&\n !namedImports.includes('isRecord')\n ? ['isRecord']\n : []),\n ...(namedImports.includes('hasKey') ? [] : ['hasKey']),\n ];\n\n for (const [\n index,\n { node, objExpression, keyExpression, needsIsRecord },\n ] of rewrites.entries()) {\n const objText = sourceCode.getText(objExpression);\n\n const keyText = sourceCode.getText(keyExpression);\n\n const originalText = sourceCode.getText(node);\n\n context.report({\n node,\n messageId: needsIsRecord ? 'useIsRecordAndHasKey' : 'useHasKey',\n data: {\n original: originalText,\n objName: objText,\n keyName: keyText,\n },\n fix: (fixer) => {\n const replacement = needsIsRecord\n ? `(isRecord(${objText}) && hasKey(${objText}, ${keyText}))`\n : `hasKey(${objText}, ${keyText})`;\n\n // All import fixes have to live on the first report:\n // `insertTextBefore(program, …)` produces overlapping ranges\n // otherwise and only one of them would survive a pass.\n const importFixes =\n index === 0 && importsToAdd.length > 0\n ? buildImportFixes(\n fixer,\n program,\n tsDataForgeImport,\n importsToAdd,\n )\n : [];\n\n return [...importFixes, fixer.replaceText(node, replacement)];\n },\n });\n }\n },\n };\n },\n defaultOptions: [],\n } as const;\n\n/**\n * Whether `type` already satisfies `hasKey`'s `R extends UnknownRecord`\n * constraint, so that guarding the call with `isRecord` adds nothing.\n *\n * `UnknownRecord` is `ReadonlyRecord<string, unknown>`, so a string index\n * signature is exactly what it asks for and its value type is `unknown`, which\n * anything satisfies. Callables and arrays are excluded because `isRecord`\n * rejects them at runtime (`typeof fn === 'object'` is false, `Array.isArray`\n * is true), so dropping the guard there would change behavior.\n *\n * Deliberately conservative: a type TypeScript would accept through an\n * *implicit* index signature (an object type alias without one of its own)\n * keeps the guard, because the checker does not report such a signature here.\n */\nconst isAlreadyRecordType = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n checker: ts.TypeChecker,\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n type: ts.Type,\n): boolean =>\n type.isUnion()\n ? type.types.every((member) => isAlreadyRecordType(checker, member))\n : checker.getIndexInfoOfType(type, ts.IndexKind.String) !== undefined &&\n Arr.isEmpty(checker.getSignaturesOfType(type, ts.SignatureKind.Call)) &&\n Arr.isEmpty(\n checker.getSignaturesOfType(type, ts.SignatureKind.Construct),\n ) &&\n !checker.isArrayType(type) &&\n !checker.isTupleType(type);\n"],"names":[],"mappings":";;;;;AAiBO,MAAM,uBAAA,GACX;AAAA,EACE,IAAA,EAAM;AAAA,IACJ,IAAA,EAAM,YAAA;AAAA,IACN,IAAA,EAAM;AAAA,MACJ,WAAA,EACE;AAAA,KACJ;AAAA,IACA,OAAA,EAAS,MAAA;AAAA,IACT,QAAQ,EAAC;AAAA,IACT,QAAA,EAAU;AAAA,MACR,oBAAA,EACE,6GAAA;AAAA,MACF,SAAA,EACE;AAAA;AACJ,GACF;AAAA,EAEA,MAAA,EAAQ,CAAC,OAAA,KAAY;AACnB,IAAA,MAAM,aAAa,OAAA,CAAQ,UAAA;AAE3B,IAAA,MAAM,UAAU,UAAA,CAAW,GAAA;AAE3B,IAAA,MAAM,iBAAA,GAAoB,qBAAqB,OAAO,CAAA;AAEtD,IAAA,MAAM,WAAW,UAAA,CAAW,cAAA;AAE5B,IAAA,MAAM,OAAA,GAAU,QAAA,EAAU,OAAA,EAAS,cAAA,EAAe;AAQlD,IAAA,MAAM,aAAA,GAAgB,CAEpB,UAAA,KACY;AACZ,MAAA,IAAI,OAAA,KAAY,QAAW,OAAO,KAAA;AAElC,MAAA,MAAM,MAAA,GAAS,QAAA,EAAU,qBAAA,EAAuB,GAAA,CAAI,UAAU,CAAA;AAE9D,MAAA,OACE,WAAW,MAAA,IACX,mBAAA,CAAoB,SAAS,OAAA,CAAQ,iBAAA,CAAkB,MAAM,CAAC,CAAA;AAAA,IAElE,CAAA;AAEA,IAAA,MAAM,iBAIA,EAAC;AAEP,IAAA,OAAO;AAAA;AAAA,MAEL,cAAA,EAAgB,CAAC,IAAA,KAAS;AACxB,QAAA,IACE,IAAA,CAAK,MAAA,CAAO,IAAA,KAAS,cAAA,CAAe,gBAAA,IACpC,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,IAAA,KAAS,cAAA,CAAe,UAAA,IAC3C,IAAA,CAAK,MAAA,CAAO,OAAO,IAAA,KAAS,QAAA,IAC5B,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,IAAA,KAAS,cAAA,CAAe,UAAA,IAC7C,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,IAAA,KAAS,QAAA,EAC9B;AACA,UAAA;AAAA,QACF;AAGA,QAAA,IAAI,IAAA,CAAK,SAAA,CAAU,MAAA,KAAW,CAAA,EAAG;AAEjC,QAAA,MAAM,MAAA,GAAS,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA;AAE/B,QAAA,MAAM,MAAA,GAAS,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA;AAE/B,QAAA,IAAI,MAAA,KAAW,MAAA,IAAa,MAAA,KAAW,MAAA,EAAW;AAGlD,QAAA,IACE,OAAO,IAAA,KAAS,cAAA,CAAe,iBAC/B,MAAA,CAAO,IAAA,KAAS,eAAe,aAAA,EAC/B;AACA,UAAA;AAAA,QACF;AAEA,QAAA,cAAA,CAAe,IAAA,CAAK;AAAA,UAClB,IAAA;AAAA,UACA,aAAA,EAAe,MAAA;AAAA,UACf,aAAA,EAAe;AAAA,SAChB,CAAA;AAAA,MACH,CAAA;AAAA;AAAA,MAGA,gBAAA,EAAkB,CAAC,IAAA,KAAS;AAC1B,QAAA,IAAI,IAAA,CAAK,aAAa,IAAA,EAAM;AAE5B,QAAA,MAAM,gBAAgB,IAAA,CAAK,IAAA;AAE3B,QAAA,MAAM,gBAAgB,IAAA,CAAK,KAAA;AAG3B,QAAA,IAAI,aAAA,CAAc,IAAA,KAAS,cAAA,CAAe,iBAAA,EAAmB;AAE7D,QAAA,cAAA,CAAe,IAAA,CAAK;AAAA,UAClB,IAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA,SACD,CAAA;AAAA,MACH,CAAA;AAAA,MAEA,gBAAgB,MAAM;AACpB,QAAA,MAAM,YAAA,GAAe,gBAAgB,iBAAiB,CAAA;AAEtD,QAAA,MAAM,QAAA,GAAW,cAAA,CAAe,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,UAC9C,GAAG,KAAA;AAAA;AAAA;AAAA,UAGH,aAAA,EAAe,CAAC,aAAA,CAAc,KAAA,CAAM,aAAa;AAAA,SACnD,CAAE,CAAA;AAEF,QAAA,MAAM,YAAA,GAAkC;AAAA,UACtC,GAAI,QAAA,CAAS,IAAA,CAAK,CAAC,EAAE,eAAc,KAAM,aAAa,CAAA,IACtD,CAAC,aAAa,QAAA,CAAS,UAAU,IAC7B,CAAC,UAAU,IACX,EAAC;AAAA,UACL,GAAI,aAAa,QAAA,CAAS,QAAQ,IAAI,EAAC,GAAI,CAAC,QAAQ;AAAA,SACtD;AAEA,QAAA,KAAA,MAAW;AAAA,UACT,KAAA;AAAA,UACA,EAAE,IAAA,EAAM,aAAA,EAAe,aAAA,EAAe,aAAA;AAAc,SACtD,IAAK,QAAA,CAAS,OAAA,EAAQ,EAAG;AACvB,UAAA,MAAM,OAAA,GAAU,UAAA,CAAW,OAAA,CAAQ,aAAa,CAAA;AAEhD,UAAA,MAAM,OAAA,GAAU,UAAA,CAAW,OAAA,CAAQ,aAAa,CAAA;AAEhD,UAAA,MAAM,YAAA,GAAe,UAAA,CAAW,OAAA,CAAQ,IAAI,CAAA;AAE5C,UAAA,OAAA,CAAQ,MAAA,CAAO;AAAA,YACb,IAAA;AAAA,YACA,SAAA,EAAW,gBAAgB,sBAAA,GAAyB,WAAA;AAAA,YACpD,IAAA,EAAM;AAAA,cACJ,QAAA,EAAU,YAAA;AAAA,cACV,OAAA,EAAS,OAAA;AAAA,cACT,OAAA,EAAS;AAAA,aACX;AAAA,YACA,GAAA,EAAK,CAAC,KAAA,KAAU;AACd,cAAA,MAAM,WAAA,GAAc,aAAA,GAChB,CAAA,UAAA,EAAa,OAAO,CAAA,YAAA,EAAe,OAAO,CAAA,EAAA,EAAK,OAAO,CAAA,EAAA,CAAA,GACtD,CAAA,OAAA,EAAU,OAAO,CAAA,EAAA,EAAK,OAAO,CAAA,CAAA,CAAA;AAKjC,cAAA,MAAM,WAAA,GACJ,KAAA,KAAU,CAAA,IAAK,YAAA,CAAa,SAAS,CAAA,GACjC,gBAAA;AAAA,gBACE,KAAA;AAAA,gBACA,OAAA;AAAA,gBACA,iBAAA;AAAA,gBACA;AAAA,kBAEF,EAAC;AAEP,cAAA,OAAO,CAAC,GAAG,WAAA,EAAa,MAAM,WAAA,CAAY,IAAA,EAAM,WAAW,CAAC,CAAA;AAAA,YAC9D;AAAA,WACD,CAAA;AAAA,QACH;AAAA,MACF;AAAA,KACF;AAAA,EACF,CAAA;AAAA,EACA,gBAAgB;AAClB;AAgBF,MAAM,mBAAA,GAAsB,CAE1B,OAAA,EAEA,IAAA,KAEA,KAAK,OAAA,EAAQ,GACT,IAAA,CAAK,KAAA,CAAM,MAAM,CAAC,MAAA,KAAW,mBAAA,CAAoB,OAAA,EAAS,MAAM,CAAC,CAAA,GACjE,OAAA,CAAQ,kBAAA,CAAmB,MAAM,EAAA,CAAG,SAAA,CAAU,MAAM,CAAA,KAAM,UAC1D,GAAA,CAAI,OAAA,CAAQ,OAAA,CAAQ,mBAAA,CAAoB,MAAM,EAAA,CAAG,aAAA,CAAc,IAAI,CAAC,KACpE,GAAA,CAAI,OAAA;AAAA,EACF,OAAA,CAAQ,mBAAA,CAAoB,IAAA,EAAM,EAAA,CAAG,cAAc,SAAS;AAC9D,CAAA,IACA,CAAC,QAAQ,WAAA,CAAY,IAAI,KACzB,CAAC,OAAA,CAAQ,YAAY,IAAI,CAAA;;"}
1
+ {"version":3,"file":"prefer-is-record-and-has-key.mjs","sourceRoot":"","sources":["../../src/rules/prefer-is-record-and-has-key.mts"],"names":[],"mappings":"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"}