corsa-oxlint 0.1.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 (121) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +171 -0
  3. package/dist/_virtual/_rolldown/runtime.js +13 -0
  4. package/dist/ast_utils.d.ts +17 -0
  5. package/dist/ast_utils.js +21 -0
  6. package/dist/ast_utils.js.map +1 -0
  7. package/dist/checker.d.ts +11 -0
  8. package/dist/checker.js +80 -0
  9. package/dist/checker.js.map +1 -0
  10. package/dist/compat.d.ts +194 -0
  11. package/dist/compat.js +103 -0
  12. package/dist/compat.js.map +1 -0
  13. package/dist/context.d.ts +24 -0
  14. package/dist/context.js +134 -0
  15. package/dist/context.js.map +1 -0
  16. package/dist/eslint_utils.d.ts +19 -0
  17. package/dist/eslint_utils.js +48 -0
  18. package/dist/eslint_utils.js.map +1 -0
  19. package/dist/index.d.ts +12 -0
  20. package/dist/index.js +11 -0
  21. package/dist/json_schema.d.ts +11 -0
  22. package/dist/json_schema.js +17 -0
  23. package/dist/json_schema.js.map +1 -0
  24. package/dist/node_map.d.ts +18 -0
  25. package/dist/node_map.js +52 -0
  26. package/dist/node_map.js.map +1 -0
  27. package/dist/parser_services.d.ts +16 -0
  28. package/dist/parser_services.js +48 -0
  29. package/dist/parser_services.js.map +1 -0
  30. package/dist/plugin.d.ts +26 -0
  31. package/dist/plugin.js +83 -0
  32. package/dist/plugin.js.map +1 -0
  33. package/dist/registry.d.ts +12 -0
  34. package/dist/registry.js +35 -0
  35. package/dist/registry.js.map +1 -0
  36. package/dist/rule_tester.d.ts +37 -0
  37. package/dist/rule_tester.js +120 -0
  38. package/dist/rule_tester.js.map +1 -0
  39. package/dist/rules/ast.d.ts +16 -0
  40. package/dist/rules/ast.js +56 -0
  41. package/dist/rules/ast.js.map +1 -0
  42. package/dist/rules/await_thenable.d.ts +16 -0
  43. package/dist/rules/await_thenable.js +23 -0
  44. package/dist/rules/await_thenable.js.map +1 -0
  45. package/dist/rules/index.d.ts +473 -0
  46. package/dist/rules/index.js +120 -0
  47. package/dist/rules/index.js.map +1 -0
  48. package/dist/rules/no_array_delete.d.ts +16 -0
  49. package/dist/rules/no_array_delete.js +29 -0
  50. package/dist/rules/no_array_delete.js.map +1 -0
  51. package/dist/rules/no_base_to_string.d.ts +16 -0
  52. package/dist/rules/no_base_to_string.js +66 -0
  53. package/dist/rules/no_base_to_string.js.map +1 -0
  54. package/dist/rules/no_floating_promises.d.ts +16 -0
  55. package/dist/rules/no_floating_promises.js +42 -0
  56. package/dist/rules/no_floating_promises.js.map +1 -0
  57. package/dist/rules/no_for_in_array.d.ts +16 -0
  58. package/dist/rules/no_for_in_array.js +16 -0
  59. package/dist/rules/no_for_in_array.js.map +1 -0
  60. package/dist/rules/no_implied_eval.d.ts +16 -0
  61. package/dist/rules/no_implied_eval.js +35 -0
  62. package/dist/rules/no_implied_eval.js.map +1 -0
  63. package/dist/rules/no_mixed_enums.d.ts +16 -0
  64. package/dist/rules/no_mixed_enums.js +41 -0
  65. package/dist/rules/no_mixed_enums.js.map +1 -0
  66. package/dist/rules/no_unsafe_assignment.d.ts +16 -0
  67. package/dist/rules/no_unsafe_assignment.js +41 -0
  68. package/dist/rules/no_unsafe_assignment.js.map +1 -0
  69. package/dist/rules/no_unsafe_return.d.ts +16 -0
  70. package/dist/rules/no_unsafe_return.js +56 -0
  71. package/dist/rules/no_unsafe_return.js.map +1 -0
  72. package/dist/rules/no_unsafe_unary_minus.d.ts +16 -0
  73. package/dist/rules/no_unsafe_unary_minus.js +28 -0
  74. package/dist/rules/no_unsafe_unary_minus.js.map +1 -0
  75. package/dist/rules/only_throw_error.d.ts +16 -0
  76. package/dist/rules/only_throw_error.js +16 -0
  77. package/dist/rules/only_throw_error.js.map +1 -0
  78. package/dist/rules/prefer_find.d.ts +16 -0
  79. package/dist/rules/prefer_find.js +25 -0
  80. package/dist/rules/prefer_find.js.map +1 -0
  81. package/dist/rules/prefer_includes.d.ts +16 -0
  82. package/dist/rules/prefer_includes.js +21 -0
  83. package/dist/rules/prefer_includes.js.map +1 -0
  84. package/dist/rules/prefer_promise_reject_errors.d.ts +16 -0
  85. package/dist/rules/prefer_promise_reject_errors.js +52 -0
  86. package/dist/rules/prefer_promise_reject_errors.js.map +1 -0
  87. package/dist/rules/prefer_regexp_exec.d.ts +16 -0
  88. package/dist/rules/prefer_regexp_exec.js +20 -0
  89. package/dist/rules/prefer_regexp_exec.js.map +1 -0
  90. package/dist/rules/prefer_string_starts_ends_with.d.ts +16 -0
  91. package/dist/rules/prefer_string_starts_ends_with.js +53 -0
  92. package/dist/rules/prefer_string_starts_ends_with.js.map +1 -0
  93. package/dist/rules/require_array_sort_compare.d.ts +16 -0
  94. package/dist/rules/require_array_sort_compare.js +36 -0
  95. package/dist/rules/require_array_sort_compare.js.map +1 -0
  96. package/dist/rules/restrict_plus_operands.d.ts +16 -0
  97. package/dist/rules/restrict_plus_operands.js +62 -0
  98. package/dist/rules/restrict_plus_operands.js.map +1 -0
  99. package/dist/rules/rule_creator.d.ts +16 -0
  100. package/dist/rules/rule_creator.js +22 -0
  101. package/dist/rules/rule_creator.js.map +1 -0
  102. package/dist/rules/type_utils.d.ts +56 -0
  103. package/dist/rules/type_utils.js +102 -0
  104. package/dist/rules/type_utils.js.map +1 -0
  105. package/dist/rules/use_unknown_in_catch_callback_variable.d.ts +16 -0
  106. package/dist/rules/use_unknown_in_catch_callback_variable.js +19 -0
  107. package/dist/rules/use_unknown_in_catch_callback_variable.js.map +1 -0
  108. package/dist/session.d.ts +32 -0
  109. package/dist/session.js +179 -0
  110. package/dist/session.js.map +1 -0
  111. package/dist/ts_eslint.d.ts +22 -0
  112. package/dist/ts_eslint.js +30 -0
  113. package/dist/ts_eslint.js.map +1 -0
  114. package/dist/ts_estree.d.ts +2 -0
  115. package/dist/ts_estree.js +2 -0
  116. package/dist/types.d.ts +136 -0
  117. package/dist/types.js +1 -0
  118. package/dist/utils.d.ts +22 -0
  119. package/dist/utils.js +22 -0
  120. package/dist/utils.js.map +1 -0
  121. package/package.json +69 -0
@@ -0,0 +1,21 @@
1
+ import { calleePropertyName, isNegativeOneLiteral, isZeroLiteral } from "./ast.js";
2
+ import { createNativeRule } from "./rule_creator.js";
3
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/prefer_includes.ts
4
+ const preferIncludesRule = createNativeRule("prefer-includes", {
5
+ docs: { description: "Prefer includes over indexOf/lastIndexOf comparisons." },
6
+ messages: { unexpected: "Use .includes() instead of comparing an index result." }
7
+ }, (context) => ({ BinaryExpression(node) {
8
+ if (!isComparableIndexSearch(node.left) && !isComparableIndexSearch(node.right)) return;
9
+ if (isNegativeOneLiteral(node.left) || isNegativeOneLiteral(node.right) || isZeroLiteral(node.left) || isZeroLiteral(node.right)) context.report({
10
+ node,
11
+ messageId: "unexpected"
12
+ });
13
+ } }));
14
+ function isComparableIndexSearch(node) {
15
+ const propertyName = calleePropertyName(node);
16
+ return propertyName === "indexOf" || propertyName === "lastIndexOf";
17
+ }
18
+ //#endregion
19
+ export { preferIncludesRule };
20
+
21
+ //# sourceMappingURL=prefer_includes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefer_includes.js","names":[],"sources":["../../ts/rules/prefer_includes.ts"],"sourcesContent":["import { calleePropertyName, isNegativeOneLiteral, isZeroLiteral } from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\n\nexport const preferIncludesRule = createNativeRule(\n \"prefer-includes\",\n {\n docs: {\n description: \"Prefer includes over indexOf/lastIndexOf comparisons.\",\n },\n messages: {\n unexpected: \"Use .includes() instead of comparing an index result.\",\n },\n },\n (context) => ({\n BinaryExpression(node: any) {\n if (!isComparableIndexSearch(node.left) && !isComparableIndexSearch(node.right)) {\n return;\n }\n if (\n isNegativeOneLiteral(node.left) ||\n isNegativeOneLiteral(node.right) ||\n isZeroLiteral(node.left) ||\n isZeroLiteral(node.right)\n ) {\n context.report({ node, messageId: \"unexpected\" });\n }\n },\n }),\n);\n\nfunction isComparableIndexSearch(node: any): boolean {\n const propertyName = calleePropertyName(node);\n return propertyName === \"indexOf\" || propertyName === \"lastIndexOf\";\n}\n"],"mappings":";;;AAGA,MAAa,qBAAqB,iBAChC,mBACA;CACE,MAAM,EACJ,aAAa,yDACd;CACD,UAAU,EACR,YAAY,yDACb;CACF,GACA,aAAa,EACZ,iBAAiB,MAAW;AAC1B,KAAI,CAAC,wBAAwB,KAAK,KAAK,IAAI,CAAC,wBAAwB,KAAK,MAAM,CAC7E;AAEF,KACE,qBAAqB,KAAK,KAAK,IAC/B,qBAAqB,KAAK,MAAM,IAChC,cAAc,KAAK,KAAK,IACxB,cAAc,KAAK,MAAM,CAEzB,SAAQ,OAAO;EAAE;EAAM,WAAW;EAAc,CAAC;GAGtD,EACF;AAED,SAAS,wBAAwB,MAAoB;CACnD,MAAM,eAAe,mBAAmB,KAAK;AAC7C,QAAO,iBAAiB,aAAa,iBAAiB"}
@@ -0,0 +1,16 @@
1
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/prefer_promise_reject_errors.d.ts
2
+ declare const preferPromiseRejectErrorsRule: {
3
+ defaultOptions: never[];
4
+ meta: {
5
+ docs: {
6
+ requiresTypeChecking: boolean;
7
+ url: string;
8
+ };
9
+ type: "problem";
10
+ schema: never[];
11
+ };
12
+ create: (context: any) => Record<string, (node: any) => void>;
13
+ };
14
+ //#endregion
15
+ export { preferPromiseRejectErrorsRule };
16
+ //# sourceMappingURL=prefer_promise_reject_errors.d.ts.map
@@ -0,0 +1,52 @@
1
+ import { isIdentifierNamed, memberObject, memberPropertyName, nearestFunctionAncestors, stripChainExpression } from "./ast.js";
2
+ import { createNativeRule } from "./rule_creator.js";
3
+ import { isAnyLikeNode, isErrorLikeNode, isPromiseLikeNode, isUnknownLikeNode } from "./type_utils.js";
4
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/prefer_promise_reject_errors.ts
5
+ const defaults = {
6
+ allowEmptyReject: false,
7
+ allowThrowingAny: false,
8
+ allowThrowingUnknown: false
9
+ };
10
+ const preferPromiseRejectErrorsRule = createNativeRule("prefer-promise-reject-errors", {
11
+ docs: { description: "Require Promise rejection reasons to be Error-like values." },
12
+ messages: { rejectAnError: "Expected the Promise rejection reason to be an Error." },
13
+ schema: { type: "array" }
14
+ }, (context) => ({ CallExpression(node) {
15
+ if (!isPromiseRejectCall(context, node) && !isPromiseExecutorRejectCall(context, node)) return;
16
+ if (acceptRejectArguments(context, node.arguments, resolveOptions(context.options))) return;
17
+ context.report({
18
+ node,
19
+ messageId: "rejectAnError"
20
+ });
21
+ } }));
22
+ function isPromiseRejectCall(context, node) {
23
+ const object = memberObject(node.callee);
24
+ return memberPropertyName(node.callee) === "reject" && (isIdentifierNamed(object, "Promise") || isPromiseLikeNode(context, object));
25
+ }
26
+ function isPromiseExecutorRejectCall(context, node) {
27
+ const callee = stripChainExpression(node.callee);
28
+ if (callee?.type !== "Identifier") return false;
29
+ const [nearestFunction] = nearestFunctionAncestors(node, context.sourceCode);
30
+ if (!nearestFunction) return false;
31
+ const rejectParam = nearestFunction.params?.[1];
32
+ if (!rejectParam || rejectParam.type !== "Identifier" || rejectParam.name !== callee.name) return false;
33
+ const promiseConstructor = stripChainExpression(nearestFunction.parent?.parent);
34
+ return nearestFunction.parent?.type === "NewExpression" && isIdentifierNamed(nearestFunction.parent.callee, "Promise") || promiseConstructor?.type === "NewExpression" && isIdentifierNamed(promiseConstructor.callee, "Promise");
35
+ }
36
+ function acceptRejectArguments(context, args, options) {
37
+ const [argument] = args;
38
+ if (!argument) return options.allowEmptyReject;
39
+ if (options.allowThrowingAny && isAnyLikeNode(context, argument)) return true;
40
+ if (options.allowThrowingUnknown && isUnknownLikeNode(context, argument)) return true;
41
+ return isErrorLikeNode(context, argument);
42
+ }
43
+ function resolveOptions(options) {
44
+ return {
45
+ ...defaults,
46
+ ...options[0]
47
+ };
48
+ }
49
+ //#endregion
50
+ export { preferPromiseRejectErrorsRule };
51
+
52
+ //# sourceMappingURL=prefer_promise_reject_errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefer_promise_reject_errors.js","names":[],"sources":["../../ts/rules/prefer_promise_reject_errors.ts"],"sourcesContent":["import {\n isIdentifierNamed,\n memberObject,\n memberPropertyName,\n nearestFunctionAncestors,\n stripChainExpression,\n} from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport { isAnyLikeNode, isErrorLikeNode, isPromiseLikeNode, isUnknownLikeNode } from \"./type_utils\";\n\ntype Options = {\n allowEmptyReject?: boolean;\n allowThrowingAny?: boolean;\n allowThrowingUnknown?: boolean;\n};\n\nconst defaults: Required<Options> = {\n allowEmptyReject: false,\n allowThrowingAny: false,\n allowThrowingUnknown: false,\n};\n\nexport const preferPromiseRejectErrorsRule = createNativeRule(\n \"prefer-promise-reject-errors\",\n {\n docs: {\n description: \"Require Promise rejection reasons to be Error-like values.\",\n },\n messages: {\n rejectAnError: \"Expected the Promise rejection reason to be an Error.\",\n },\n schema: { type: \"array\" },\n },\n (context) => ({\n CallExpression(node: any) {\n if (!isPromiseRejectCall(context, node) && !isPromiseExecutorRejectCall(context, node)) {\n return;\n }\n if (acceptRejectArguments(context, node.arguments, resolveOptions(context.options))) {\n return;\n }\n context.report({ node, messageId: \"rejectAnError\" });\n },\n }),\n);\n\nfunction isPromiseRejectCall(context: any, node: any): boolean {\n const object = memberObject(node.callee) as any;\n return (\n memberPropertyName(node.callee) === \"reject\" &&\n (isIdentifierNamed(object, \"Promise\") || isPromiseLikeNode(context, object))\n );\n}\n\nfunction isPromiseExecutorRejectCall(context: any, node: any): boolean {\n const callee = stripChainExpression(node.callee);\n if (callee?.type !== \"Identifier\") {\n return false;\n }\n const [nearestFunction] = nearestFunctionAncestors(node, context.sourceCode);\n if (!nearestFunction) {\n return false;\n }\n const rejectParam = nearestFunction.params?.[1];\n if (!rejectParam || rejectParam.type !== \"Identifier\" || rejectParam.name !== callee.name) {\n return false;\n }\n const promiseConstructor = stripChainExpression(nearestFunction.parent?.parent);\n return (\n (nearestFunction.parent?.type === \"NewExpression\" &&\n isIdentifierNamed(nearestFunction.parent.callee, \"Promise\")) ||\n (promiseConstructor?.type === \"NewExpression\" &&\n isIdentifierNamed(promiseConstructor.callee, \"Promise\"))\n );\n}\n\nfunction acceptRejectArguments(\n context: any,\n args: readonly any[],\n options: Required<Options>,\n): boolean {\n const [argument] = args;\n if (!argument) {\n return options.allowEmptyReject;\n }\n if (options.allowThrowingAny && isAnyLikeNode(context, argument)) {\n return true;\n }\n if (options.allowThrowingUnknown && isUnknownLikeNode(context, argument)) {\n return true;\n }\n return isErrorLikeNode(context, argument);\n}\n\nfunction resolveOptions(options: readonly unknown[]): Required<Options> {\n return { ...defaults, ...(options[0] as Options | undefined) };\n}\n"],"mappings":";;;;AAgBA,MAAM,WAA8B;CAClC,kBAAkB;CAClB,kBAAkB;CAClB,sBAAsB;CACvB;AAED,MAAa,gCAAgC,iBAC3C,gCACA;CACE,MAAM,EACJ,aAAa,8DACd;CACD,UAAU,EACR,eAAe,yDAChB;CACD,QAAQ,EAAE,MAAM,SAAS;CAC1B,GACA,aAAa,EACZ,eAAe,MAAW;AACxB,KAAI,CAAC,oBAAoB,SAAS,KAAK,IAAI,CAAC,4BAA4B,SAAS,KAAK,CACpF;AAEF,KAAI,sBAAsB,SAAS,KAAK,WAAW,eAAe,QAAQ,QAAQ,CAAC,CACjF;AAEF,SAAQ,OAAO;EAAE;EAAM,WAAW;EAAiB,CAAC;GAEvD,EACF;AAED,SAAS,oBAAoB,SAAc,MAAoB;CAC7D,MAAM,SAAS,aAAa,KAAK,OAAO;AACxC,QACE,mBAAmB,KAAK,OAAO,KAAK,aACnC,kBAAkB,QAAQ,UAAU,IAAI,kBAAkB,SAAS,OAAO;;AAI/E,SAAS,4BAA4B,SAAc,MAAoB;CACrE,MAAM,SAAS,qBAAqB,KAAK,OAAO;AAChD,KAAI,QAAQ,SAAS,aACnB,QAAO;CAET,MAAM,CAAC,mBAAmB,yBAAyB,MAAM,QAAQ,WAAW;AAC5E,KAAI,CAAC,gBACH,QAAO;CAET,MAAM,cAAc,gBAAgB,SAAS;AAC7C,KAAI,CAAC,eAAe,YAAY,SAAS,gBAAgB,YAAY,SAAS,OAAO,KACnF,QAAO;CAET,MAAM,qBAAqB,qBAAqB,gBAAgB,QAAQ,OAAO;AAC/E,QACG,gBAAgB,QAAQ,SAAS,mBAChC,kBAAkB,gBAAgB,OAAO,QAAQ,UAAU,IAC5D,oBAAoB,SAAS,mBAC5B,kBAAkB,mBAAmB,QAAQ,UAAU;;AAI7D,SAAS,sBACP,SACA,MACA,SACS;CACT,MAAM,CAAC,YAAY;AACnB,KAAI,CAAC,SACH,QAAO,QAAQ;AAEjB,KAAI,QAAQ,oBAAoB,cAAc,SAAS,SAAS,CAC9D,QAAO;AAET,KAAI,QAAQ,wBAAwB,kBAAkB,SAAS,SAAS,CACtE,QAAO;AAET,QAAO,gBAAgB,SAAS,SAAS;;AAG3C,SAAS,eAAe,SAAgD;AACtE,QAAO;EAAE,GAAG;EAAU,GAAI,QAAQ;EAA4B"}
@@ -0,0 +1,16 @@
1
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/prefer_regexp_exec.d.ts
2
+ declare const preferRegexpExecRule: {
3
+ defaultOptions: never[];
4
+ meta: {
5
+ docs: {
6
+ requiresTypeChecking: boolean;
7
+ url: string;
8
+ };
9
+ type: "problem";
10
+ schema: never[];
11
+ };
12
+ create: (context: any) => Record<string, (node: any) => void>;
13
+ };
14
+ //#endregion
15
+ export { preferRegexpExecRule };
16
+ //# sourceMappingURL=prefer_regexp_exec.d.ts.map
@@ -0,0 +1,20 @@
1
+ import { calleePropertyName, regexFlags } from "./ast.js";
2
+ import { createNativeRule } from "./rule_creator.js";
3
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/prefer_regexp_exec.ts
4
+ const preferRegexpExecRule = createNativeRule("prefer-regexp-exec", {
5
+ docs: { description: "Prefer RegExp#exec over String#match for single matches." },
6
+ messages: { unexpected: "Use a RegExp exec() call instead of String match()." }
7
+ }, (context) => ({ CallExpression(node) {
8
+ if (calleePropertyName(node) !== "match") return;
9
+ const [firstArgument] = node.arguments;
10
+ if (!firstArgument) return;
11
+ const flags = regexFlags(firstArgument);
12
+ if (flags !== void 0 && !flags.includes("g")) context.report({
13
+ node,
14
+ messageId: "unexpected"
15
+ });
16
+ } }));
17
+ //#endregion
18
+ export { preferRegexpExecRule };
19
+
20
+ //# sourceMappingURL=prefer_regexp_exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefer_regexp_exec.js","names":[],"sources":["../../ts/rules/prefer_regexp_exec.ts"],"sourcesContent":["import { calleePropertyName, regexFlags } from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\n\nexport const preferRegexpExecRule = createNativeRule(\n \"prefer-regexp-exec\",\n {\n docs: {\n description: \"Prefer RegExp#exec over String#match for single matches.\",\n },\n messages: {\n unexpected: \"Use a RegExp exec() call instead of String match().\",\n },\n },\n (context) => ({\n CallExpression(node: any) {\n if (calleePropertyName(node) !== \"match\") {\n return;\n }\n const [firstArgument] = node.arguments;\n if (!firstArgument) {\n return;\n }\n const flags = regexFlags(firstArgument);\n if (flags !== undefined && !flags.includes(\"g\")) {\n context.report({ node, messageId: \"unexpected\" });\n }\n },\n }),\n);\n"],"mappings":";;;AAGA,MAAa,uBAAuB,iBAClC,sBACA;CACE,MAAM,EACJ,aAAa,4DACd;CACD,UAAU,EACR,YAAY,uDACb;CACF,GACA,aAAa,EACZ,eAAe,MAAW;AACxB,KAAI,mBAAmB,KAAK,KAAK,QAC/B;CAEF,MAAM,CAAC,iBAAiB,KAAK;AAC7B,KAAI,CAAC,cACH;CAEF,MAAM,QAAQ,WAAW,cAAc;AACvC,KAAI,UAAU,KAAA,KAAa,CAAC,MAAM,SAAS,IAAI,CAC7C,SAAQ,OAAO;EAAE;EAAM,WAAW;EAAc,CAAC;GAGtD,EACF"}
@@ -0,0 +1,16 @@
1
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/prefer_string_starts_ends_with.d.ts
2
+ declare const preferStringStartsEndsWithRule: {
3
+ defaultOptions: never[];
4
+ meta: {
5
+ docs: {
6
+ requiresTypeChecking: boolean;
7
+ url: string;
8
+ };
9
+ type: "problem";
10
+ schema: never[];
11
+ };
12
+ create: (context: any) => Record<string, (node: any) => void>;
13
+ };
14
+ //#endregion
15
+ export { preferStringStartsEndsWithRule };
16
+ //# sourceMappingURL=prefer_string_starts_ends_with.d.ts.map
@@ -0,0 +1,53 @@
1
+ import { calleePropertyName, isZeroLiteral, memberObject, memberPropertyName, stripChainExpression } from "./ast.js";
2
+ import { createNativeRule } from "./rule_creator.js";
3
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/prefer_string_starts_ends_with.ts
4
+ const comparableOperators = new Set([
5
+ "==",
6
+ "===",
7
+ "!=",
8
+ "!=="
9
+ ]);
10
+ const preferStringStartsEndsWithRule = createNativeRule("prefer-string-starts-ends-with", {
11
+ docs: { description: "Prefer startsWith()/endsWith() over manual string prefix/suffix checks." },
12
+ messages: {
13
+ endsWith: "Use endsWith() instead of slicing and comparing a suffix.",
14
+ startsWith: "Use startsWith() instead of comparing a prefix manually."
15
+ }
16
+ }, (context) => ({ BinaryExpression(node) {
17
+ if (!comparableOperators.has(node.operator)) return;
18
+ const match = detectManualStringCheck(context.sourceCode, node.left, node.right) ?? detectManualStringCheck(context.sourceCode, node.right, node.left);
19
+ if (!match) return;
20
+ context.report({
21
+ node,
22
+ messageId: match
23
+ });
24
+ } }));
25
+ function detectManualStringCheck(sourceCode, candidate, compared) {
26
+ const current = stripChainExpression(candidate);
27
+ if (current?.type !== "CallExpression") return;
28
+ if (calleePropertyName(current) === "indexOf" && isZeroLiteral(compared)) return "startsWith";
29
+ if (calleePropertyName(current) !== "slice") return;
30
+ const [start, end] = current.arguments;
31
+ if (isZeroLiteral(start) && end && sameLengthTarget(end, compared, sourceCode)) return "startsWith";
32
+ const suffix = negativeLengthTarget(start);
33
+ if (!end && suffix && sameExpression(suffix, compared, sourceCode)) return "endsWith";
34
+ }
35
+ function sameLengthTarget(lengthNode, compared, sourceCode) {
36
+ if (memberPropertyName(lengthNode) !== "length") return false;
37
+ const target = memberObject(lengthNode);
38
+ return target ? sameExpression(target, compared, sourceCode) : false;
39
+ }
40
+ function negativeLengthTarget(node) {
41
+ const current = stripChainExpression(node);
42
+ if (current?.type !== "UnaryExpression" || current.operator !== "-") return;
43
+ const target = memberObject(current.argument);
44
+ if (!target || memberPropertyName(current.argument) !== "length") return;
45
+ return target;
46
+ }
47
+ function sameExpression(left, right, sourceCode) {
48
+ return sourceCode.getText(stripChainExpression(left)) === sourceCode.getText(stripChainExpression(right));
49
+ }
50
+ //#endregion
51
+ export { preferStringStartsEndsWithRule };
52
+
53
+ //# sourceMappingURL=prefer_string_starts_ends_with.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefer_string_starts_ends_with.js","names":[],"sources":["../../ts/rules/prefer_string_starts_ends_with.ts"],"sourcesContent":["import {\n calleePropertyName,\n isZeroLiteral,\n memberObject,\n memberPropertyName,\n stripChainExpression,\n} from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\n\nconst comparableOperators = new Set([\"==\", \"===\", \"!=\", \"!==\"]);\n\nexport const preferStringStartsEndsWithRule = createNativeRule(\n \"prefer-string-starts-ends-with\",\n {\n docs: {\n description: \"Prefer startsWith()/endsWith() over manual string prefix/suffix checks.\",\n },\n messages: {\n endsWith: \"Use endsWith() instead of slicing and comparing a suffix.\",\n startsWith: \"Use startsWith() instead of comparing a prefix manually.\",\n },\n },\n (context) => ({\n BinaryExpression(node: any) {\n if (!comparableOperators.has(node.operator)) {\n return;\n }\n\n const match =\n detectManualStringCheck(context.sourceCode, node.left, node.right) ??\n detectManualStringCheck(context.sourceCode, node.right, node.left);\n if (!match) {\n return;\n }\n\n context.report({\n node,\n messageId: match,\n });\n },\n }),\n);\n\nfunction detectManualStringCheck(\n sourceCode: any,\n candidate: any,\n compared: any,\n): \"startsWith\" | \"endsWith\" | undefined {\n const current = stripChainExpression(candidate) as any;\n if (current?.type !== \"CallExpression\") {\n return undefined;\n }\n\n if (calleePropertyName(current) === \"indexOf\" && isZeroLiteral(compared)) {\n return \"startsWith\";\n }\n\n if (calleePropertyName(current) !== \"slice\") {\n return undefined;\n }\n\n const [start, end] = current.arguments;\n if (isZeroLiteral(start) && end && sameLengthTarget(end, compared, sourceCode)) {\n return \"startsWith\";\n }\n\n const suffix = negativeLengthTarget(start);\n if (!end && suffix && sameExpression(suffix, compared, sourceCode)) {\n return \"endsWith\";\n }\n\n return undefined;\n}\n\nfunction sameLengthTarget(lengthNode: any, compared: any, sourceCode: any): boolean {\n if (memberPropertyName(lengthNode) !== \"length\") {\n return false;\n }\n const target = memberObject(lengthNode);\n return target ? sameExpression(target, compared, sourceCode) : false;\n}\n\nfunction negativeLengthTarget(node: any): any {\n const current = stripChainExpression(node) as any;\n if (current?.type !== \"UnaryExpression\" || current.operator !== \"-\") {\n return undefined;\n }\n const target = memberObject(current.argument);\n if (!target || memberPropertyName(current.argument) !== \"length\") {\n return undefined;\n }\n return target;\n}\n\nfunction sameExpression(left: any, right: any, sourceCode: any): boolean {\n return (\n sourceCode.getText(stripChainExpression(left)) ===\n sourceCode.getText(stripChainExpression(right))\n );\n}\n"],"mappings":";;;AASA,MAAM,sBAAsB,IAAI,IAAI;CAAC;CAAM;CAAO;CAAM;CAAM,CAAC;AAE/D,MAAa,iCAAiC,iBAC5C,kCACA;CACE,MAAM,EACJ,aAAa,2EACd;CACD,UAAU;EACR,UAAU;EACV,YAAY;EACb;CACF,GACA,aAAa,EACZ,iBAAiB,MAAW;AAC1B,KAAI,CAAC,oBAAoB,IAAI,KAAK,SAAS,CACzC;CAGF,MAAM,QACJ,wBAAwB,QAAQ,YAAY,KAAK,MAAM,KAAK,MAAM,IAClE,wBAAwB,QAAQ,YAAY,KAAK,OAAO,KAAK,KAAK;AACpE,KAAI,CAAC,MACH;AAGF,SAAQ,OAAO;EACb;EACA,WAAW;EACZ,CAAC;GAEL,EACF;AAED,SAAS,wBACP,YACA,WACA,UACuC;CACvC,MAAM,UAAU,qBAAqB,UAAU;AAC/C,KAAI,SAAS,SAAS,iBACpB;AAGF,KAAI,mBAAmB,QAAQ,KAAK,aAAa,cAAc,SAAS,CACtE,QAAO;AAGT,KAAI,mBAAmB,QAAQ,KAAK,QAClC;CAGF,MAAM,CAAC,OAAO,OAAO,QAAQ;AAC7B,KAAI,cAAc,MAAM,IAAI,OAAO,iBAAiB,KAAK,UAAU,WAAW,CAC5E,QAAO;CAGT,MAAM,SAAS,qBAAqB,MAAM;AAC1C,KAAI,CAAC,OAAO,UAAU,eAAe,QAAQ,UAAU,WAAW,CAChE,QAAO;;AAMX,SAAS,iBAAiB,YAAiB,UAAe,YAA0B;AAClF,KAAI,mBAAmB,WAAW,KAAK,SACrC,QAAO;CAET,MAAM,SAAS,aAAa,WAAW;AACvC,QAAO,SAAS,eAAe,QAAQ,UAAU,WAAW,GAAG;;AAGjE,SAAS,qBAAqB,MAAgB;CAC5C,MAAM,UAAU,qBAAqB,KAAK;AAC1C,KAAI,SAAS,SAAS,qBAAqB,QAAQ,aAAa,IAC9D;CAEF,MAAM,SAAS,aAAa,QAAQ,SAAS;AAC7C,KAAI,CAAC,UAAU,mBAAmB,QAAQ,SAAS,KAAK,SACtD;AAEF,QAAO;;AAGT,SAAS,eAAe,MAAW,OAAY,YAA0B;AACvE,QACE,WAAW,QAAQ,qBAAqB,KAAK,CAAC,KAC9C,WAAW,QAAQ,qBAAqB,MAAM,CAAC"}
@@ -0,0 +1,16 @@
1
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/require_array_sort_compare.d.ts
2
+ declare const requireArraySortCompareRule: {
3
+ defaultOptions: never[];
4
+ meta: {
5
+ docs: {
6
+ requiresTypeChecking: boolean;
7
+ url: string;
8
+ };
9
+ type: "problem";
10
+ schema: never[];
11
+ };
12
+ create: (context: any) => Record<string, (node: any) => void>;
13
+ };
14
+ //#endregion
15
+ export { requireArraySortCompareRule };
16
+ //# sourceMappingURL=require_array_sort_compare.d.ts.map
@@ -0,0 +1,36 @@
1
+ import { memberObject, memberPropertyName } from "./ast.js";
2
+ import { createNativeRule } from "./rule_creator.js";
3
+ import { isArrayLikeNode, typeTextsAtNode } from "./type_utils.js";
4
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/require_array_sort_compare.ts
5
+ const defaults = { ignoreStringArrays: true };
6
+ const requireArraySortCompareRule = createNativeRule("require-array-sort-compare", {
7
+ docs: { description: "Require compare callbacks for array sorting calls." },
8
+ messages: { requireCompare: "Require a compare argument for array sorting." },
9
+ schema: { type: "array" }
10
+ }, (context) => ({ CallExpression(node) {
11
+ if (node.arguments.length !== 0) return;
12
+ const methodName = memberPropertyName(node.callee);
13
+ if (methodName !== "sort" && methodName !== "toSorted") return;
14
+ const object = memberObject(node.callee);
15
+ if (!object || !isArrayLikeNode(context, object)) return;
16
+ if (resolveOptions(context.options).ignoreStringArrays && isStringArrayLike(context, object)) return;
17
+ context.report({
18
+ node,
19
+ messageId: "requireCompare"
20
+ });
21
+ } }));
22
+ function isStringArrayLike(context, node) {
23
+ return typeTextsAtNode(context, node).some((text) => {
24
+ return text === "string[]" || text === "readonly string[]" || text.startsWith("Array<string>") || text.startsWith("ReadonlyArray<string>");
25
+ });
26
+ }
27
+ function resolveOptions(options) {
28
+ return {
29
+ ...defaults,
30
+ ...options[0]
31
+ };
32
+ }
33
+ //#endregion
34
+ export { requireArraySortCompareRule };
35
+
36
+ //# sourceMappingURL=require_array_sort_compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require_array_sort_compare.js","names":[],"sources":["../../ts/rules/require_array_sort_compare.ts"],"sourcesContent":["import { memberObject, memberPropertyName } from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport { isArrayLikeNode, typeTextsAtNode } from \"./type_utils\";\n\ntype Options = {\n ignoreStringArrays?: boolean;\n};\n\nconst defaults: Required<Options> = {\n ignoreStringArrays: true,\n};\n\nexport const requireArraySortCompareRule = createNativeRule(\n \"require-array-sort-compare\",\n {\n docs: {\n description: \"Require compare callbacks for array sorting calls.\",\n },\n messages: {\n requireCompare: \"Require a compare argument for array sorting.\",\n },\n schema: { type: \"array\" },\n },\n (context) => ({\n CallExpression(node: any) {\n if (node.arguments.length !== 0) {\n return;\n }\n const methodName = memberPropertyName(node.callee);\n if (methodName !== \"sort\" && methodName !== \"toSorted\") {\n return;\n }\n const object = memberObject(node.callee) as any;\n if (!object || !isArrayLikeNode(context, object)) {\n return;\n }\n if (\n resolveOptions(context.options).ignoreStringArrays &&\n isStringArrayLike(context, object)\n ) {\n return;\n }\n context.report({ node, messageId: \"requireCompare\" });\n },\n }),\n);\n\nfunction isStringArrayLike(context: any, node: any): boolean {\n return typeTextsAtNode(context, node).some((text) => {\n return (\n text === \"string[]\" ||\n text === \"readonly string[]\" ||\n text.startsWith(\"Array<string>\") ||\n text.startsWith(\"ReadonlyArray<string>\")\n );\n });\n}\n\nfunction resolveOptions(options: readonly unknown[]): Required<Options> {\n return { ...defaults, ...(options[0] as Options | undefined) };\n}\n"],"mappings":";;;;AAQA,MAAM,WAA8B,EAClC,oBAAoB,MACrB;AAED,MAAa,8BAA8B,iBACzC,8BACA;CACE,MAAM,EACJ,aAAa,sDACd;CACD,UAAU,EACR,gBAAgB,iDACjB;CACD,QAAQ,EAAE,MAAM,SAAS;CAC1B,GACA,aAAa,EACZ,eAAe,MAAW;AACxB,KAAI,KAAK,UAAU,WAAW,EAC5B;CAEF,MAAM,aAAa,mBAAmB,KAAK,OAAO;AAClD,KAAI,eAAe,UAAU,eAAe,WAC1C;CAEF,MAAM,SAAS,aAAa,KAAK,OAAO;AACxC,KAAI,CAAC,UAAU,CAAC,gBAAgB,SAAS,OAAO,CAC9C;AAEF,KACE,eAAe,QAAQ,QAAQ,CAAC,sBAChC,kBAAkB,SAAS,OAAO,CAElC;AAEF,SAAQ,OAAO;EAAE;EAAM,WAAW;EAAkB,CAAC;GAExD,EACF;AAED,SAAS,kBAAkB,SAAc,MAAoB;AAC3D,QAAO,gBAAgB,SAAS,KAAK,CAAC,MAAM,SAAS;AACnD,SACE,SAAS,cACT,SAAS,uBACT,KAAK,WAAW,gBAAgB,IAChC,KAAK,WAAW,wBAAwB;GAE1C;;AAGJ,SAAS,eAAe,SAAgD;AACtE,QAAO;EAAE,GAAG;EAAU,GAAI,QAAQ;EAA4B"}
@@ -0,0 +1,16 @@
1
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/restrict_plus_operands.d.ts
2
+ declare const restrictPlusOperandsRule: {
3
+ defaultOptions: never[];
4
+ meta: {
5
+ docs: {
6
+ requiresTypeChecking: boolean;
7
+ url: string;
8
+ };
9
+ type: "problem";
10
+ schema: never[];
11
+ };
12
+ create: (context: any) => Record<string, (node: any) => void>;
13
+ };
14
+ //#endregion
15
+ export { restrictPlusOperandsRule };
16
+ //# sourceMappingURL=restrict_plus_operands.d.ts.map
@@ -0,0 +1,62 @@
1
+ import { createNativeRule } from "./rule_creator.js";
2
+ import { classifyTypeText, typeTextAtNode } from "./type_utils.js";
3
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/restrict_plus_operands.ts
4
+ const defaults = {
5
+ allowAny: true,
6
+ allowBoolean: true,
7
+ allowNullish: true,
8
+ allowNumberAndString: true,
9
+ allowRegExp: false,
10
+ skipCompoundAssignments: false
11
+ };
12
+ const restrictPlusOperandsRule = createNativeRule("restrict-plus-operands", {
13
+ docs: { description: "Require plus operands to be explicitly compatible." },
14
+ messages: {
15
+ invalid: "Operands of + must be compatible primitive values.",
16
+ mismatched: "Operands of + operations must be of the same type."
17
+ },
18
+ schema: { type: "array" }
19
+ }, (context) => ({
20
+ AssignmentExpression(node) {
21
+ const options = resolveOptions(context.options);
22
+ if (options.skipCompoundAssignments || node.operator !== "+=") return;
23
+ reportIfInvalid(context, node, node.left, node.right, options);
24
+ },
25
+ BinaryExpression(node) {
26
+ if (node.operator !== "+") return;
27
+ reportIfInvalid(context, node, node.left, node.right, resolveOptions(context.options));
28
+ }
29
+ }));
30
+ function reportIfInvalid(context, node, left, right, options) {
31
+ const leftKind = classifyTypeText(typeTextAtNode(context, left));
32
+ const rightKind = classifyTypeText(typeTextAtNode(context, right));
33
+ if (isAllowed(leftKind, rightKind, options)) return;
34
+ context.report({
35
+ node,
36
+ messageId: leftKind === "other" || rightKind === "other" || leftKind === "unknown" || rightKind === "unknown" ? "invalid" : "mismatched"
37
+ });
38
+ }
39
+ function isAllowed(leftKind, rightKind, options) {
40
+ if (leftKind === rightKind && [
41
+ "bigint",
42
+ "number",
43
+ "string"
44
+ ].includes(leftKind)) return true;
45
+ if (options.allowNumberAndString && (leftKind === "string" && rightKind === "number" || leftKind === "number" && rightKind === "string")) return true;
46
+ if (leftKind === "string" && isStringCompanion(rightKind, options)) return true;
47
+ if (rightKind === "string" && isStringCompanion(leftKind, options)) return true;
48
+ return false;
49
+ }
50
+ function isStringCompanion(kind, options) {
51
+ return kind === "any" && options.allowAny || kind === "boolean" && options.allowBoolean || kind === "nullish" && options.allowNullish || kind === "regexp" && options.allowRegExp;
52
+ }
53
+ function resolveOptions(options) {
54
+ return {
55
+ ...defaults,
56
+ ...options[0]
57
+ };
58
+ }
59
+ //#endregion
60
+ export { restrictPlusOperandsRule };
61
+
62
+ //# sourceMappingURL=restrict_plus_operands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restrict_plus_operands.js","names":[],"sources":["../../ts/rules/restrict_plus_operands.ts"],"sourcesContent":["import { createNativeRule } from \"./rule_creator\";\nimport { classifyTypeText, typeTextAtNode } from \"./type_utils\";\n\ntype Options = {\n allowAny?: boolean;\n allowBoolean?: boolean;\n allowNullish?: boolean;\n allowNumberAndString?: boolean;\n allowRegExp?: boolean;\n skipCompoundAssignments?: boolean;\n};\n\nconst defaults: Required<Options> = {\n allowAny: true,\n allowBoolean: true,\n allowNullish: true,\n allowNumberAndString: true,\n allowRegExp: false,\n skipCompoundAssignments: false,\n};\n\nexport const restrictPlusOperandsRule = createNativeRule(\n \"restrict-plus-operands\",\n {\n docs: {\n description: \"Require plus operands to be explicitly compatible.\",\n },\n messages: {\n invalid: \"Operands of + must be compatible primitive values.\",\n mismatched: \"Operands of + operations must be of the same type.\",\n },\n schema: { type: \"array\" },\n },\n (context) => ({\n AssignmentExpression(node: any) {\n const options = resolveOptions(context.options);\n if (options.skipCompoundAssignments || node.operator !== \"+=\") {\n return;\n }\n reportIfInvalid(context, node, node.left, node.right, options);\n },\n BinaryExpression(node: any) {\n if (node.operator !== \"+\") {\n return;\n }\n reportIfInvalid(context, node, node.left, node.right, resolveOptions(context.options));\n },\n }),\n);\n\nfunction reportIfInvalid(\n context: any,\n node: any,\n left: any,\n right: any,\n options: Required<Options>,\n) {\n const leftKind = classifyTypeText(typeTextAtNode(context, left));\n const rightKind = classifyTypeText(typeTextAtNode(context, right));\n if (isAllowed(leftKind, rightKind, options)) {\n return;\n }\n context.report({\n node,\n messageId:\n leftKind === \"other\" ||\n rightKind === \"other\" ||\n leftKind === \"unknown\" ||\n rightKind === \"unknown\"\n ? \"invalid\"\n : \"mismatched\",\n });\n}\n\nfunction isAllowed(\n leftKind: ReturnType<typeof classifyTypeText>,\n rightKind: ReturnType<typeof classifyTypeText>,\n options: Required<Options>,\n): boolean {\n if (leftKind === rightKind && [\"bigint\", \"number\", \"string\"].includes(leftKind)) {\n return true;\n }\n if (\n options.allowNumberAndString &&\n ((leftKind === \"string\" && rightKind === \"number\") ||\n (leftKind === \"number\" && rightKind === \"string\"))\n ) {\n return true;\n }\n if (leftKind === \"string\" && isStringCompanion(rightKind, options)) {\n return true;\n }\n if (rightKind === \"string\" && isStringCompanion(leftKind, options)) {\n return true;\n }\n return false;\n}\n\nfunction isStringCompanion(\n kind: ReturnType<typeof classifyTypeText>,\n options: Required<Options>,\n): boolean {\n return (\n (kind === \"any\" && options.allowAny) ||\n (kind === \"boolean\" && options.allowBoolean) ||\n (kind === \"nullish\" && options.allowNullish) ||\n (kind === \"regexp\" && options.allowRegExp)\n );\n}\n\nfunction resolveOptions(options: readonly unknown[]): Required<Options> {\n return { ...defaults, ...(options[0] as Options | undefined) };\n}\n"],"mappings":";;;AAYA,MAAM,WAA8B;CAClC,UAAU;CACV,cAAc;CACd,cAAc;CACd,sBAAsB;CACtB,aAAa;CACb,yBAAyB;CAC1B;AAED,MAAa,2BAA2B,iBACtC,0BACA;CACE,MAAM,EACJ,aAAa,sDACd;CACD,UAAU;EACR,SAAS;EACT,YAAY;EACb;CACD,QAAQ,EAAE,MAAM,SAAS;CAC1B,GACA,aAAa;CACZ,qBAAqB,MAAW;EAC9B,MAAM,UAAU,eAAe,QAAQ,QAAQ;AAC/C,MAAI,QAAQ,2BAA2B,KAAK,aAAa,KACvD;AAEF,kBAAgB,SAAS,MAAM,KAAK,MAAM,KAAK,OAAO,QAAQ;;CAEhE,iBAAiB,MAAW;AAC1B,MAAI,KAAK,aAAa,IACpB;AAEF,kBAAgB,SAAS,MAAM,KAAK,MAAM,KAAK,OAAO,eAAe,QAAQ,QAAQ,CAAC;;CAEzF,EACF;AAED,SAAS,gBACP,SACA,MACA,MACA,OACA,SACA;CACA,MAAM,WAAW,iBAAiB,eAAe,SAAS,KAAK,CAAC;CAChE,MAAM,YAAY,iBAAiB,eAAe,SAAS,MAAM,CAAC;AAClE,KAAI,UAAU,UAAU,WAAW,QAAQ,CACzC;AAEF,SAAQ,OAAO;EACb;EACA,WACE,aAAa,WACb,cAAc,WACd,aAAa,aACb,cAAc,YACV,YACA;EACP,CAAC;;AAGJ,SAAS,UACP,UACA,WACA,SACS;AACT,KAAI,aAAa,aAAa;EAAC;EAAU;EAAU;EAAS,CAAC,SAAS,SAAS,CAC7E,QAAO;AAET,KACE,QAAQ,yBACN,aAAa,YAAY,cAAc,YACtC,aAAa,YAAY,cAAc,UAE1C,QAAO;AAET,KAAI,aAAa,YAAY,kBAAkB,WAAW,QAAQ,CAChE,QAAO;AAET,KAAI,cAAc,YAAY,kBAAkB,UAAU,QAAQ,CAChE,QAAO;AAET,QAAO;;AAGT,SAAS,kBACP,MACA,SACS;AACT,QACG,SAAS,SAAS,QAAQ,YAC1B,SAAS,aAAa,QAAQ,gBAC9B,SAAS,aAAa,QAAQ,gBAC9B,SAAS,YAAY,QAAQ;;AAIlC,SAAS,eAAe,SAAgD;AACtE,QAAO;EAAE,GAAG;EAAU,GAAI,QAAQ;EAA4B"}
@@ -0,0 +1,16 @@
1
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/rule_creator.d.ts
2
+ declare function createNativeRule(name: string, meta: Record<string, unknown>, create: (context: any) => Record<string, (node: any) => void>): {
3
+ defaultOptions: never[];
4
+ meta: {
5
+ docs: {
6
+ requiresTypeChecking: boolean;
7
+ url: string;
8
+ };
9
+ type: "problem";
10
+ schema: never[];
11
+ };
12
+ create: (context: any) => Record<string, (node: any) => void>;
13
+ };
14
+ //#endregion
15
+ export { createNativeRule };
16
+ //# sourceMappingURL=rule_creator.d.ts.map
@@ -0,0 +1,22 @@
1
+ import { defineRule } from "../plugin.js";
2
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/rule_creator.ts
3
+ function createNativeRule(name, meta, create) {
4
+ return defineRule({
5
+ defaultOptions: [],
6
+ meta: {
7
+ type: "problem",
8
+ schema: [],
9
+ ...meta,
10
+ docs: {
11
+ requiresTypeChecking: true,
12
+ url: `https://github.com/ubugeeei/corsa-bind/tree/main/src/bindings/nodejs/typescript_oxlint/ts/rules/${name.replaceAll("-", "_")}.ts`,
13
+ ...meta.docs
14
+ }
15
+ },
16
+ create
17
+ });
18
+ }
19
+ //#endregion
20
+ export { createNativeRule };
21
+
22
+ //# sourceMappingURL=rule_creator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule_creator.js","names":[],"sources":["../../ts/rules/rule_creator.ts"],"sourcesContent":["import { defineRule } from \"../plugin\";\n\nexport function createNativeRule(\n name: string,\n meta: Record<string, unknown>,\n create: (context: any) => Record<string, (node: any) => void>,\n) {\n return defineRule({\n defaultOptions: [],\n meta: {\n type: \"problem\",\n schema: [],\n ...meta,\n docs: {\n requiresTypeChecking: true,\n url: `https://github.com/ubugeeei/corsa-bind/tree/main/src/bindings/nodejs/typescript_oxlint/ts/rules/${name.replaceAll(\"-\", \"_\")}.ts`,\n ...(meta.docs as object | undefined),\n },\n },\n create,\n });\n}\n"],"mappings":";;AAEA,SAAgB,iBACd,MACA,MACA,QACA;AACA,QAAO,WAAW;EAChB,gBAAgB,EAAE;EAClB,MAAM;GACJ,MAAM;GACN,QAAQ,EAAE;GACV,GAAG;GACH,MAAM;IACJ,sBAAsB;IACtB,KAAK,mGAAmG,KAAK,WAAW,KAAK,IAAI,CAAC;IAClI,GAAI,KAAK;IACV;GACF;EACD;EACD,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { ContextWithParserOptions, TsgoType, TsgoTypeCheckerShape } from "../types.js";
2
+ import { Node } from "@oxlint/plugins";
3
+
4
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/type_utils.d.ts
5
+ declare function checkerFor(context: ContextWithParserOptions): TsgoTypeCheckerShape;
6
+ declare function typeAtNode(context: ContextWithParserOptions, node: Node | {
7
+ readonly range: readonly [number, number];
8
+ }): TsgoType | undefined;
9
+ declare function baseTypeAtNode(context: ContextWithParserOptions, node: Node | {
10
+ readonly range: readonly [number, number];
11
+ }): TsgoType | undefined;
12
+ declare function symbolTypeAtNode(context: ContextWithParserOptions, node: Node | {
13
+ readonly range: readonly [number, number];
14
+ }): TsgoType | undefined;
15
+ declare function typeTextAtNode(context: ContextWithParserOptions, node: Node | {
16
+ readonly range: readonly [number, number];
17
+ }): string | undefined;
18
+ declare function symbolTypeTextAtNode(context: ContextWithParserOptions, node: Node | {
19
+ readonly range: readonly [number, number];
20
+ }): string | undefined;
21
+ declare function propertyNamesOfNode(context: ContextWithParserOptions, node: Node | {
22
+ readonly range: readonly [number, number];
23
+ }): readonly string[];
24
+ declare function isPromiseLikeNode(context: ContextWithParserOptions, node: Node | {
25
+ readonly range: readonly [number, number];
26
+ }): boolean;
27
+ declare function isArrayLikeNode(context: ContextWithParserOptions, node: Node | {
28
+ readonly range: readonly [number, number];
29
+ }): boolean;
30
+ declare function isStringLikeNode(context: ContextWithParserOptions, node: Node | {
31
+ readonly range: readonly [number, number];
32
+ }): boolean;
33
+ declare function isErrorLikeNode(context: ContextWithParserOptions, node: Node | {
34
+ readonly range: readonly [number, number];
35
+ }): boolean;
36
+ declare function isNumberLikeNode(context: ContextWithParserOptions, node: Node | {
37
+ readonly range: readonly [number, number];
38
+ }): boolean;
39
+ declare function isBigIntLikeNode(context: ContextWithParserOptions, node: Node | {
40
+ readonly range: readonly [number, number];
41
+ }): boolean;
42
+ declare function isAnyLikeNode(context: ContextWithParserOptions, node: Node | {
43
+ readonly range: readonly [number, number];
44
+ }): boolean;
45
+ declare function isUnknownLikeNode(context: ContextWithParserOptions, node: Node | {
46
+ readonly range: readonly [number, number];
47
+ }): boolean;
48
+ declare function typeTextsAtNode(context: ContextWithParserOptions, node: Node | {
49
+ readonly range: readonly [number, number];
50
+ }): readonly string[];
51
+ declare function classifyTypeText(text: string | undefined): "any" | "bigint" | "boolean" | "nullish" | "number" | "regexp" | "string" | "unknown" | "other";
52
+ declare function splitTopLevelTypeText(text: string, delimiter: "|" | "&" | ","): readonly string[];
53
+ declare function splitTypeText(text: string): readonly string[];
54
+ //#endregion
55
+ export { baseTypeAtNode, checkerFor, classifyTypeText, isAnyLikeNode, isArrayLikeNode, isBigIntLikeNode, isErrorLikeNode, isNumberLikeNode, isPromiseLikeNode, isStringLikeNode, isUnknownLikeNode, propertyNamesOfNode, splitTopLevelTypeText, splitTypeText, symbolTypeAtNode, symbolTypeTextAtNode, typeAtNode, typeTextAtNode, typeTextsAtNode };
56
+ //# sourceMappingURL=type_utils.d.ts.map
@@ -0,0 +1,102 @@
1
+ import { ESLintUtils } from "../eslint_utils.js";
2
+ import { classifyTypeText as classifyTypeText$1, isAnyLikeTypeTexts, isArrayLikeTypeTexts, isBigIntLikeTypeTexts, isErrorLikeTypeTexts, isNumberLikeTypeTexts, isPromiseLikeTypeTexts, isStringLikeTypeTexts, isUnknownLikeTypeTexts, splitTopLevelTypeText as splitTopLevelTypeText$1, splitTypeText as splitTypeText$1 } from "../utils.js";
3
+ import { isIdentifierNamed, memberPropertyName, stripChainExpression } from "./ast.js";
4
+ //#region src/bindings/nodejs/typescript_oxlint/ts/rules/type_utils.ts
5
+ function checkerFor(context) {
6
+ return ESLintUtils.getParserServices(context).program.getTypeChecker();
7
+ }
8
+ function typeAtNode(context, node) {
9
+ return checkerFor(context).getTypeAtLocation(node);
10
+ }
11
+ function baseTypeAtNode(context, node) {
12
+ const type = typeAtNode(context, node);
13
+ if (!type) return;
14
+ return checkerFor(context).getBaseTypeOfLiteralType(type) ?? type;
15
+ }
16
+ function symbolTypeAtNode(context, node) {
17
+ const checker = checkerFor(context);
18
+ const symbol = checker.getSymbolAtLocation(node);
19
+ if (!symbol) return;
20
+ return checker.getTypeOfSymbol(symbol) ?? checker.getDeclaredTypeOfSymbol(symbol);
21
+ }
22
+ function typeTextAtNode(context, node) {
23
+ const type = baseTypeAtNode(context, node);
24
+ return type ? checkerFor(context).typeToString(type) : void 0;
25
+ }
26
+ function symbolTypeTextAtNode(context, node) {
27
+ const type = symbolTypeAtNode(context, node);
28
+ if (!type) return;
29
+ const checker = checkerFor(context);
30
+ return checker.typeToString(checker.getBaseTypeOfLiteralType(type) ?? type);
31
+ }
32
+ function propertyNamesOfNode(context, node) {
33
+ const checker = checkerFor(context);
34
+ const names = /* @__PURE__ */ new Set();
35
+ for (const type of [baseTypeAtNode(context, node), symbolTypeAtNode(context, node)]) {
36
+ if (!type) continue;
37
+ for (const property of checker.getPropertiesOfType(type)) names.add(property.name);
38
+ }
39
+ return [...names];
40
+ }
41
+ function isPromiseLikeNode(context, node) {
42
+ const current = stripChainExpression(node);
43
+ if (current?.type === "NewExpression" && isIdentifierNamed(current.callee, "Promise")) return true;
44
+ if (current?.type === "CallExpression" && memberPropertyName(current.callee) === "resolve" && isIdentifierNamed(current.callee.object, "Promise")) return true;
45
+ return isPromiseLikeTypeTexts([typeTextAtNode(context, node), symbolTypeTextAtNode(context, node)].filter((text) => Boolean(text)), propertyNamesOfNode(context, node));
46
+ }
47
+ function isArrayLikeNode(context, node) {
48
+ if (stripChainExpression(node)?.type === "ArrayExpression") return true;
49
+ return isArrayLikeTypeTexts(typeTextsAtNode(context, node));
50
+ }
51
+ function isStringLikeNode(context, node) {
52
+ return isStringLikeTypeTexts(typeTextsAtNode(context, node));
53
+ }
54
+ function isErrorLikeNode(context, node) {
55
+ const current = stripChainExpression(node);
56
+ if (current?.type === "NewExpression") {
57
+ const callee = stripChainExpression(current.callee);
58
+ if ((callee?.type === "Identifier" ? callee.name : memberPropertyName(callee))?.endsWith("Error")) return true;
59
+ }
60
+ return isErrorLikeTypeTexts(typeTextsAtNode(context, node), propertyNamesOfNode(context, node));
61
+ }
62
+ function isNumberLikeNode(context, node) {
63
+ return isNumberLikeTypeTexts(typeTextsAtNode(context, node));
64
+ }
65
+ function isBigIntLikeNode(context, node) {
66
+ return isBigIntLikeTypeTexts(typeTextsAtNode(context, node));
67
+ }
68
+ function isAnyLikeNode(context, node) {
69
+ const current = stripChainExpression(node);
70
+ if (current?.type === "TSAsExpression" && current.typeAnnotation?.type === "TSAnyKeyword") return true;
71
+ return isAnyLikeTypeTexts(typeTextsAtNode(context, node));
72
+ }
73
+ function isUnknownLikeNode(context, node) {
74
+ const current = stripChainExpression(node);
75
+ if (current?.type === "TSAsExpression" && current.typeAnnotation?.type === "TSUnknownKeyword") return true;
76
+ return isUnknownLikeTypeTexts(typeTextsAtNode(context, node));
77
+ }
78
+ function typeTextsAtNode(context, node) {
79
+ const values = /* @__PURE__ */ new Set();
80
+ const checker = checkerFor(context);
81
+ collectTexts(baseTypeAtNode(context, node));
82
+ collectTexts(symbolTypeAtNode(context, node));
83
+ return [...values];
84
+ function collectTexts(type) {
85
+ if (!type) return;
86
+ const texts = Array.isArray(type.texts) ? type.texts : [];
87
+ for (const text of [...texts, checker.typeToString(type)]) if (text) values.add(text);
88
+ }
89
+ }
90
+ function classifyTypeText(text) {
91
+ return classifyTypeText$1(text);
92
+ }
93
+ function splitTopLevelTypeText(text, delimiter) {
94
+ return splitTopLevelTypeText$1(text, delimiter);
95
+ }
96
+ function splitTypeText(text) {
97
+ return splitTypeText$1(text);
98
+ }
99
+ //#endregion
100
+ export { baseTypeAtNode, checkerFor, classifyTypeText, isAnyLikeNode, isArrayLikeNode, isBigIntLikeNode, isErrorLikeNode, isNumberLikeNode, isPromiseLikeNode, isStringLikeNode, isUnknownLikeNode, propertyNamesOfNode, splitTopLevelTypeText, splitTypeText, symbolTypeAtNode, symbolTypeTextAtNode, typeAtNode, typeTextAtNode, typeTextsAtNode };
101
+
102
+ //# sourceMappingURL=type_utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type_utils.js","names":["classifyTypeTextFromRust","splitTopLevelTypeTextFromRust","splitTypeTextFromRust"],"sources":["../../ts/rules/type_utils.ts"],"sourcesContent":["import type { Node } from \"@oxlint/plugins\";\n\nimport { ESLintUtils } from \"../eslint_utils\";\nimport {\n classifyTypeText as classifyTypeTextFromRust,\n isAnyLikeTypeTexts,\n isArrayLikeTypeTexts,\n isBigIntLikeTypeTexts,\n isErrorLikeTypeTexts,\n isNumberLikeTypeTexts,\n isPromiseLikeTypeTexts,\n isStringLikeTypeTexts,\n isUnknownLikeTypeTexts,\n splitTopLevelTypeText as splitTopLevelTypeTextFromRust,\n splitTypeText as splitTypeTextFromRust,\n} from \"../utils\";\nimport { isIdentifierNamed, memberPropertyName, stripChainExpression } from \"./ast\";\nimport type { ContextWithParserOptions, TsgoType, TsgoTypeCheckerShape } from \"../types\";\n\nexport function checkerFor(context: ContextWithParserOptions): TsgoTypeCheckerShape {\n return ESLintUtils.getParserServices(context).program.getTypeChecker();\n}\n\nexport function typeAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): TsgoType | undefined {\n return checkerFor(context).getTypeAtLocation(node as Node);\n}\n\nexport function baseTypeAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): TsgoType | undefined {\n const type = typeAtNode(context, node);\n if (!type) {\n return undefined;\n }\n return checkerFor(context).getBaseTypeOfLiteralType(type) ?? type;\n}\n\nexport function symbolTypeAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): TsgoType | undefined {\n const checker = checkerFor(context);\n const symbol = checker.getSymbolAtLocation(node as Node);\n if (!symbol) {\n return undefined;\n }\n return checker.getTypeOfSymbol(symbol) ?? checker.getDeclaredTypeOfSymbol(symbol);\n}\n\nexport function typeTextAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): string | undefined {\n const type = baseTypeAtNode(context, node);\n return type ? checkerFor(context).typeToString(type) : undefined;\n}\n\nexport function symbolTypeTextAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): string | undefined {\n const type = symbolTypeAtNode(context, node);\n if (!type) {\n return undefined;\n }\n const checker = checkerFor(context);\n return checker.typeToString(checker.getBaseTypeOfLiteralType(type) ?? type);\n}\n\nexport function propertyNamesOfNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): readonly string[] {\n const checker = checkerFor(context);\n const names = new Set<string>();\n for (const type of [baseTypeAtNode(context, node), symbolTypeAtNode(context, node)]) {\n if (!type) {\n continue;\n }\n for (const property of checker.getPropertiesOfType(type)) {\n names.add(property.name);\n }\n }\n return [...names];\n}\n\nexport function isPromiseLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"NewExpression\" && isIdentifierNamed(current.callee, \"Promise\")) {\n return true;\n }\n if (\n current?.type === \"CallExpression\" &&\n memberPropertyName(current.callee) === \"resolve\" &&\n isIdentifierNamed((current.callee as any).object, \"Promise\")\n ) {\n return true;\n }\n return isPromiseLikeTypeTexts(\n [typeTextAtNode(context, node), symbolTypeTextAtNode(context, node)].filter(\n (text): text is string => Boolean(text),\n ),\n propertyNamesOfNode(context, node),\n );\n}\n\nexport function isArrayLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"ArrayExpression\") {\n return true;\n }\n return isArrayLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isStringLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n return isStringLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isErrorLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"NewExpression\") {\n const callee = stripChainExpression(current.callee);\n const identifier = callee?.type === \"Identifier\" ? callee.name : memberPropertyName(callee);\n if (identifier?.endsWith(\"Error\")) {\n return true;\n }\n }\n return isErrorLikeTypeTexts(typeTextsAtNode(context, node), propertyNamesOfNode(context, node));\n}\n\nexport function isNumberLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n return isNumberLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isBigIntLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n return isBigIntLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isAnyLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"TSAsExpression\" && current.typeAnnotation?.type === \"TSAnyKeyword\") {\n return true;\n }\n return isAnyLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isUnknownLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"TSAsExpression\" && current.typeAnnotation?.type === \"TSUnknownKeyword\") {\n return true;\n }\n return isUnknownLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function typeTextsAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): readonly string[] {\n const values = new Set<string>();\n const checker = checkerFor(context);\n collectTexts(baseTypeAtNode(context, node));\n collectTexts(symbolTypeAtNode(context, node));\n return [...values];\n\n function collectTexts(type: TsgoType | undefined): void {\n if (!type) {\n return;\n }\n const texts = Array.isArray(type.texts) ? type.texts : [];\n for (const text of [...texts, checker.typeToString(type)]) {\n if (text) {\n values.add(text);\n }\n }\n }\n}\n\nexport function classifyTypeText(\n text: string | undefined,\n): \"any\" | \"bigint\" | \"boolean\" | \"nullish\" | \"number\" | \"regexp\" | \"string\" | \"unknown\" | \"other\" {\n return classifyTypeTextFromRust(text);\n}\n\nexport function splitTopLevelTypeText(text: string, delimiter: \"|\" | \"&\" | \",\"): readonly string[] {\n return splitTopLevelTypeTextFromRust(text, delimiter);\n}\n\nexport function splitTypeText(text: string): readonly string[] {\n return splitTypeTextFromRust(text);\n}\n"],"mappings":"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"}