@ttsc/lint 0.13.0 → 0.14.0-dev.20260528

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 (467) hide show
  1. package/README.md +948 -69
  2. package/lib/defaultFormat.d.ts +9 -6
  3. package/lib/defaultFormat.js +9 -6
  4. package/lib/defaultFormat.js.map +1 -1
  5. package/lib/index.d.ts +46 -0
  6. package/lib/index.js +60 -37
  7. package/lib/index.js.map +1 -1
  8. package/lib/structures/ITtscLintConfig.d.ts +12 -6
  9. package/lib/structures/{ITtscLintFormatConfig.d.ts → ITtscLintFormat.d.ts} +2 -2
  10. package/lib/structures/{TtscLintRuleMap.js → ITtscLintFormat.js} +1 -1
  11. package/lib/structures/ITtscLintFormat.js.map +1 -0
  12. package/lib/structures/TtscLintRuleSetting.d.ts +49 -0
  13. package/lib/structures/{TtscLintRuleOptions.js → TtscLintRuleSetting.js} +1 -1
  14. package/lib/structures/TtscLintRuleSetting.js.map +1 -0
  15. package/lib/structures/index.d.ts +3 -4
  16. package/lib/structures/index.js +3 -4
  17. package/lib/structures/index.js.map +1 -1
  18. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +104 -0
  19. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +14 -0
  20. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
  21. package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +79 -0
  22. package/lib/structures/rules/ITtscLintBoundariesRules.js +3 -0
  23. package/lib/structures/rules/ITtscLintBoundariesRules.js.map +1 -0
  24. package/lib/structures/rules/ITtscLintContributorRules.d.ts +17 -0
  25. package/lib/structures/rules/ITtscLintContributorRules.js +3 -0
  26. package/lib/structures/rules/ITtscLintContributorRules.js.map +1 -0
  27. package/lib/structures/rules/ITtscLintCoreRules.d.ts +1257 -0
  28. package/lib/structures/{ITtscLintFormatConfig.js → rules/ITtscLintCoreRules.js} +1 -1
  29. package/lib/structures/rules/ITtscLintCoreRules.js.map +1 -0
  30. package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +17 -0
  31. package/lib/structures/rules/ITtscLintCypressRuleOptions.js +10 -0
  32. package/lib/structures/rules/ITtscLintCypressRuleOptions.js.map +1 -0
  33. package/lib/structures/rules/ITtscLintCypressRules.d.ts +129 -0
  34. package/lib/structures/rules/ITtscLintCypressRules.js +3 -0
  35. package/lib/structures/rules/ITtscLintCypressRules.js.map +1 -0
  36. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +157 -0
  37. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +13 -0
  38. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js.map +1 -0
  39. package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +167 -0
  40. package/lib/structures/rules/ITtscLintFunctionalRules.js +3 -0
  41. package/lib/structures/rules/ITtscLintFunctionalRules.js.map +1 -0
  42. package/lib/structures/rules/ITtscLintJestRules.d.ts +201 -0
  43. package/lib/structures/rules/ITtscLintJestRules.js +3 -0
  44. package/lib/structures/rules/ITtscLintJestRules.js.map +1 -0
  45. package/lib/structures/rules/ITtscLintJsdocRules.d.ts +140 -0
  46. package/lib/structures/rules/ITtscLintJsdocRules.js +3 -0
  47. package/lib/structures/rules/ITtscLintJsdocRules.js.map +1 -0
  48. package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +302 -0
  49. package/lib/structures/rules/ITtscLintJsxA11yRules.js +3 -0
  50. package/lib/structures/rules/ITtscLintJsxA11yRules.js.map +1 -0
  51. package/lib/structures/rules/ITtscLintNextjsRules.d.ts +185 -0
  52. package/lib/structures/rules/ITtscLintNextjsRules.js +3 -0
  53. package/lib/structures/rules/ITtscLintNextjsRules.js.map +1 -0
  54. package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +330 -0
  55. package/lib/structures/rules/ITtscLintPlaywrightRules.js +3 -0
  56. package/lib/structures/rules/ITtscLintPlaywrightRules.js.map +1 -0
  57. package/lib/structures/rules/ITtscLintPromiseRules.d.ts +188 -0
  58. package/lib/structures/rules/ITtscLintPromiseRules.js +3 -0
  59. package/lib/structures/rules/ITtscLintPromiseRules.js.map +1 -0
  60. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +18 -0
  61. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js +8 -0
  62. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js.map +1 -0
  63. package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +51 -0
  64. package/lib/structures/rules/ITtscLintReactPerfRules.js +3 -0
  65. package/lib/structures/rules/ITtscLintReactPerfRules.js.map +1 -0
  66. package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +39 -0
  67. package/lib/structures/rules/ITtscLintReactRuleOptions.js +12 -0
  68. package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
  69. package/lib/structures/rules/ITtscLintReactRules.d.ts +289 -0
  70. package/lib/structures/rules/ITtscLintReactRules.js +3 -0
  71. package/lib/structures/rules/ITtscLintReactRules.js.map +1 -0
  72. package/lib/structures/rules/ITtscLintRegexpRules.d.ts +190 -0
  73. package/lib/structures/rules/ITtscLintRegexpRules.js +3 -0
  74. package/lib/structures/rules/ITtscLintRegexpRules.js.map +1 -0
  75. package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +66 -0
  76. package/lib/structures/rules/ITtscLintRuleOptionsMap.js +3 -0
  77. package/lib/structures/rules/ITtscLintRuleOptionsMap.js.map +1 -0
  78. package/lib/structures/rules/ITtscLintRules.d.ts +55 -0
  79. package/lib/structures/{TtscLintRule.js → rules/ITtscLintRules.js} +1 -1
  80. package/lib/structures/rules/ITtscLintRules.js.map +1 -0
  81. package/lib/structures/rules/ITtscLintSecurityRules.d.ts +148 -0
  82. package/lib/structures/rules/ITtscLintSecurityRules.js +3 -0
  83. package/lib/structures/rules/ITtscLintSecurityRules.js.map +1 -0
  84. package/lib/structures/rules/ITtscLintSolidRules.d.ts +181 -0
  85. package/lib/structures/rules/ITtscLintSolidRules.js +3 -0
  86. package/lib/structures/rules/ITtscLintSolidRules.js.map +1 -0
  87. package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +21 -0
  88. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js +9 -0
  89. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js.map +1 -0
  90. package/lib/structures/rules/ITtscLintStorybookRules.d.ts +174 -0
  91. package/lib/structures/rules/ITtscLintStorybookRules.js +3 -0
  92. package/lib/structures/rules/ITtscLintStorybookRules.js.map +1 -0
  93. package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +94 -0
  94. package/lib/structures/rules/ITtscLintTanstackQueryRules.js +3 -0
  95. package/lib/structures/rules/ITtscLintTanstackQueryRules.js.map +1 -0
  96. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +22 -0
  97. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js +10 -0
  98. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js.map +1 -0
  99. package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +310 -0
  100. package/lib/structures/rules/ITtscLintTestingLibraryRules.js +3 -0
  101. package/lib/structures/rules/ITtscLintTestingLibraryRules.js.map +1 -0
  102. package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +1132 -0
  103. package/lib/structures/rules/ITtscLintTypeScriptRules.js +3 -0
  104. package/lib/structures/rules/ITtscLintTypeScriptRules.js.map +1 -0
  105. package/lib/structures/rules/ITtscLintUnicornRules.d.ts +997 -0
  106. package/lib/structures/rules/ITtscLintUnicornRules.js +3 -0
  107. package/lib/structures/rules/ITtscLintUnicornRules.js.map +1 -0
  108. package/lib/structures/rules/ITtscLintVitestRules.d.ts +141 -0
  109. package/lib/structures/rules/ITtscLintVitestRules.js +3 -0
  110. package/lib/structures/rules/ITtscLintVitestRules.js.map +1 -0
  111. package/lib/structures/rules/index.d.ts +31 -0
  112. package/lib/structures/rules/index.js +48 -0
  113. package/lib/structures/rules/index.js.map +1 -0
  114. package/linthost/ast_helpers.go +30 -5
  115. package/linthost/compile.go +33 -2
  116. package/linthost/config.go +48 -17
  117. package/linthost/config_format.go +9 -9
  118. package/linthost/directives.go +67 -25
  119. package/linthost/dispatch.go +14 -3
  120. package/linthost/engine.go +160 -40
  121. package/linthost/fix.go +2 -2
  122. package/linthost/flags_gen.go +17 -15
  123. package/linthost/host.go +40 -3
  124. package/linthost/lsp.go +747 -0
  125. package/linthost/print_dispatch.go +2 -2
  126. package/linthost/print_nodes_function.go +2 -2
  127. package/linthost/print_nodes_object.go +1 -1
  128. package/linthost/rule_names.go +14 -0
  129. package/linthost/rules_arrays.go +2 -2
  130. package/linthost/rules_boundaries.go +532 -0
  131. package/linthost/rules_camelcase.go +133 -0
  132. package/linthost/rules_complexity.go +94 -0
  133. package/linthost/rules_consistent_return.go +130 -0
  134. package/linthost/rules_console.go +1 -1
  135. package/linthost/rules_core_extra.go +739 -0
  136. package/linthost/rules_curly.go +70 -0
  137. package/linthost/rules_cypress.go +608 -0
  138. package/linthost/rules_debugger.go +2 -2
  139. package/linthost/rules_default_case.go +39 -0
  140. package/linthost/rules_default_case_last.go +46 -0
  141. package/linthost/rules_dupes.go +3 -3
  142. package/linthost/rules_empty.go +3 -3
  143. package/linthost/rules_escape.go +44 -24
  144. package/linthost/rules_eval.go +2 -2
  145. package/linthost/rules_finally.go +2 -2
  146. package/linthost/rules_format_jsdoc.go +1 -1
  147. package/linthost/rules_format_print_width.go +9 -9
  148. package/linthost/rules_format_quotes.go +1 -1
  149. package/linthost/rules_format_semi.go +1 -1
  150. package/linthost/rules_format_sort_imports.go +1 -1
  151. package/linthost/rules_format_trailing_comma.go +1 -1
  152. package/linthost/rules_functional.go +967 -0
  153. package/linthost/rules_gap.go +24 -45
  154. package/linthost/rules_grouped_accessor_pairs.go +87 -0
  155. package/linthost/rules_guard_for_in.go +198 -0
  156. package/linthost/rules_id_length.go +77 -0
  157. package/linthost/rules_imports.go +70 -2
  158. package/linthost/rules_init_declarations.go +53 -0
  159. package/linthost/rules_jest.go +618 -0
  160. package/linthost/rules_jsdoc.go +502 -0
  161. package/linthost/rules_jsx_a11y.go +1264 -0
  162. package/linthost/rules_logic.go +12 -12
  163. package/linthost/rules_loops.go +1 -1
  164. package/linthost/rules_max_classes_per_file.go +58 -0
  165. package/linthost/rules_max_depth.go +83 -0
  166. package/linthost/rules_max_lines.go +101 -0
  167. package/linthost/rules_max_lines_per_function.go +57 -0
  168. package/linthost/rules_max_nested_callbacks.go +61 -0
  169. package/linthost/rules_max_params.go +49 -0
  170. package/linthost/rules_max_statements.go +59 -0
  171. package/linthost/rules_misc.go +1 -1
  172. package/linthost/rules_nextjs.go +697 -0
  173. package/linthost/rules_no_else_return.go +75 -0
  174. package/linthost/rules_no_empty_named_blocks.go +91 -0
  175. package/linthost/rules_no_extend_native.go +51 -0
  176. package/linthost/rules_no_import_assign.go +140 -0
  177. package/linthost/rules_no_invalid_this.go +52 -0
  178. package/linthost/rules_no_loop_func.go +85 -0
  179. package/linthost/rules_no_magic_numbers.go +123 -0
  180. package/linthost/rules_no_mixed_operators.go +80 -0
  181. package/linthost/rules_no_param_reassign.go +98 -0
  182. package/linthost/rules_no_redeclare.go +270 -0
  183. package/linthost/rules_no_restricted_imports.go +105 -0
  184. package/linthost/rules_no_restricted_syntax.go +49 -0
  185. package/linthost/rules_no_shadow.go +147 -0
  186. package/linthost/rules_no_unreachable.go +77 -0
  187. package/linthost/rules_no_useless_assignment.go +120 -0
  188. package/linthost/rules_no_useless_constructor.go +245 -0
  189. package/linthost/rules_no_useless_return.go +51 -0
  190. package/linthost/rules_params.go +1 -1
  191. package/linthost/rules_playwright.go +788 -0
  192. package/linthost/rules_prefer_arrow_callback.go +124 -0
  193. package/linthost/rules_prefer_destructuring.go +98 -0
  194. package/linthost/rules_prefer_named_capture_group.go +129 -0
  195. package/linthost/rules_prefer_rest_params.go +94 -0
  196. package/linthost/rules_problems.go +41 -30
  197. package/linthost/rules_promise.go +1128 -73
  198. package/linthost/rules_protos.go +2 -2
  199. package/linthost/rules_react.go +773 -0
  200. package/linthost/rules_react_extras.go +227 -0
  201. package/linthost/rules_react_hooks.go +848 -0
  202. package/linthost/rules_react_perf.go +293 -0
  203. package/linthost/rules_react_refresh.go +583 -0
  204. package/linthost/rules_regexp.go +410 -0
  205. package/linthost/rules_security.go +830 -0
  206. package/linthost/rules_self.go +2 -2
  207. package/linthost/rules_solid.go +1073 -0
  208. package/linthost/rules_sort_imports.go +69 -0
  209. package/linthost/rules_sort_keys.go +134 -0
  210. package/linthost/rules_storybook.go +1176 -0
  211. package/linthost/rules_strings.go +4 -4
  212. package/linthost/rules_suggestions.go +38 -38
  213. package/linthost/rules_tanstack_query.go +844 -0
  214. package/linthost/rules_testing_library.go +1204 -0
  215. package/linthost/rules_throw.go +1 -1
  216. package/linthost/rules_ts.go +19 -19
  217. package/linthost/rules_ts_async.go +399 -0
  218. package/linthost/rules_ts_class_literal_property_style.go +115 -0
  219. package/linthost/rules_ts_consistent_type_exports.go +256 -0
  220. package/linthost/rules_ts_explicit_function_return_type.go +67 -0
  221. package/linthost/rules_ts_extra.go +155 -36
  222. package/linthost/rules_ts_no_base_to_string.go +218 -0
  223. package/linthost/rules_ts_no_confusing_void.go +72 -0
  224. package/linthost/rules_ts_no_deprecated.go +195 -0
  225. package/linthost/rules_ts_no_for_in_array.go +84 -0
  226. package/linthost/rules_ts_no_magic_numbers.go +124 -0
  227. package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
  228. package/linthost/rules_ts_no_misused_spread.go +104 -0
  229. package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
  230. package/linthost/rules_ts_no_restricted_types.go +62 -0
  231. package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
  232. package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
  233. package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
  234. package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
  235. package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
  236. package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
  237. package/linthost/rules_ts_no_unsafe_argument.go +82 -0
  238. package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
  239. package/linthost/rules_ts_no_unsafe_call.go +82 -0
  240. package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
  241. package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
  242. package/linthost/rules_ts_no_unsafe_return.go +126 -0
  243. package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
  244. package/linthost/rules_ts_no_useless_constructor.go +52 -0
  245. package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
  246. package/linthost/rules_ts_parameter_properties.go +38 -0
  247. package/linthost/rules_ts_prefer_find.go +178 -0
  248. package/linthost/rules_ts_prefer_includes.go +255 -0
  249. package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
  250. package/linthost/rules_ts_prefer_optional_chain.go +228 -0
  251. package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
  252. package/linthost/rules_ts_prefer_readonly.go +73 -0
  253. package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
  254. package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
  255. package/linthost/rules_ts_prefer_return_this_type.go +135 -0
  256. package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
  257. package/linthost/rules_ts_promise_function_async.go +77 -0
  258. package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
  259. package/linthost/rules_ts_require_array_sort_compare.go +96 -0
  260. package/linthost/rules_ts_restrict_plus_operands.go +127 -0
  261. package/linthost/rules_ts_restrict_template_expressions.go +95 -0
  262. package/linthost/rules_ts_simple.go +387 -0
  263. package/linthost/rules_ts_sort_type_constituents.go +144 -0
  264. package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
  265. package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
  266. package/linthost/rules_ts_unbound_method.go +126 -0
  267. package/linthost/rules_tsdoc.go +136 -0
  268. package/linthost/rules_unicorn_better_regex.go +27 -0
  269. package/linthost/rules_unicorn_catch_error_name.go +46 -0
  270. package/linthost/rules_unicorn_consistent_assert.go +47 -0
  271. package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
  272. package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
  273. package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
  274. package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
  275. package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
  276. package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
  277. package/linthost/rules_unicorn_custom_error_definition.go +138 -0
  278. package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
  279. package/linthost/rules_unicorn_error_message.go +64 -0
  280. package/linthost/rules_unicorn_escape_case.go +51 -0
  281. package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
  282. package/linthost/rules_unicorn_explicit_length_check.go +88 -0
  283. package/linthost/rules_unicorn_filename_case.go +29 -0
  284. package/linthost/rules_unicorn_import_style.go +28 -0
  285. package/linthost/rules_unicorn_isolated_functions.go +29 -0
  286. package/linthost/rules_unicorn_new_for_builtins.go +87 -0
  287. package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
  288. package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
  289. package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
  290. package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
  291. package/linthost/rules_unicorn_no_array_for_each.go +40 -0
  292. package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
  293. package/linthost/rules_unicorn_no_array_reduce.go +41 -0
  294. package/linthost/rules_unicorn_no_array_reverse.go +44 -0
  295. package/linthost/rules_unicorn_no_array_sort.go +43 -0
  296. package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
  297. package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
  298. package/linthost/rules_unicorn_no_console_spaces.go +61 -0
  299. package/linthost/rules_unicorn_no_document_cookie.go +41 -0
  300. package/linthost/rules_unicorn_no_empty_file.go +44 -0
  301. package/linthost/rules_unicorn_no_for_loop.go +102 -0
  302. package/linthost/rules_unicorn_no_hex_escape.go +42 -0
  303. package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
  304. package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
  305. package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
  306. package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
  307. package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
  308. package/linthost/rules_unicorn_no_lonely_if.go +44 -0
  309. package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
  310. package/linthost/rules_unicorn_no_named_default.go +54 -0
  311. package/linthost/rules_unicorn_no_negated_condition.go +85 -0
  312. package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
  313. package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
  314. package/linthost/rules_unicorn_no_new_array.go +30 -0
  315. package/linthost/rules_unicorn_no_new_buffer.go +31 -0
  316. package/linthost/rules_unicorn_no_null.go +24 -0
  317. package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
  318. package/linthost/rules_unicorn_no_process_exit.go +43 -0
  319. package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
  320. package/linthost/rules_unicorn_no_static_only_class.go +56 -0
  321. package/linthost/rules_unicorn_no_thenable.go +74 -0
  322. package/linthost/rules_unicorn_no_this_assignment.go +35 -0
  323. package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
  324. package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
  325. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
  326. package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
  327. package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
  328. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
  329. package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
  330. package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
  331. package/linthost/rules_unicorn_no_unused_properties.go +30 -0
  332. package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
  333. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
  334. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
  335. package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
  336. package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
  337. package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
  338. package/linthost/rules_unicorn_no_useless_spread.go +67 -0
  339. package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
  340. package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
  341. package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
  342. package/linthost/rules_unicorn_number_literal_case.go +69 -0
  343. package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
  344. package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
  345. package/linthost/rules_unicorn_prefer_array_find.go +51 -0
  346. package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
  347. package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
  348. package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
  349. package/linthost/rules_unicorn_prefer_array_some.go +67 -0
  350. package/linthost/rules_unicorn_prefer_at.go +77 -0
  351. package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
  352. package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
  353. package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
  354. package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
  355. package/linthost/rules_unicorn_prefer_code_point.go +49 -0
  356. package/linthost/rules_unicorn_prefer_date_now.go +78 -0
  357. package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
  358. package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
  359. package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
  360. package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
  361. package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
  362. package/linthost/rules_unicorn_prefer_event_target.go +36 -0
  363. package/linthost/rules_unicorn_prefer_export_from.go +129 -0
  364. package/linthost/rules_unicorn_prefer_global_this.go +127 -0
  365. package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
  366. package/linthost/rules_unicorn_prefer_includes.go +149 -0
  367. package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
  368. package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
  369. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
  370. package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
  371. package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
  372. package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
  373. package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
  374. package/linthost/rules_unicorn_prefer_module.go +50 -0
  375. package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
  376. package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
  377. package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
  378. package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
  379. package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
  380. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
  381. package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
  382. package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
  383. package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
  384. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
  385. package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
  386. package/linthost/rules_unicorn_prefer_set_has.go +42 -0
  387. package/linthost/rules_unicorn_prefer_set_size.go +48 -0
  388. package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
  389. package/linthost/rules_unicorn_prefer_single_call.go +96 -0
  390. package/linthost/rules_unicorn_prefer_spread.go +51 -0
  391. package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
  392. package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
  393. package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
  394. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
  395. package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
  396. package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
  397. package/linthost/rules_unicorn_prefer_switch.go +103 -0
  398. package/linthost/rules_unicorn_prefer_ternary.go +71 -0
  399. package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
  400. package/linthost/rules_unicorn_prefer_type_error.go +127 -0
  401. package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
  402. package/linthost/rules_unicorn_relative_url_style.go +49 -0
  403. package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
  404. package/linthost/rules_unicorn_require_module_attributes.go +54 -0
  405. package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
  406. package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
  407. package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
  408. package/linthost/rules_unicorn_string_content.go +27 -0
  409. package/linthost/rules_unicorn_switch_case_braces.go +42 -0
  410. package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
  411. package/linthost/rules_unicorn_template_indent.go +28 -0
  412. package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
  413. package/linthost/rules_unicorn_throw_new_error.go +61 -0
  414. package/linthost/rules_var.go +10 -4
  415. package/linthost/rules_vitest.go +568 -0
  416. package/package.json +3 -3
  417. package/plugin/main.go +49 -3
  418. package/rule/astutil/astutil.go +10 -3
  419. package/rule/rule.go +12 -10
  420. package/src/defaultFormat.ts +11 -8
  421. package/src/index.ts +65 -43
  422. package/src/structures/ITtscLintConfig.ts +12 -6
  423. package/src/structures/{ITtscLintFormatConfig.ts → ITtscLintFormat.ts} +2 -2
  424. package/src/structures/TtscLintRuleSetting.ts +55 -0
  425. package/src/structures/index.ts +3 -4
  426. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +128 -0
  427. package/src/structures/rules/ITtscLintBoundariesRules.ts +95 -0
  428. package/src/structures/rules/ITtscLintContributorRules.ts +21 -0
  429. package/src/structures/rules/ITtscLintCoreRules.ts +1406 -0
  430. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
  431. package/src/structures/rules/ITtscLintCypressRules.ts +145 -0
  432. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +213 -0
  433. package/src/structures/rules/ITtscLintFunctionalRules.ts +202 -0
  434. package/src/structures/rules/ITtscLintJestRules.ts +220 -0
  435. package/src/structures/rules/ITtscLintJsdocRules.ts +153 -0
  436. package/src/structures/rules/ITtscLintJsxA11yRules.ts +339 -0
  437. package/src/structures/rules/ITtscLintNextjsRules.ts +206 -0
  438. package/src/structures/rules/ITtscLintPlaywrightRules.ts +361 -0
  439. package/src/structures/rules/ITtscLintPromiseRules.ts +205 -0
  440. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
  441. package/src/structures/rules/ITtscLintReactPerfRules.ts +55 -0
  442. package/src/structures/rules/ITtscLintReactRuleOptions.ts +43 -0
  443. package/src/structures/rules/ITtscLintReactRules.ts +321 -0
  444. package/src/structures/rules/ITtscLintRegexpRules.ts +212 -0
  445. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +89 -0
  446. package/src/structures/rules/ITtscLintRules.ts +77 -0
  447. package/src/structures/rules/ITtscLintSecurityRules.ts +162 -0
  448. package/src/structures/rules/ITtscLintSolidRules.ts +202 -0
  449. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +23 -0
  450. package/src/structures/rules/ITtscLintStorybookRules.ts +193 -0
  451. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +102 -0
  452. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +24 -0
  453. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +342 -0
  454. package/src/structures/rules/ITtscLintTypeScriptRules.ts +1230 -0
  455. package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
  456. package/src/structures/rules/ITtscLintVitestRules.ts +154 -0
  457. package/src/structures/rules/index.ts +31 -0
  458. package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
  459. package/lib/structures/TtscLintRule.d.ts +0 -17
  460. package/lib/structures/TtscLintRule.js.map +0 -1
  461. package/lib/structures/TtscLintRuleMap.d.ts +0 -46
  462. package/lib/structures/TtscLintRuleMap.js.map +0 -1
  463. package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
  464. package/lib/structures/TtscLintRuleOptions.js.map +0 -1
  465. package/src/structures/TtscLintRule.ts +0 -160
  466. package/src/structures/TtscLintRuleMap.ts +0 -55
  467. package/src/structures/TtscLintRuleOptions.ts +0 -151
@@ -0,0 +1,124 @@
1
+ // preferArrowCallback: a `function() { … }` expression passed as a
2
+ // callback argument predates ES2015 arrow functions. The arrow form is
3
+ // shorter, captures `this` lexically (the usual intent for a callback),
4
+ // and avoids the named-binding hoisting of `function` expressions.
5
+ // https://eslint.org/docs/latest/rules/prefer-arrow-callback
6
+ //
7
+ // AST-only: visit every `CallExpression`/`NewExpression` and check
8
+ // whether any of its arguments is a `FunctionExpression`. A few shapes
9
+ // are skipped because converting them would change behaviour:
10
+ //
11
+ // - generators (`function* () {}`) cannot be arrows at all.
12
+ // - bodies that read `this` or `arguments` rely on the function
13
+ // expression's own binding; an arrow would capture the surrounding
14
+ // binding instead.
15
+ // - functions immediately followed by `.bind(…)` opt the caller into
16
+ // an explicit `this` binding that an arrow cannot honour.
17
+ //
18
+ // Named function expressions (`function name() { … }`) still flag —
19
+ // ESLint's default `allowNamedFunctions` is `false` — but a body that
20
+ // references the function's own name through the inner binding is left
21
+ // alone so the recursion stays valid.
22
+ package linthost
23
+
24
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
25
+
26
+ type preferArrowCallback struct{}
27
+
28
+ func (preferArrowCallback) Name() string { return "prefer-arrow-callback" }
29
+ func (preferArrowCallback) Visits() []shimast.Kind {
30
+ return []shimast.Kind{shimast.KindCallExpression, shimast.KindNewExpression}
31
+ }
32
+ func (preferArrowCallback) Check(ctx *Context, node *shimast.Node) {
33
+ args := callArgumentsList(node)
34
+ if args == nil {
35
+ return
36
+ }
37
+ for _, arg := range args.Nodes {
38
+ fn := stripParens(arg)
39
+ if fn == nil || fn.Kind != shimast.KindFunctionExpression {
40
+ continue
41
+ }
42
+ if !preferArrowCallbackEligible(fn) {
43
+ continue
44
+ }
45
+ ctx.Report(fn, "Unexpected function expression. Use an arrow function instead.")
46
+ }
47
+ }
48
+
49
+ // callArgumentsList returns the argument NodeList of a CallExpression or
50
+ // NewExpression, or nil when the node either lacks arguments or is not a
51
+ // call/new shape.
52
+ func callArgumentsList(node *shimast.Node) *shimast.NodeList {
53
+ switch node.Kind {
54
+ case shimast.KindCallExpression:
55
+ call := node.AsCallExpression()
56
+ if call == nil {
57
+ return nil
58
+ }
59
+ return call.Arguments
60
+ case shimast.KindNewExpression:
61
+ newExpr := node.AsNewExpression()
62
+ if newExpr == nil {
63
+ return nil
64
+ }
65
+ return newExpr.Arguments
66
+ }
67
+ return nil
68
+ }
69
+
70
+ // preferArrowCallbackEligible reports whether `fn` (a FunctionExpression)
71
+ // can be converted to an arrow without changing observable behaviour.
72
+ // The function must not be a generator, must not read `this` or
73
+ // `arguments` outside any nested function-like, and must not reference
74
+ // its own inner name (a self-recursion handle that an arrow cannot
75
+ // reproduce).
76
+ func preferArrowCallbackEligible(fn *shimast.Node) bool {
77
+ expr := fn.AsFunctionExpression()
78
+ if expr == nil {
79
+ return false
80
+ }
81
+ if expr.AsteriskToken != nil {
82
+ return false
83
+ }
84
+ innerName := identifierText(expr.Name())
85
+ body := expr.Body
86
+ if body == nil {
87
+ return true
88
+ }
89
+ usesForbidden := false
90
+ walkFunctionBody(body, func(child *shimast.Node) {
91
+ if usesForbidden || child == nil {
92
+ return
93
+ }
94
+ switch child.Kind {
95
+ case shimast.KindThisKeyword:
96
+ usesForbidden = true
97
+ case shimast.KindIdentifier:
98
+ text := identifierText(child)
99
+ if text == "arguments" {
100
+ // Skip `obj.arguments` — that's an unrelated member access.
101
+ if parent := child.Parent; parent != nil && parent.Kind == shimast.KindPropertyAccessExpression {
102
+ if access := parent.AsPropertyAccessExpression(); access != nil && access.Name() == child {
103
+ return
104
+ }
105
+ }
106
+ usesForbidden = true
107
+ return
108
+ }
109
+ if innerName != "" && text == innerName {
110
+ if parent := child.Parent; parent != nil && parent.Kind == shimast.KindPropertyAccessExpression {
111
+ if access := parent.AsPropertyAccessExpression(); access != nil && access.Name() == child {
112
+ return
113
+ }
114
+ }
115
+ usesForbidden = true
116
+ }
117
+ }
118
+ })
119
+ return !usesForbidden
120
+ }
121
+
122
+ func init() {
123
+ Register(preferArrowCallback{})
124
+ }
@@ -0,0 +1,98 @@
1
+ // preferDestructuring: a variable declaration whose initializer is a
2
+ // single property or index access (`const a = obj.a;`, `const x =
3
+ // arr[0];`) is just longhand for the destructuring form (`const { a }
4
+ // = obj;`, `const [x] = arr;`). The destructuring form reads at the
5
+ // site as "extracts this from that", names the source object once, and
6
+ // scales to multi-field extraction without retyping the receiver.
7
+ // https://eslint.org/docs/latest/rules/prefer-destructuring
8
+ //
9
+ // AST-only: each visited `VariableDeclaration` is checked for an
10
+ // initializer shape that destructuring would replace verbatim:
11
+ //
12
+ // - `obj.<name>` where the variable name matches `<name>`
13
+ // - `arr[<n>]` where `<n>` is a numeric literal
14
+ //
15
+ // Computed string-literal access (`obj["a"]`) is skipped — that idiom
16
+ // is usually deliberate (e.g. key with hyphens or reserved-word
17
+ // keys). The receiver must be a plain identifier or property access;
18
+ // call expressions and other compound shapes are not flagged because
19
+ // the receiver would be re-evaluated under destructuring.
20
+ package linthost
21
+
22
+ import (
23
+ shimast "github.com/microsoft/typescript-go/shim/ast"
24
+ )
25
+
26
+ type preferDestructuring struct{}
27
+
28
+ func (preferDestructuring) Name() string { return "prefer-destructuring" }
29
+ func (preferDestructuring) Visits() []shimast.Kind {
30
+ return []shimast.Kind{shimast.KindVariableDeclaration}
31
+ }
32
+ func (preferDestructuring) Check(ctx *Context, node *shimast.Node) {
33
+ decl := node.AsVariableDeclaration()
34
+ if decl == nil || decl.Initializer == nil {
35
+ return
36
+ }
37
+ // Only fire on plain identifier bindings — destructuring already
38
+ // happens on `const { a } = obj;`.
39
+ name := decl.Name()
40
+ if name == nil || name.Kind != shimast.KindIdentifier {
41
+ return
42
+ }
43
+ varName := identifierText(name)
44
+ if varName == "" {
45
+ return
46
+ }
47
+ init := stripParens(decl.Initializer)
48
+ if init == nil {
49
+ return
50
+ }
51
+ switch init.Kind {
52
+ case shimast.KindPropertyAccessExpression:
53
+ access := init.AsPropertyAccessExpression()
54
+ if access == nil || access.Expression == nil || !preferDestructuringSimpleReceiver(access.Expression) {
55
+ return
56
+ }
57
+ propName := access.Name()
58
+ if propName == nil || propName.Kind != shimast.KindIdentifier {
59
+ return
60
+ }
61
+ if identifierText(propName) != varName {
62
+ return
63
+ }
64
+ ctx.Report(node, "Use object destructuring (`const { "+varName+" } = obj`).")
65
+ case shimast.KindElementAccessExpression:
66
+ access := init.AsElementAccessExpression()
67
+ if access == nil || access.Expression == nil || access.ArgumentExpression == nil {
68
+ return
69
+ }
70
+ if !preferDestructuringSimpleReceiver(access.Expression) {
71
+ return
72
+ }
73
+ // Only numeric-literal index — array destructuring.
74
+ idx := stripParens(access.ArgumentExpression)
75
+ if idx == nil || idx.Kind != shimast.KindNumericLiteral {
76
+ return
77
+ }
78
+ ctx.Report(node, "Use array destructuring (`const ["+varName+"] = arr`).")
79
+ }
80
+ }
81
+
82
+ func preferDestructuringSimpleReceiver(node *shimast.Node) bool {
83
+ n := stripParens(node)
84
+ if n == nil {
85
+ return false
86
+ }
87
+ switch n.Kind {
88
+ case shimast.KindIdentifier,
89
+ shimast.KindThisKeyword,
90
+ shimast.KindPropertyAccessExpression:
91
+ return true
92
+ }
93
+ return false
94
+ }
95
+
96
+ func init() {
97
+ Register(preferDestructuring{})
98
+ }
@@ -0,0 +1,129 @@
1
+ // preferNamedCaptureGroup: an unnamed capturing group `(…)` in a
2
+ // regular-expression literal has to be referenced by ordinal number.
3
+ // Named groups `(?<name>…)` document the captured value at the
4
+ // definition site and survive pattern edits that would otherwise renumber
5
+ // the groups silently.
6
+ // https://eslint.org/docs/latest/rules/prefer-named-capture-group
7
+ //
8
+ // AST-only: scan the pattern of every `RegularExpressionLiteral`,
9
+ // stepping past escapes and character classes (where `(` is a literal
10
+ // '(' rather than a group opener). Each `(` that is not followed by `?:`,
11
+ // `?<name>`, `?<=`, `?<!`, `?=`, or `?!` is an unnamed capture group and
12
+ // fires the rule. Character-class contents are skipped because '(' there
13
+ // is a literal byte, never a group opener.
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ type preferNamedCaptureGroup struct{}
19
+
20
+ func (preferNamedCaptureGroup) Name() string { return "prefer-named-capture-group" }
21
+ func (preferNamedCaptureGroup) Visits() []shimast.Kind {
22
+ return []shimast.Kind{shimast.KindRegularExpressionLiteral}
23
+ }
24
+ func (preferNamedCaptureGroup) Check(ctx *Context, node *shimast.Node) {
25
+ raw := nodeText(ctx.File, node)
26
+ if len(raw) < 2 || raw[0] != '/' {
27
+ return
28
+ }
29
+ closing := lastSlashOutsideClass(raw)
30
+ if closing <= 0 {
31
+ return
32
+ }
33
+ pattern := raw[1:closing]
34
+ if regexpHasUnnamedCapture(pattern) {
35
+ ctx.Report(node, "Capture group should be named.")
36
+ }
37
+ }
38
+
39
+ // regexpHasUnnamedCapture reports whether `pattern` contains at least
40
+ // one capturing group that is neither a non-capturing group (`(?:…)`),
41
+ // a named group (`(?<name>…)`), nor a lookaround assertion (`(?=…)`,
42
+ // `(?!…)`, `(?<=…)`, `(?<!…)`). The scan skips escape sequences and
43
+ // character-class contents because `(` is a literal byte in those
44
+ // positions and never opens a group.
45
+ func regexpHasUnnamedCapture(pattern string) bool {
46
+ inClass := false
47
+ for i := 0; i < len(pattern); i++ {
48
+ ch := pattern[i]
49
+ if ch == '\\' {
50
+ i++
51
+ continue
52
+ }
53
+ if inClass {
54
+ if ch == ']' {
55
+ inClass = false
56
+ }
57
+ continue
58
+ }
59
+ if ch == '[' {
60
+ inClass = true
61
+ continue
62
+ }
63
+ if ch != '(' {
64
+ continue
65
+ }
66
+ // `(` is a group opener; classify what follows.
67
+ if i+1 >= len(pattern) || pattern[i+1] != '?' {
68
+ return true
69
+ }
70
+ if i+2 >= len(pattern) {
71
+ // `(?` with nothing after — treat as malformed but not flagged;
72
+ // the parser would have rejected this regex if it was truly
73
+ // invalid, so leave it alone.
74
+ continue
75
+ }
76
+ switch pattern[i+2] {
77
+ case ':', '=', '!':
78
+ // non-capturing or lookahead
79
+ continue
80
+ case '<':
81
+ if i+3 < len(pattern) && (pattern[i+3] == '=' || pattern[i+3] == '!') {
82
+ // lookbehind `(?<=` / `(?<!`
83
+ continue
84
+ }
85
+ // named capture `(?<name>…)`
86
+ continue
87
+ }
88
+ // `(?` followed by something else (e.g. an inline flag group).
89
+ // Treat as unnamed; ESLint flags these too because they still
90
+ // capture under the standard regex semantics they target.
91
+ return true
92
+ }
93
+ return false
94
+ }
95
+
96
+ // lastSlashOutsideClass returns the index of the closing `/` of a regex
97
+ // literal, accounting for `/` characters that appear inside escapes or
98
+ // character classes. Returns -1 when no closing slash is found.
99
+ func lastSlashOutsideClass(raw string) int {
100
+ if len(raw) < 2 || raw[0] != '/' {
101
+ return -1
102
+ }
103
+ inClass := false
104
+ for i := 1; i < len(raw); i++ {
105
+ ch := raw[i]
106
+ if ch == '\\' {
107
+ i++
108
+ continue
109
+ }
110
+ if inClass {
111
+ if ch == ']' {
112
+ inClass = false
113
+ }
114
+ continue
115
+ }
116
+ if ch == '[' {
117
+ inClass = true
118
+ continue
119
+ }
120
+ if ch == '/' {
121
+ return i
122
+ }
123
+ }
124
+ return -1
125
+ }
126
+
127
+ func init() {
128
+ Register(preferNamedCaptureGroup{})
129
+ }
@@ -0,0 +1,94 @@
1
+ // preferRestParams: a non-arrow function body that reads from
2
+ // `arguments` is using the legacy variadic-argument shape that predates
3
+ // ES6 rest parameters. Replacing the `arguments` access with
4
+ // `(...args)` declares the variadic contract on the signature, makes
5
+ // the parameter list iterable like every other JS array, and lets a
6
+ // reader see the variadic intent without reading the body.
7
+ // https://eslint.org/docs/latest/rules/prefer-rest-params
8
+ //
9
+ // AST-only: each visited function-like that owns its own `arguments`
10
+ // binding (function declaration, function expression, method, accessor,
11
+ // constructor — i.e. NOT an arrow function) is scanned for an
12
+ // `Identifier(arguments)` use inside its body. The walk stops at nested
13
+ // function-like boundaries via the shared `walkFunctionBody` helper.
14
+ // Property names like `obj.arguments` are skipped because they
15
+ // reference an unrelated member; only bare identifier reads count.
16
+ package linthost
17
+
18
+ import (
19
+ shimast "github.com/microsoft/typescript-go/shim/ast"
20
+ )
21
+
22
+ type preferRestParams struct{}
23
+
24
+ func (preferRestParams) Name() string { return "prefer-rest-params" }
25
+ func (preferRestParams) Visits() []shimast.Kind {
26
+ return []shimast.Kind{
27
+ shimast.KindFunctionDeclaration,
28
+ shimast.KindFunctionExpression,
29
+ shimast.KindMethodDeclaration,
30
+ shimast.KindGetAccessor,
31
+ shimast.KindSetAccessor,
32
+ shimast.KindConstructor,
33
+ }
34
+ }
35
+ func (preferRestParams) Check(ctx *Context, node *shimast.Node) {
36
+ body := preferRestParamsBody(node)
37
+ if body == nil {
38
+ return
39
+ }
40
+ reported := false
41
+ walkFunctionBody(body, func(child *shimast.Node) {
42
+ if reported || child == nil {
43
+ return
44
+ }
45
+ if child.Kind != shimast.KindIdentifier {
46
+ return
47
+ }
48
+ if identifierText(child) != "arguments" {
49
+ return
50
+ }
51
+ // Skip `obj.arguments` — that's an unrelated member access.
52
+ if parent := child.Parent; parent != nil && parent.Kind == shimast.KindPropertyAccessExpression {
53
+ if access := parent.AsPropertyAccessExpression(); access != nil && access.Name() == child {
54
+ return
55
+ }
56
+ }
57
+ reported = true
58
+ ctx.Report(child, "Use rest parameters (`...args`) instead of `arguments`.")
59
+ })
60
+ }
61
+
62
+ func preferRestParamsBody(node *shimast.Node) *shimast.Node {
63
+ switch node.Kind {
64
+ case shimast.KindFunctionDeclaration:
65
+ if fn := node.AsFunctionDeclaration(); fn != nil {
66
+ return fn.Body
67
+ }
68
+ case shimast.KindFunctionExpression:
69
+ if fn := node.AsFunctionExpression(); fn != nil {
70
+ return fn.Body
71
+ }
72
+ case shimast.KindMethodDeclaration:
73
+ if m := node.AsMethodDeclaration(); m != nil {
74
+ return m.Body
75
+ }
76
+ case shimast.KindGetAccessor:
77
+ if a := node.AsGetAccessorDeclaration(); a != nil {
78
+ return a.Body
79
+ }
80
+ case shimast.KindSetAccessor:
81
+ if a := node.AsSetAccessorDeclaration(); a != nil {
82
+ return a.Body
83
+ }
84
+ case shimast.KindConstructor:
85
+ if c := node.AsConstructorDeclaration(); c != nil {
86
+ return c.Body
87
+ }
88
+ }
89
+ return nil
90
+ }
91
+
92
+ func init() {
93
+ Register(preferRestParams{})
94
+ }
@@ -8,12 +8,13 @@
8
8
  package linthost
9
9
 
10
10
  import (
11
+ "strconv"
11
12
  "strings"
12
13
 
13
14
  shimast "github.com/microsoft/typescript-go/shim/ast"
14
15
  )
15
16
 
16
- // no-dupe-else-if: `if (a) {} else if (a) {}` — the second branch is
17
+ // noDupeElseIf: `if (a) {} else if (a) {}` — the second branch is
17
18
  // unreachable.
18
19
  type noDupeElseIf struct{}
19
20
 
@@ -49,7 +50,7 @@ func (noDupeElseIf) Check(ctx *Context, node *shimast.Node) {
49
50
  }
50
51
  }
51
52
 
52
- // no-ex-assign: `try { } catch (e) { e = 1; }` — reassigning the catch
53
+ // noExAssign: `try { } catch (e) { e = 1; }` — reassigning the catch
53
54
  // binding silently throws away the error.
54
55
  type noExAssign struct{}
55
56
 
@@ -74,8 +75,8 @@ func (noExAssign) Check(ctx *Context, node *shimast.Node) {
74
75
  }
75
76
 
76
77
  // walkAssignments invokes `report` on every `<name> = ...` shape inside
77
- // `root`. Used by no-ex-assign to scan a single catch block; the
78
- // file-wide no-func-assign / no-class-assign scans go through
78
+ // `root`. Used by noExAssign to scan a single catch block; the
79
+ // file-wide noFuncAssign / noClassAssign scans go through
79
80
  // reportAssignmentsToDeclarations instead.
80
81
  func walkAssignments(root *shimast.Node, name string, report func(*shimast.Node)) {
81
82
  if root == nil {
@@ -98,7 +99,7 @@ func walkAssignments(root *shimast.Node, name string, report func(*shimast.Node)
98
99
  })
99
100
  }
100
101
 
101
- // no-empty-character-class: `/[]/` matches nothing.
102
+ // noEmptyCharacterClass: `/[]/` matches nothing.
102
103
  type noEmptyCharacterClass struct{}
103
104
 
104
105
  func (noEmptyCharacterClass) Name() string { return "no-empty-character-class" }
@@ -133,7 +134,7 @@ func hasEmptyCharClass(src string) bool {
133
134
  return false
134
135
  }
135
136
 
136
- // no-misleading-character-class: `/[👍]/` — surrogate pairs in regex.
137
+ // noMisleadingCharacterClass: `/[👍]/` — surrogate pairs in regex.
137
138
  type noMisleadingCharacterClass struct{}
138
139
 
139
140
  func (noMisleadingCharacterClass) Name() string { return "no-misleading-character-class" }
@@ -178,10 +179,10 @@ func regexHasSurrogatePair(src string) bool {
178
179
  return false
179
180
  }
180
181
 
181
- // no-loss-of-precision: `9007199254740993` — integer literal larger than
182
- // `Number.MAX_SAFE_INTEGER`. We read the *source* form (not the parser's
183
- // normalized .Text, which has already lost precision) and decide off
184
- // that.
182
+ // noLossOfPrecision: `9007199254740993` — decimal numeric literal whose
183
+ // source text changes when parsed as a JavaScript Number. We read the source
184
+ // form instead of the parser's normalized .Text, which has already lost
185
+ // precision.
185
186
  type noLossOfPrecision struct{}
186
187
 
187
188
  func (noLossOfPrecision) Name() string { return "no-loss-of-precision" }
@@ -196,10 +197,10 @@ func (noLossOfPrecision) Check(ctx *Context, node *shimast.Node) {
196
197
  }
197
198
  }
198
199
 
199
- // numericLiteralLosesPrecision reports whether the decimal integer literal
200
- // text exceeds Number.MAX_SAFE_INTEGER (2^53 - 1). Non-decimal literals
201
- // (hex, octal, binary) and literals with exponents or decimal points are
202
- // exempt because their precision loss is caller-visible and intentional.
200
+ // numericLiteralLosesPrecision reports whether the decimal integer literal text
201
+ // changes when parsed as a JavaScript Number. Non-decimal literals (hex, octal,
202
+ // binary) and literals with exponents or decimal points are exempt because
203
+ // their precision loss is caller-visible and intentional.
203
204
  func numericLiteralLosesPrecision(text string) bool {
204
205
  // Strip underscore separators, exponents, decimal/hex/oct/binary
205
206
  // markers — for the simple-base-10 integer case the round-trip
@@ -216,19 +217,29 @@ func numericLiteralLosesPrecision(text string) bool {
216
217
  if trimmed == "" {
217
218
  return false
218
219
  }
219
- // Number.MAX_SAFE_INTEGER is 2^53-1 = 9007199254740991; 2^53 itself
220
- // (9007199254740992) is the first integer that float64 cannot round-trip.
221
- const maxSafe = "9007199254740992"
222
- if len(trimmed) < len(maxSafe) {
220
+ // 2^53 is unsafe for arithmetic comparisons but still exactly representable.
221
+ // 2^53+1 is the first plain decimal integer that changes when parsed.
222
+ const firstPossibleLoss = "9007199254740993"
223
+ if len(trimmed) < len(firstPossibleLoss) {
223
224
  return false
224
225
  }
225
- if len(trimmed) > len(maxSafe) {
226
+ if len(trimmed) == len(firstPossibleLoss) && trimmed < firstPossibleLoss {
227
+ return false
228
+ }
229
+ // Number.MAX_VALUE is around 1.79e308, so any integer with more than 309
230
+ // decimal digits cannot round-trip through a finite JavaScript Number.
231
+ const maxFiniteDecimalDigits = 309
232
+ if len(trimmed) > maxFiniteDecimalDigits {
226
233
  return true
227
234
  }
228
- return trimmed > maxSafe
235
+ parsed, err := strconv.ParseFloat(trimmed, 64)
236
+ if err != nil && parsed == 0 {
237
+ return false
238
+ }
239
+ return strconv.FormatFloat(parsed, 'f', 0, 64) != trimmed
229
240
  }
230
241
 
231
- // no-class-assign: assigning to a class declaration's name.
242
+ // noClassAssign: assigning to a class declaration's name.
232
243
  type noClassAssign struct{}
233
244
 
234
245
  func (noClassAssign) Name() string { return "no-class-assign" }
@@ -237,7 +248,7 @@ func (noClassAssign) Check(ctx *Context, node *shimast.Node) {
237
248
  reportAssignmentsToDeclarations(ctx, node, shimast.KindClassDeclaration, "is a class.")
238
249
  }
239
250
 
240
- // no-func-assign: same idea, but for function declarations.
251
+ // noFuncAssign: same idea, but for function declarations.
241
252
  type noFuncAssign struct{}
242
253
 
243
254
  func (noFuncAssign) Name() string { return "no-func-assign" }
@@ -308,7 +319,7 @@ func declarationName(n *shimast.Node) string {
308
319
  return ""
309
320
  }
310
321
 
311
- // no-prototype-builtins: `obj.hasOwnProperty(x)` — should be
322
+ // noPrototypeBuiltins: `obj.hasOwnProperty(x)` — should be
312
323
  // `Object.prototype.hasOwnProperty.call(obj, x)` or `Object.hasOwn`.
313
324
  type noPrototypeBuiltins struct{}
314
325
 
@@ -333,7 +344,7 @@ func (noPrototypeBuiltins) Check(ctx *Context, node *shimast.Node) {
333
344
  }
334
345
  }
335
346
 
336
- // no-async-promise-executor: `new Promise(async (resolve) => {...})`.
347
+ // noAsyncPromiseExecutor: `new Promise(async (resolve) => {...})`.
337
348
  type noAsyncPromiseExecutor struct{}
338
349
 
339
350
  func (noAsyncPromiseExecutor) Name() string { return "no-async-promise-executor" }
@@ -360,7 +371,7 @@ func (noAsyncPromiseExecutor) Check(ctx *Context, node *shimast.Node) {
360
371
  }
361
372
  }
362
373
 
363
- // no-promise-executor-return: `new Promise(() => 1)` — the value is
374
+ // noPromiseExecutorReturn: `new Promise(() => 1)` — the value is
364
375
  // thrown away.
365
376
  type noPromiseExecutorReturn struct{}
366
377
 
@@ -390,7 +401,7 @@ func (noPromiseExecutorReturn) Check(ctx *Context, node *shimast.Node) {
390
401
  }
391
402
  }
392
403
 
393
- // no-control-regex: `/\x00/` — control characters in regex are usually
404
+ // noControlRegex: `/\x00/` — control characters in regex are usually
394
405
  // the result of accidentally typing the escape rather than the printable
395
406
  // counterpart.
396
407
  type noControlRegex struct{}
@@ -454,7 +465,7 @@ func hexDigit(b byte) int {
454
465
  return -1
455
466
  }
456
467
 
457
- // no-irregular-whitespace: zero-width spaces, NBSP, etc. The TS parser
468
+ // noIrregularWhitespace: zero-width spaces, NBSP, etc. The TS parser
458
469
  // accepts them but copy-paste into source is almost always a mistake.
459
470
  type noIrregularWhitespace struct{}
460
471
 
@@ -491,7 +502,7 @@ func isIrregularWhitespace(r rune) bool {
491
502
  return false
492
503
  }
493
504
 
494
- // no-fallthrough: `switch` cases that fall through to the next label
505
+ // noFallthrough: `switch` cases that fall through to the next label
495
506
  // without an explicit `break` / `return` / `throw` / `continue`.
496
507
  type noFallthrough struct{}
497
508
 
@@ -549,7 +560,7 @@ func isTerminating(stmt *shimast.Node) bool {
549
560
  return false
550
561
  }
551
562
 
552
- // no-inner-declarations: `function foo() { if (x) { function bar() {} } }`
563
+ // noInnerDeclarations: `function foo() { if (x) { function bar() {} } }`
553
564
  // — inner function declarations are hoisted differently in strict mode
554
565
  // vs sloppy and are confusing.
555
566
  type noInnerDeclarations struct{}
@@ -592,7 +603,7 @@ func (noInnerDeclarations) Check(ctx *Context, node *shimast.Node) {
592
603
  ctx.Report(node, "Move "+what+" declaration to the function scope.")
593
604
  }
594
605
 
595
- // no-obj-calls: `Math()`, `JSON()` — these globals are objects, not
606
+ // noObjCalls: `Math()`, `JSON()` — these globals are objects, not
596
607
  // callables. ESLint catches a small list.
597
608
  type noObjCalls struct{}
598
609