eslint-plugin-ts-std-forge 0.1.3 → 0.1.5

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 (54) hide show
  1. package/dist/plugin.d.mts +1 -1
  2. package/dist/plugin.d.mts.map +1 -1
  3. package/dist/plugin.mjs +1 -0
  4. package/dist/plugin.mjs.map +1 -1
  5. package/dist/rule-types.d.mts +1 -1
  6. package/dist/rule-types.d.mts.map +1 -1
  7. package/dist/rules/ast-utils.d.mts +41 -0
  8. package/dist/rules/ast-utils.d.mts.map +1 -0
  9. package/dist/rules/ast-utils.mjs +101 -0
  10. package/dist/rules/ast-utils.mjs.map +1 -0
  11. package/dist/rules/import-utils.d.mts +1 -1
  12. package/dist/rules/import-utils.d.mts.map +1 -1
  13. package/dist/rules/import-utils.mjs +2 -1
  14. package/dist/rules/import-utils.mjs.map +1 -1
  15. package/dist/rules/prefer-is-non-null-object.d.mts.map +1 -1
  16. package/dist/rules/prefer-is-non-null-object.mjs +55 -43
  17. package/dist/rules/prefer-is-non-null-object.mjs.map +1 -1
  18. package/dist/rules/prefer-is-record-and-has-key.d.mts.map +1 -1
  19. package/dist/rules/prefer-is-record-and-has-key.mjs +22 -17
  20. package/dist/rules/prefer-is-record-and-has-key.mjs.map +1 -1
  21. package/dist/rules/prefer-safe-array-is-array.d.mts.map +1 -1
  22. package/dist/rules/prefer-safe-array-is-array.mjs +23 -14
  23. package/dist/rules/prefer-safe-array-is-array.mjs.map +1 -1
  24. package/dist/rules/prefer-safe-array-length-guard.d.mts.map +1 -1
  25. package/dist/rules/prefer-safe-array-length-guard.mjs +19 -15
  26. package/dist/rules/prefer-safe-array-length-guard.mjs.map +1 -1
  27. package/dist/rules/prefer-safe-number-parse-integer.d.mts.map +1 -1
  28. package/dist/rules/prefer-safe-number-parse-integer.mjs +16 -17
  29. package/dist/rules/prefer-safe-number-parse-integer.mjs.map +1 -1
  30. package/dist/rules/prefer-safe-number-parse.d.mts.map +1 -1
  31. package/dist/rules/prefer-safe-number-parse.mjs +14 -16
  32. package/dist/rules/prefer-safe-number-parse.mjs.map +1 -1
  33. package/dist/types.d.mts +2 -2
  34. package/dist/types.d.mts.map +1 -1
  35. package/package.json +24 -22
  36. package/src/plugin.mts +5 -4
  37. package/src/plugin.test.mts +0 -13
  38. package/src/rule-types.mts +2 -2
  39. package/src/rules/ast-utils.mts +147 -0
  40. package/src/rules/import-utils.mts +4 -2
  41. package/src/rules/prefer-is-non-null-object.mts +63 -38
  42. package/src/rules/prefer-is-non-null-object.test.mts +54 -0
  43. package/src/rules/prefer-is-record-and-has-key.mts +34 -21
  44. package/src/rules/prefer-is-record-and-has-key.test.mts +128 -0
  45. package/src/rules/prefer-safe-array-is-array.mts +34 -16
  46. package/src/rules/prefer-safe-array-is-array.test.mts +93 -0
  47. package/src/rules/prefer-safe-array-length-guard.mts +32 -19
  48. package/src/rules/prefer-safe-array-length-guard.test.mts +98 -0
  49. package/src/rules/prefer-safe-number-parse-integer.mts +29 -23
  50. package/src/rules/prefer-safe-number-parse-integer.test.mts +104 -0
  51. package/src/rules/prefer-safe-number-parse.mts +25 -21
  52. package/src/rules/prefer-safe-number-parse.test.mts +97 -0
  53. package/src/rules/rules.mts +1 -1
  54. package/src/types.mts +2 -2
@@ -1,4 +1,5 @@
1
1
  import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
2
+ import { getArgumentText, getValueType, skipTypeWrappers, } from './ast-utils.mjs';
2
3
  import { buildImportFixes, getNamedImports, getTsStdForgeImport, } from './import-utils.mjs';
3
4
 
4
5
 
@@ -46,8 +47,8 @@ export const preferSafeArrayLengthGuard = {
46
47
  const sourceCode = context.sourceCode;
47
48
  const program = sourceCode.ast;
48
49
  const tsStdForgeImport = getTsStdForgeImport(program);
49
- const services = sourceCode.parserServices;
50
- const checker = services?.program?.getTypeChecker();
50
+ const checker = sourceCode.parserServices?.program?.getTypeChecker();
51
+
51
52
 
52
53
 
53
54
 
@@ -56,22 +57,23 @@ export const preferSafeArrayLengthGuard = {
56
57
  const isArrayLike = (
57
58
 
58
59
  expression) => {
59
- if (checker === undefined)
60
- return false;
61
- const tsNode = services?.esTreeNodeToTSNodeMap?.get(expression);
62
- if (tsNode === undefined)
60
+ if (checker === undefined) {
63
61
  return false;
64
- const type = checker.getTypeAtLocation(tsNode);
65
- return checker.isArrayType(type) || checker.isTupleType(type);
62
+ }
63
+ const type = getValueType(sourceCode, expression);
64
+ return (type !== undefined &&
65
+ (checker.isArrayType(type) || checker.isTupleType(type)));
66
66
  };
67
67
  const mut_nodesToFix = [];
68
68
  return {
69
69
  BinaryExpression: (node) => {
70
70
  const matched = matchLengthComparison(node);
71
- if (matched === undefined)
71
+ if (matched === undefined) {
72
72
  return;
73
- if (!isArrayLike(matched.arrayExpression))
73
+ }
74
+ if (!isArrayLike(matched.arrayExpression)) {
74
75
  return;
76
+ }
75
77
  mut_nodesToFix.push({ node, ...matched });
76
78
  },
77
79
  'Program:exit': () => {
@@ -82,7 +84,7 @@ export const preferSafeArrayLengthGuard = {
82
84
 
83
85
 
84
86
  for (const [index, { node, arrayExpression, guard },] of mut_nodesToFix.entries()) {
85
- const arrayText = sourceCode.getText(arrayExpression);
87
+ const arrayText = getArgumentText(sourceCode, arrayExpression);
86
88
  context.report({
87
89
  node,
88
90
  messageId: MESSAGE_IDS[guard],
@@ -114,14 +116,16 @@ const matchLengthComparison = (
114
116
 
115
117
 
116
118
  node) => {
117
- const { left, right } = node;
118
- if (left.type === AST_NODE_TYPES.PrivateIdentifier)
119
- return undefined;
119
+
120
+
121
+ const left = skipTypeWrappers(node.left);
122
+ const right = skipTypeWrappers(node.right);
120
123
  const lengthOnLeft = isLengthAccess(left);
121
124
  const lengthSide = lengthOnLeft ? left : right;
122
125
  const boundSide = lengthOnLeft ? right : left;
123
- if (!isLengthAccess(lengthSide))
126
+ if (!isLengthAccess(lengthSide)) {
124
127
  return undefined;
128
+ }
125
129
 
126
130
 
127
131
  if (boundSide.type !== AST_NODE_TYPES.Literal ||
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-safe-array-length-guard.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-length-guard.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prefer-safe-array-length-guard.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-length-guard.mts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-safe-number-parse-integer.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse-integer.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAQlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,2BAA2B,CAAC;AAkB9C;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,UAAU,CAC5D,UAAU,EACV,OAAO,CAwHC,CAAC"}
1
+ {"version":3,"file":"prefer-safe-number-parse-integer.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse-integer.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAclC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,2BAA2B,CAAC;AAkB9C;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,UAAU,CAC5D,UAAU,EACV,OAAO,CAwHC,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
2
2
  import * as ts from 'typescript';
3
+ import { getArgumentText, getValueType, isIdentifierNamed, skipTypeWrappers, } from './ast-utils.mjs';
3
4
  import { buildImportFixes, getNamedImports, getTsStdForgeImport, } from './import-utils.mjs';
4
5
 
5
6
 
@@ -36,32 +37,34 @@ export const preferSafeNumberParseInteger = {
36
37
  const sourceCode = context.sourceCode;
37
38
  const program = sourceCode.ast;
38
39
  const tsStdForgeImport = getTsStdForgeImport(program);
39
- const services = sourceCode.parserServices;
40
40
  const mut_nodesToFix = [];
41
41
  return {
42
42
  CallExpression: (node) => {
43
- const { callee } = node;
43
+ const callee = skipTypeWrappers(node.callee);
44
44
 
45
45
  const isGlobalParseInt = callee.type === AST_NODE_TYPES.Identifier &&
46
46
  callee.name === 'parseInt';
47
47
  const isNumberParseInt = callee.type === AST_NODE_TYPES.MemberExpression &&
48
48
  !callee.computed &&
49
- callee.object.type === AST_NODE_TYPES.Identifier &&
50
- callee.object.name === 'Number' &&
49
+ isIdentifierNamed(callee.object, 'Number') &&
51
50
  callee.property.type === AST_NODE_TYPES.Identifier &&
52
51
  callee.property.name === 'parseInt';
53
- if (!isGlobalParseInt && !isNumberParseInt)
52
+ if (!isGlobalParseInt && !isNumberParseInt) {
54
53
  return;
54
+ }
55
55
  const args = node.arguments;
56
56
  const firstArg = args[0];
57
- if (firstArg === undefined)
57
+ if (firstArg === undefined) {
58
58
  return;
59
+ }
59
60
 
60
- if (firstArg.type === AST_NODE_TYPES.SpreadElement)
61
+ if (firstArg.type === AST_NODE_TYPES.SpreadElement) {
61
62
  return;
63
+ }
64
+
62
65
 
63
66
  if (args.length >= 2) {
64
- const radix = args[1];
67
+ const radix = args[1] === undefined ? undefined : skipTypeWrappers(args[1]);
65
68
  if (radix?.type !== AST_NODE_TYPES.Literal || radix.value !== 10) {
66
69
  return;
67
70
  }
@@ -69,22 +72,18 @@ export const preferSafeNumberParseInteger = {
69
72
 
70
73
 
71
74
 
72
- if (services?.program == null)
73
- return;
74
- const checker = services.program.getTypeChecker();
75
- const tsNode = services.esTreeNodeToTSNodeMap?.get(firstArg);
76
- if (tsNode === undefined)
77
- return;
78
- const argType = checker.getTypeAtLocation(tsNode);
79
- if (!isStringType(argType))
75
+
76
+ const argType = getValueType(sourceCode, firstArg);
77
+ if (argType === undefined || !isStringType(argType)) {
80
78
  return;
79
+ }
81
80
  mut_nodesToFix.push({ node, argExpression: firstArg });
82
81
  },
83
82
  'Program:exit': () => {
84
83
  const namedImports = getNamedImports(tsStdForgeImport);
85
84
  const missingImports = ['Result', 'SafeNumber'].filter((name) => !namedImports.includes(name));
86
85
  for (const [index, { node, argExpression },] of mut_nodesToFix.entries()) {
87
- const argText = sourceCode.getText(argExpression);
86
+ const argText = getArgumentText(sourceCode, argExpression);
88
87
  context.report({
89
88
  node,
90
89
  messageId: 'useSafeNumberParseInteger',
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-safe-number-parse-integer.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse-integer.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prefer-safe-number-parse-integer.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse-integer.mts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-safe-number-parse.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAQlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,oBAAoB,CAAC;AAkBvC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAmHjE,CAAC"}
1
+ {"version":3,"file":"prefer-safe-number-parse.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAclC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,oBAAoB,CAAC;AAkBvC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAiHjE,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
2
2
  import * as ts from 'typescript';
3
+ import { getArgumentText, getValueType, isIdentifierNamed, skipTypeWrappers, } from './ast-utils.mjs';
3
4
  import { buildImportFixes, getNamedImports, getTsStdForgeImport, } from './import-utils.mjs';
4
5
 
5
6
 
@@ -42,51 +43,48 @@ export const preferSafeNumberParse = {
42
43
  const sourceCode = context.sourceCode;
43
44
  const program = sourceCode.ast;
44
45
  const tsStdForgeImport = getTsStdForgeImport(program);
45
- const services = sourceCode.parserServices;
46
46
  const mut_nodesToFix = [];
47
47
  return {
48
48
  CallExpression: (node) => {
49
- const { callee } = node;
49
+ const callee = skipTypeWrappers(node.callee);
50
50
 
51
51
  const isGlobalParseFloat = callee.type === AST_NODE_TYPES.Identifier &&
52
52
  callee.name === 'parseFloat';
53
53
 
54
54
  const isNumberParseFloat = callee.type === AST_NODE_TYPES.MemberExpression &&
55
55
  !callee.computed &&
56
- callee.object.type === AST_NODE_TYPES.Identifier &&
57
- callee.object.name === 'Number' &&
56
+ isIdentifierNamed(callee.object, 'Number') &&
58
57
  callee.property.type === AST_NODE_TYPES.Identifier &&
59
58
  callee.property.name === 'parseFloat';
60
59
 
61
60
  const isNumberCall = callee.type === AST_NODE_TYPES.Identifier && callee.name === 'Number';
62
- if (!isGlobalParseFloat && !isNumberParseFloat && !isNumberCall)
61
+ if (!isGlobalParseFloat && !isNumberParseFloat && !isNumberCall) {
63
62
  return;
63
+ }
64
64
  const args = node.arguments;
65
65
  const firstArg = args[0];
66
- if (firstArg === undefined)
66
+ if (firstArg === undefined) {
67
67
  return;
68
+ }
68
69
 
69
- if (firstArg.type === AST_NODE_TYPES.SpreadElement)
70
+ if (firstArg.type === AST_NODE_TYPES.SpreadElement) {
70
71
  return;
72
+ }
71
73
 
72
74
 
73
75
 
74
- if (services?.program == null)
75
- return;
76
- const checker = services.program.getTypeChecker();
77
- const tsNode = services.esTreeNodeToTSNodeMap?.get(firstArg);
78
- if (tsNode === undefined)
79
- return;
80
- const argType = checker.getTypeAtLocation(tsNode);
81
- if (!isStringType(argType))
76
+
77
+ const argType = getValueType(sourceCode, firstArg);
78
+ if (argType === undefined || !isStringType(argType)) {
82
79
  return;
80
+ }
83
81
  mut_nodesToFix.push({ node, argExpression: firstArg });
84
82
  },
85
83
  'Program:exit': () => {
86
84
  const namedImports = getNamedImports(tsStdForgeImport);
87
85
  const missingImports = ['Result', 'SafeNumber'].filter((name) => !namedImports.includes(name));
88
86
  for (const [index, { node, argExpression },] of mut_nodesToFix.entries()) {
89
- const argText = sourceCode.getText(argExpression);
87
+ const argText = getArgumentText(sourceCode, argExpression);
90
88
  context.report({
91
89
  node,
92
90
  messageId: 'useSafeNumberParse',
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-safe-number-parse.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prefer-safe-number-parse.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse.mts"],"names":[],"mappings":"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"}
package/dist/types.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { type TSESLint } from '@typescript-eslint/utils';
2
- import { type DeepReadonly } from 'ts-type-forge';
1
+ import type { TSESLint } from '@typescript-eslint/utils';
2
+ import type { DeepReadonly } from 'ts-type-forge';
3
3
  export type ESLintPlugin = DeepReadonly<TSESLint.FlatConfig.Plugin>;
4
4
  export type ESLintFlatConfig = DeepReadonly<TSESLint.FlatConfig.Config>;
5
5
  //# sourceMappingURL=types.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../src/types.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AAEpE,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../src/types.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AAEpE,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-ts-std-forge",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "private": false,
5
5
  "description": "ESLint rules that steer code toward ts-std-forge idioms.",
6
6
  "keywords": [
@@ -34,21 +34,21 @@
34
34
  "LICENSE"
35
35
  ],
36
36
  "dependencies": {
37
- "@typescript-eslint/utils": "^8.70.0",
37
+ "@typescript-eslint/utils": "^8.70.1",
38
38
  "ts-std-forge": "0.5.1",
39
39
  "ts-type-forge": "~9.2.2"
40
40
  },
41
41
  "devDependencies": {
42
- "@typescript-eslint/parser": "8.70.0",
43
- "@typescript-eslint/rule-tester": "8.70.0",
42
+ "@typescript-eslint/parser": "8.70.1",
43
+ "@typescript-eslint/rule-tester": "8.70.1",
44
44
  "dedent": "1.7.2",
45
- "eslint-config-typed": "5.11.9",
46
- "eslint-plugin-ts-fortress": "1.2.3",
47
- "eslint-plugin-ts-type-forge": "0.8.4",
48
- "prettier": "3.9.6",
45
+ "eslint-config-typed": "5.17.0",
46
+ "eslint-plugin-ts-fortress": "1.3.0",
47
+ "eslint-plugin-ts-type-forge": "0.8.5",
48
+ "prettier": "3.9.9",
49
49
  "prettier-plugin-organize-imports": "4.3.0",
50
50
  "prettier-plugin-packagejson": "3.0.2",
51
- "ts-repo-utils": "10.6.2"
51
+ "ts-repo-utils": "10.7.1"
52
52
  },
53
53
  "peerDependencies": {
54
54
  "eslint": ">=9.0.0",
@@ -65,20 +65,22 @@
65
65
  "scripts": {
66
66
  "build": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/build.mts",
67
67
  "check:ext": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/check-ext.mts",
68
- "doc": "pnpm run doc:embed",
69
- "doc:embed": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/embed-examples.mts",
70
- "fmt": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../../libs/ts-repo-utils/src/cmd/format-uncommitted.mts --cwd .",
71
- "fmt:diff": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../../libs/ts-repo-utils/src/cmd/format-diff-from.mts origin/main --cwd .",
72
- "fmt:full": "pnpm run z:prettier .",
68
+ "check:lint": "eslint .",
69
+ "check:test": "pnpm run z:vitest run",
70
+ "check:test:cov": "pnpm run z:vitest run --coverage",
71
+ "check:types": "node ../../node_modules/typescript-native/bin/tsc --noEmit",
72
+ "doc": "pnpm run gen:readme",
73
+ "fix:fmt": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../../libs/ts-repo-utils/src/cmd/format-uncommitted.mts --cwd .",
74
+ "fix:fmt:diff": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../../libs/ts-repo-utils/src/cmd/format-diff-from.mts origin/main --cwd .",
75
+ "fix:fmt:full": "pnpm run z:prettier .",
76
+ "fix:lint": "eslint . --fix",
77
+ "fmt": "pnpm run fix:fmt",
78
+ "gen": "run-s gen:rule-types gen:readme",
79
+ "gen:readme": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/embed-examples.mts",
73
80
  "gen:rule-types": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/gen-rule-types.mts",
74
- "gen:src": "pnpm run gen:rule-types",
75
- "lint": "eslint .",
76
- "lint:fix": "eslint . --fix",
77
- "test": "pnpm run z:vitest run",
78
- "test:cov": "pnpm run z:vitest run --coverage",
79
- "testw": "pnpm run z:vitest",
80
- "tscw": "node ../../node_modules/typescript-native/bin/tsc --noEmit --watch -p ./tsconfig.json",
81
- "type-check": "node ../../node_modules/typescript-native/bin/tsc --noEmit",
81
+ "test": "pnpm run check:test",
82
+ "watch:test": "pnpm run z:vitest",
83
+ "watch:types": "node ../../node_modules/typescript-native/bin/tsc --noEmit --watch -p ./tsconfig.json",
82
84
  "z:prettier": "prettier --config ../../.prettierrc --ignore-path ../../.prettierignore --ignore-path ../../.gitignore --ignore-unknown --no-error-on-unmatched-pattern --write",
83
85
  "z:vitest": "vitest --config ./configs/vitest.config.mts"
84
86
  }
package/src/plugin.mts CHANGED
@@ -1,12 +1,13 @@
1
- import { type ReadonlyRecord } from 'ts-type-forge';
1
+ import type { ReadonlyRecord } from 'ts-type-forge';
2
2
  import { tsStdForgeRules } from './rules/index.mjs';
3
- import { type ESLintFlatConfig, type ESLintPlugin } from './types.mjs';
3
+ import type { ESLintFlatConfig, ESLintPlugin } from './types.mjs';
4
4
 
5
5
  /**
6
6
  * Every rule this plugin ships, at `error`.
7
7
  *
8
- * The `satisfies` clause below is keyed off {@link tsStdForgeRules}, so adding
9
- * a rule without listing it here fails to type-check.
8
+ * The `satisfies` clause below is keyed off {@link tsStdForgeRules}, so leaving a
9
+ * rule out, naming one that does not exist, or setting one to anything
10
+ * but `error` fails to type-check. That is the whole check; no test repeats it.
10
11
  */
11
12
  const recommendedRules = {
12
13
  'ts-std-forge/prefer-is-non-null-object': 'error',
@@ -1,21 +1,8 @@
1
1
  import { eslintPluginTsStdForge } from './plugin.mjs';
2
- import { tsStdForgeRules } from './rules/index.mjs';
3
2
 
4
3
  describe('eslintPluginTsStdForge.configs.recommended', () => {
5
4
  const recommended = eslintPluginTsStdForge.configs.recommended;
6
5
 
7
- test('enables every rule of the plugin, and nothing else, at "error"', () => {
8
- assert.deepStrictEqual(
9
- recommended.rules,
10
- Object.fromEntries(
11
- Object.keys(tsStdForgeRules).map((name) => [
12
- `ts-std-forge/${name}`,
13
- 'error',
14
- ]),
15
- ),
16
- );
17
- });
18
-
19
6
  test('registers the exported plugin object itself', () => {
20
7
  // Registering a *copy* would make `Cannot redefine plugin` errors possible
21
8
  // for users who also list the plugin in their own `plugins` record.
@@ -3,9 +3,9 @@
3
3
  // This file is auto-generated by `pnpm run gen:rule-types`
4
4
  // (`scripts/cmd/gen-rule-types.mts`). Do not edit it manually.
5
5
 
6
- import { type Linter } from 'eslint';
6
+ import type { Linter } from 'eslint';
7
7
  import { expectType } from 'ts-std-forge';
8
- import { type tsStdForgeRules } from './rules/index.mjs';
8
+ import type { tsStdForgeRules } from './rules/index.mjs';
9
9
 
10
10
  /**
11
11
  * @description Replace `typeof u === "object" && u !== null` with `isNonNullObject(u)` from ts-std-forge.
@@ -0,0 +1,147 @@
1
+ import {
2
+ AST_NODE_TYPES,
3
+ ASTUtils,
4
+ type TSESLint,
5
+ type TSESTree,
6
+ } from '@typescript-eslint/utils';
7
+ import type * as ts from 'typescript';
8
+
9
+ /**
10
+ * `node` with every `as`, `satisfies`, `!` and `<T>` around it taken off: the
11
+ * expression whose value it is. Judge syntax and ask types on what this
12
+ * returns, so that a wrapper neither hides a pattern (`xs.length > (0 as
13
+ * const)`) nor vouches for a type (`Number(b as unknown as string)`, whose
14
+ * value is still a boolean), and keep the original node for fix text. See
15
+ * `docs/writing-lint-rules.md` at the repository root.
16
+ *
17
+ * A copy of the helper in `eslint-config-typed`, which this package, published
18
+ * on its own, cannot import.
19
+ */
20
+ export const skipTypeWrappers = (
21
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
22
+ node: TSESTree.Node,
23
+ ): TSESTree.Node =>
24
+ isTypeWrapper(node) ? skipTypeWrappers(node.expression) : node;
25
+
26
+ export const isTypeWrapper = (
27
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
28
+ node: TSESTree.Node,
29
+ ): node is TypeWrapper => TYPE_WRAPPERS.has(node.type);
30
+
31
+ /**
32
+ * Whether `node`, read through its type wrappers, is the identifier `name`:
33
+ * `Number`, `(Number as NumberConstructor)` and `Number!` are the same object.
34
+ */
35
+ export const isIdentifierNamed = (
36
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
37
+ node: TSESTree.Node,
38
+ name: string,
39
+ ): boolean => {
40
+ const unwrapped = skipTypeWrappers(node);
41
+
42
+ return (
43
+ unwrapped.type === AST_NODE_TYPES.Identifier && unwrapped.name === name
44
+ );
45
+ };
46
+
47
+ export type TypeWrapper =
48
+ | TSESTree.TSAsExpression
49
+ | TSESTree.TSNonNullExpression
50
+ | TSESTree.TSSatisfiesExpression
51
+ | TSESTree.TSTypeAssertion;
52
+
53
+ /**
54
+ * The type of the value `node` evaluates to, asked of the expression inside
55
+ * its type wrappers rather than of the cast, or `undefined` without type
56
+ * information. A `!` among the wrappers still takes `null` and `undefined`
57
+ * out, since that much the source asserts about the value itself.
58
+ */
59
+ export const getValueType = (
60
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
61
+ sourceCode: TSESLint.SourceCode,
62
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
63
+ node: TSESTree.Node,
64
+ ): ts.Type | undefined => {
65
+ const services = sourceCode.parserServices;
66
+
67
+ const checker = services?.program?.getTypeChecker();
68
+
69
+ const tsNode = services?.esTreeNodeToTSNodeMap?.get(skipTypeWrappers(node));
70
+
71
+ if (checker === undefined || tsNode === undefined) {
72
+ return undefined;
73
+ }
74
+
75
+ const type = checker.getTypeAtLocation(tsNode);
76
+
77
+ return hasNonNullAssertion(node) ? checker.getNonNullableType(type) : type;
78
+ };
79
+
80
+ /**
81
+ * The source text of `node` to put in a call's argument list. `getText`
82
+ * leaves out the parentheses the source puts around a node, and a sequence
83
+ * `(a, b)` without them would be read as two arguments.
84
+ */
85
+ export const getArgumentText = (
86
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
87
+ sourceCode: TSESLint.SourceCode,
88
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
89
+ node: TSESTree.Node,
90
+ ): string => {
91
+ const text = sourceCode.getText(node);
92
+
93
+ return node.type === AST_NODE_TYPES.SequenceExpression ? `(${text})` : text;
94
+ };
95
+
96
+ /**
97
+ * The range of `node` together with the parentheses the source puts around it,
98
+ * which `node.range` leaves out: all of `((Array.isArray))` for the member
99
+ * expression inside.
100
+ */
101
+ export const getRangeWithParens = (
102
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
103
+ sourceCode: TSESLint.SourceCode,
104
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
105
+ node: TSESTree.Node,
106
+ ): TSESTree.Range => {
107
+ const depth = parenthesesDepth(sourceCode, node);
108
+
109
+ if (depth === 0) {
110
+ return node.range;
111
+ }
112
+
113
+ const opening = sourceCode.getTokenBefore(node, { skip: depth - 1 });
114
+
115
+ const closing = sourceCode.getTokenAfter(node, { skip: depth - 1 });
116
+
117
+ return opening === null || closing === null
118
+ ? node.range
119
+ : [opening.range[0], closing.range[1]];
120
+ };
121
+
122
+ /** How many pairs of parentheses the source puts around `node`. */
123
+ const parenthesesDepth = (
124
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
125
+ sourceCode: TSESLint.SourceCode,
126
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
127
+ node: TSESTree.Node,
128
+ depth: number = 0,
129
+ ): number =>
130
+ ASTUtils.isParenthesized(depth + 1, node, sourceCode)
131
+ ? parenthesesDepth(sourceCode, node, depth + 1)
132
+ : depth;
133
+
134
+ const hasNonNullAssertion = (
135
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
136
+ node: TSESTree.Node,
137
+ ): boolean =>
138
+ isTypeWrapper(node) &&
139
+ (node.type === AST_NODE_TYPES.TSNonNullExpression ||
140
+ hasNonNullAssertion(node.expression));
141
+
142
+ const TYPE_WRAPPERS: ReadonlySet<AST_NODE_TYPES> = new Set([
143
+ AST_NODE_TYPES.TSAsExpression,
144
+ AST_NODE_TYPES.TSNonNullExpression,
145
+ AST_NODE_TYPES.TSSatisfiesExpression,
146
+ AST_NODE_TYPES.TSTypeAssertion,
147
+ ]);
@@ -3,7 +3,7 @@ import {
3
3
  type TSESLint,
4
4
  type TSESTree,
5
5
  } from '@typescript-eslint/utils';
6
- import { type DeepReadonly } from 'ts-type-forge';
6
+ import type { DeepReadonly } from 'ts-type-forge';
7
7
  import { TS_STD_FORGE_MODULE } from './constants.mjs';
8
8
 
9
9
  /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
@@ -20,7 +20,9 @@ export const getTsStdForgeImport = (
20
20
  export const getNamedImports = (
21
21
  node: DeepReadonly<TSESTree.ImportDeclaration> | undefined,
22
22
  ): readonly string[] => {
23
- if (node === undefined) return [];
23
+ if (node === undefined) {
24
+ return [];
25
+ }
24
26
 
25
27
  return node.specifiers.flatMap((specifier) =>
26
28
  specifier.type === AST_NODE_TYPES.ImportSpecifier