@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,66 @@
1
+ // unicorn/prefer-import-meta-properties: the legacy
2
+ // `fileURLToPath(import.meta.url)` pattern was the only way to obtain
3
+ // the on-disk path of the current ES module before Node added the
4
+ // dedicated `import.meta.dirname` and `import.meta.filename`
5
+ // properties. Once those exist, the workaround is pure noise — it
6
+ // imports `url` for one call and adds a layer the reader has to
7
+ // translate back to "the current file's directory / filename".
8
+ //
9
+ // AST-only: visit `CallExpression`, match a bare `fileURLToPath`
10
+ // callee, and check that the sole argument is the property access
11
+ // `import.meta.url`. The canonical legacy shape is the only case
12
+ // covered — other call sites of `fileURLToPath` are out of scope.
13
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-import-meta-properties.md
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ type unicornPreferImportMetaProperties struct{}
19
+
20
+ func (unicornPreferImportMetaProperties) Name() string {
21
+ return "unicorn/prefer-import-meta-properties"
22
+ }
23
+ func (unicornPreferImportMetaProperties) Visits() []shimast.Kind {
24
+ return []shimast.Kind{shimast.KindCallExpression}
25
+ }
26
+ func (unicornPreferImportMetaProperties) Check(ctx *Context, node *shimast.Node) {
27
+ call := node.AsCallExpression()
28
+ if call == nil || call.Expression == nil {
29
+ return
30
+ }
31
+ if identifierText(call.Expression) != "fileURLToPath" {
32
+ return
33
+ }
34
+ if call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
35
+ return
36
+ }
37
+ arg := stripParens(call.Arguments.Nodes[0])
38
+ if arg == nil || arg.Kind != shimast.KindPropertyAccessExpression {
39
+ return
40
+ }
41
+ access := arg.AsPropertyAccessExpression()
42
+ if access == nil {
43
+ return
44
+ }
45
+ if identifierText(access.Name()) != "url" {
46
+ return
47
+ }
48
+ receiver := stripParens(access.Expression)
49
+ if receiver == nil {
50
+ return
51
+ }
52
+ // `import.meta` parses as either a MetaProperty token or a
53
+ // PropertyAccess(import, meta) chain depending on the path; both
54
+ // resolve textually to the same source span.
55
+ if receiver.Kind == shimast.KindMetaProperty {
56
+ ctx.Report(node, "Prefer `import.meta.dirname` / `import.meta.filename` over `fileURLToPath(import.meta.url)`.")
57
+ return
58
+ }
59
+ if isMatchingPropertyAccess(receiver, "import", "meta") {
60
+ ctx.Report(node, "Prefer `import.meta.dirname` / `import.meta.filename` over `fileURLToPath(import.meta.url)`.")
61
+ }
62
+ }
63
+
64
+ func init() {
65
+ Register(unicornPreferImportMetaProperties{})
66
+ }
@@ -0,0 +1,149 @@
1
+ // unicorn/prefer-includes: `arr.indexOf(x) !== -1` (and its `=== -1`,
2
+ // `> -1`, `>= 0`, `< 0` siblings) is the legacy idiom for membership
3
+ // testing. The intent is obvious only after the reader translates the
4
+ // magic number; `arr.includes(x)` says the same thing without the
5
+ // translation step. The rule applies to both arrays and strings — both
6
+ // expose `indexOf` and both expose `includes`.
7
+ //
8
+ // AST-only: a `BinaryExpression` whose operator is one of the
9
+ // recognized comparisons and whose operands are `<call>.indexOf(...)`
10
+ // vs. one of `-1` / `0` (allowing the literal-or-unary-minus shape for
11
+ // `-1`) matches. For symmetric operators (`===`, `!==`, `==`, `!=`)
12
+ // either operand may carry the call. For asymmetric operators (`<`,
13
+ // `>=`, `>`) only the canonical orientation `indexOf(x) <op> <literal>`
14
+ // is recognized; the swapped form (`0 < indexOf(x)`) has different
15
+ // semantics (e.g. "found at index >= 1") and is intentionally NOT
16
+ // rewritten to `includes`.
17
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-includes.md
18
+ package linthost
19
+
20
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
21
+
22
+ type unicornPreferIncludes struct{}
23
+
24
+ func (unicornPreferIncludes) Name() string { return "unicorn/prefer-includes" }
25
+ func (unicornPreferIncludes) Visits() []shimast.Kind {
26
+ return []shimast.Kind{shimast.KindBinaryExpression}
27
+ }
28
+ func (unicornPreferIncludes) Check(ctx *Context, node *shimast.Node) {
29
+ bin := node.AsBinaryExpression()
30
+ if bin == nil || bin.OperatorToken == nil || bin.Left == nil || bin.Right == nil {
31
+ return
32
+ }
33
+ op := bin.OperatorToken.Kind
34
+ wantNegOne := false
35
+ wantZero := false
36
+ switch op {
37
+ case shimast.KindEqualsEqualsEqualsToken,
38
+ shimast.KindExclamationEqualsEqualsToken,
39
+ shimast.KindEqualsEqualsToken,
40
+ shimast.KindExclamationEqualsToken:
41
+ wantNegOne = true
42
+ case shimast.KindLessThanToken:
43
+ // `indexOf(x) < 0`
44
+ wantZero = true
45
+ case shimast.KindGreaterThanEqualsToken:
46
+ // `indexOf(x) >= 0`
47
+ wantZero = true
48
+ case shimast.KindGreaterThanToken:
49
+ // Not in the canonical set for this orientation; handled below
50
+ // via `> -1` matching against the negative-one form.
51
+ wantNegOne = true
52
+ default:
53
+ return
54
+ }
55
+ left := stripParens(bin.Left)
56
+ right := stripParens(bin.Right)
57
+ matched := unicornPreferIncludesMatches(left, right, op, wantNegOne, wantZero)
58
+ // Equality is symmetric — also try the swapped orientation.
59
+ // Asymmetric operators (`<`, `>=`, `>`) only match the canonical
60
+ // orientation; swapping `indexOf(x) < 0` to `0 < indexOf(x)` changes
61
+ // the meaning ("found at index >= 1") and must not be rewritten.
62
+ if !matched {
63
+ switch op {
64
+ case shimast.KindEqualsEqualsEqualsToken,
65
+ shimast.KindExclamationEqualsEqualsToken,
66
+ shimast.KindEqualsEqualsToken,
67
+ shimast.KindExclamationEqualsToken:
68
+ matched = unicornPreferIncludesMatches(right, left, op, wantNegOne, wantZero)
69
+ }
70
+ }
71
+ if matched {
72
+ ctx.Report(node, "Prefer `Array#includes()` / `String#includes()` over `indexOf` comparisons.")
73
+ }
74
+ }
75
+
76
+ func unicornPreferIncludesMatches(
77
+ callSide, literalSide *shimast.Node,
78
+ op shimast.Kind,
79
+ wantNegOne, wantZero bool,
80
+ ) bool {
81
+ if callSide == nil || literalSide == nil {
82
+ return false
83
+ }
84
+ if callSide.Kind != shimast.KindCallExpression {
85
+ return false
86
+ }
87
+ call := callSide.AsCallExpression()
88
+ if call == nil || call.Expression == nil ||
89
+ call.Expression.Kind != shimast.KindPropertyAccessExpression {
90
+ return false
91
+ }
92
+ access := call.Expression.AsPropertyAccessExpression()
93
+ if access == nil || identifierText(access.Name()) != "indexOf" {
94
+ return false
95
+ }
96
+ // `> -1`, `>= 0`, `< 0`, `=== -1`, `!== -1`, `== -1`, `!= -1`.
97
+ switch op {
98
+ case shimast.KindGreaterThanToken:
99
+ // Only `indexOf(x) > -1` matches.
100
+ return unicornPreferIncludesIsNegativeOne(literalSide)
101
+ case shimast.KindLessThanToken:
102
+ // Only `indexOf(x) < 0` matches.
103
+ return unicornPreferIncludesIsZero(literalSide)
104
+ case shimast.KindGreaterThanEqualsToken:
105
+ // Only `indexOf(x) >= 0` matches.
106
+ return unicornPreferIncludesIsZero(literalSide)
107
+ }
108
+ if wantNegOne && unicornPreferIncludesIsNegativeOne(literalSide) {
109
+ return true
110
+ }
111
+ if wantZero && unicornPreferIncludesIsZero(literalSide) {
112
+ return true
113
+ }
114
+ return false
115
+ }
116
+
117
+ func unicornPreferIncludesIsNegativeOne(node *shimast.Node) bool {
118
+ node = stripParens(node)
119
+ if node == nil {
120
+ return false
121
+ }
122
+ if node.Kind == shimast.KindPrefixUnaryExpression {
123
+ prefix := node.AsPrefixUnaryExpression()
124
+ if prefix == nil || prefix.Operator != shimast.KindMinusToken || prefix.Operand == nil {
125
+ return false
126
+ }
127
+ if prefix.Operand.Kind != shimast.KindNumericLiteral {
128
+ return false
129
+ }
130
+ return numericLiteralText(prefix.Operand) == "1"
131
+ }
132
+ if node.Kind == shimast.KindNumericLiteral {
133
+ // Some tokenizers preserve the leading `-` in the literal text.
134
+ return numericLiteralText(node) == "-1"
135
+ }
136
+ return false
137
+ }
138
+
139
+ func unicornPreferIncludesIsZero(node *shimast.Node) bool {
140
+ node = stripParens(node)
141
+ if node == nil || node.Kind != shimast.KindNumericLiteral {
142
+ return false
143
+ }
144
+ return numericLiteralText(node) == "0"
145
+ }
146
+
147
+ func init() {
148
+ Register(unicornPreferIncludes{})
149
+ }
@@ -0,0 +1,65 @@
1
+ // unicorn/prefer-json-parse-buffer: as of Node 21, `JSON.parse`
2
+ // accepts a `Buffer` directly and decodes it internally, so the common
3
+ // `JSON.parse(buf.toString())` pattern allocates an extra intermediate
4
+ // string for nothing. Dropping the `.toString()` avoids the allocation
5
+ // and reads at least as clearly.
6
+ //
7
+ // AST-only: visit `CallExpression`. Match the outer call where the
8
+ // callee is `JSON.parse` (`PropertyAccess(Identifier("JSON"), parse)`)
9
+ // AND the single argument is itself a `CallExpression` whose callee is
10
+ // `PropertyAccess(_, toString)` taking no arguments — i.e. the
11
+ // syntactic shape `JSON.parse(x.toString())`. The receiver type of
12
+ // `x` is not checked, so non-buffer receivers will produce false
13
+ // positives; this is the documented trade for an AST-only port.
14
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-json-parse-buffer.md
15
+ package linthost
16
+
17
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
18
+
19
+ type unicornPreferJsonParseBuffer struct{}
20
+
21
+ func (unicornPreferJsonParseBuffer) Name() string { return "unicorn/prefer-json-parse-buffer" }
22
+ func (unicornPreferJsonParseBuffer) Visits() []shimast.Kind {
23
+ return []shimast.Kind{shimast.KindCallExpression}
24
+ }
25
+ func (unicornPreferJsonParseBuffer) Check(ctx *Context, node *shimast.Node) {
26
+ call := node.AsCallExpression()
27
+ if call == nil || call.Expression == nil || call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
28
+ return
29
+ }
30
+ // Callee must be `JSON.parse`.
31
+ if call.Expression.Kind != shimast.KindPropertyAccessExpression {
32
+ return
33
+ }
34
+ access := call.Expression.AsPropertyAccessExpression()
35
+ if access == nil {
36
+ return
37
+ }
38
+ if identifierText(access.Expression) != "JSON" || identifierText(access.Name()) != "parse" {
39
+ return
40
+ }
41
+ // Argument must be `_.toString()` with no arguments.
42
+ arg := stripParens(call.Arguments.Nodes[0])
43
+ if arg == nil || arg.Kind != shimast.KindCallExpression {
44
+ return
45
+ }
46
+ innerCall := arg.AsCallExpression()
47
+ if innerCall == nil || innerCall.Expression == nil {
48
+ return
49
+ }
50
+ if innerCall.Arguments != nil && len(innerCall.Arguments.Nodes) != 0 {
51
+ return
52
+ }
53
+ if innerCall.Expression.Kind != shimast.KindPropertyAccessExpression {
54
+ return
55
+ }
56
+ innerAccess := innerCall.Expression.AsPropertyAccessExpression()
57
+ if innerAccess == nil || identifierText(innerAccess.Name()) != "toString" {
58
+ return
59
+ }
60
+ ctx.Report(node, "Prefer passing a `Buffer` directly to `JSON.parse` (Node 21+) over decoding to a string first.")
61
+ }
62
+
63
+ func init() {
64
+ Register(unicornPreferJsonParseBuffer{})
65
+ }
@@ -0,0 +1,38 @@
1
+ // unicorn/prefer-keyboard-event-key: `KeyboardEvent#keyCode`,
2
+ // `KeyboardEvent#charCode`, and `KeyboardEvent#which` are all
3
+ // deprecated. They expose layout-dependent integer codes that change
4
+ // across browsers and keyboard layouts and force code to maintain
5
+ // magic-number tables. `KeyboardEvent#key` returns the resolved key
6
+ // label as a string and is the spec-blessed replacement.
7
+ //
8
+ // AST-only: visit `PropertyAccessExpression` and match the right-hand
9
+ // identifier name against the deprecated property set. The receiver
10
+ // is intentionally not type-checked — the rule accepts the syntactic
11
+ // shape as the signal, which produces a small number of harmless
12
+ // false positives on non-event objects but is the correct trade for
13
+ // an AST-only port.
14
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-keyboard-event-key.md
15
+ package linthost
16
+
17
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
18
+
19
+ type unicornPreferKeyboardEventKey struct{}
20
+
21
+ func (unicornPreferKeyboardEventKey) Name() string { return "unicorn/prefer-keyboard-event-key" }
22
+ func (unicornPreferKeyboardEventKey) Visits() []shimast.Kind {
23
+ return []shimast.Kind{shimast.KindPropertyAccessExpression}
24
+ }
25
+ func (unicornPreferKeyboardEventKey) Check(ctx *Context, node *shimast.Node) {
26
+ access := node.AsPropertyAccessExpression()
27
+ if access == nil {
28
+ return
29
+ }
30
+ switch identifierText(access.Name()) {
31
+ case "keyCode", "charCode", "which":
32
+ ctx.Report(node, "Prefer `KeyboardEvent#key` over the deprecated `keyCode` / `charCode` / `which`.")
33
+ }
34
+ }
35
+
36
+ func init() {
37
+ Register(unicornPreferKeyboardEventKey{})
38
+ }
@@ -0,0 +1,48 @@
1
+ // unicorn/prefer-logical-operator-over-ternary: `x ? x : y` evaluates `x`
2
+ // twice and adds a branch only to reproduce what `x || y` (for truthy
3
+ // preservation) or `x ?? y` (for nullish-only) already say in one
4
+ // shorter, allocation-free token. The ternary spelling tends to crop up
5
+ // when authors forget the short-circuit operators exist; the rule nudges
6
+ // them back to the canonical form.
7
+ //
8
+ // AST-only: visit `KindConditionalExpression`. Fire when the textual form
9
+ // of `cond` (after `stripParens`) equals the textual form of `whenTrue`.
10
+ // That covers the `cond ? cond : alt` shape. The negated `!x ? y : x`
11
+ // case is left to a future iteration to keep the rule focused on a
12
+ // single shape.
13
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-logical-operator-over-ternary.md
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ type unicornPreferLogicalOperatorOverTernary struct{}
19
+
20
+ func (unicornPreferLogicalOperatorOverTernary) Name() string {
21
+ return "unicorn/prefer-logical-operator-over-ternary"
22
+ }
23
+ func (unicornPreferLogicalOperatorOverTernary) Visits() []shimast.Kind {
24
+ return []shimast.Kind{shimast.KindConditionalExpression}
25
+ }
26
+ func (unicornPreferLogicalOperatorOverTernary) Check(ctx *Context, node *shimast.Node) {
27
+ cond := node.AsConditionalExpression()
28
+ if cond == nil {
29
+ return
30
+ }
31
+ condExpr := stripParens(cond.Condition)
32
+ whenTrue := stripParens(cond.WhenTrue)
33
+ if condExpr == nil || whenTrue == nil {
34
+ return
35
+ }
36
+ condText := nodeText(ctx.File, condExpr)
37
+ if condText == "" {
38
+ return
39
+ }
40
+ if condText != nodeText(ctx.File, whenTrue) {
41
+ return
42
+ }
43
+ ctx.Report(node, "Prefer `a || b` / `a ?? b` over the equivalent ternary `a ? a : b`.")
44
+ }
45
+
46
+ func init() {
47
+ Register(unicornPreferLogicalOperatorOverTernary{})
48
+ }
@@ -0,0 +1,60 @@
1
+ // unicorn/prefer-math-min-max: `a < b ? a : b` is the long-hand spelling
2
+ // of `Math.min(a, b)`; the conditional adds a branch and reads each
3
+ // operand twice to do what the built-in does in one call. The built-ins
4
+ // also handle the NaN edge case the conditional silently mis-routes,
5
+ // so the rule pushes authors to switch.
6
+ //
7
+ // AST-only: visit `KindConditionalExpression`. Fire when the condition
8
+ // (after `stripParens`) is a `KindBinaryExpression` whose operator is one
9
+ // of `<`, `<=`, `>`, `>=` AND its two operands read textually as the
10
+ // two branches of the conditional (either order — `a < b ? a : b` and
11
+ // `a < b ? b : a` both qualify, since the rule covers both `Math.min`
12
+ // and `Math.max`).
13
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-math-min-max.md
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ type unicornPreferMathMinMax struct{}
19
+
20
+ func (unicornPreferMathMinMax) Name() string { return "unicorn/prefer-math-min-max" }
21
+ func (unicornPreferMathMinMax) Visits() []shimast.Kind {
22
+ return []shimast.Kind{shimast.KindConditionalExpression}
23
+ }
24
+ func (unicornPreferMathMinMax) Check(ctx *Context, node *shimast.Node) {
25
+ cond := node.AsConditionalExpression()
26
+ if cond == nil {
27
+ return
28
+ }
29
+ condExpr := stripParens(cond.Condition)
30
+ if condExpr == nil || condExpr.Kind != shimast.KindBinaryExpression {
31
+ return
32
+ }
33
+ bin := condExpr.AsBinaryExpression()
34
+ if bin == nil || bin.OperatorToken == nil {
35
+ return
36
+ }
37
+ switch bin.OperatorToken.Kind {
38
+ case shimast.KindLessThanToken,
39
+ shimast.KindLessThanEqualsToken,
40
+ shimast.KindGreaterThanToken,
41
+ shimast.KindGreaterThanEqualsToken:
42
+ default:
43
+ return
44
+ }
45
+ leftText := nodeText(ctx.File, stripParens(bin.Left))
46
+ rightText := nodeText(ctx.File, stripParens(bin.Right))
47
+ if leftText == "" || rightText == "" {
48
+ return
49
+ }
50
+ trueText := nodeText(ctx.File, stripParens(cond.WhenTrue))
51
+ falseText := nodeText(ctx.File, stripParens(cond.WhenFalse))
52
+ if (leftText == trueText && rightText == falseText) ||
53
+ (leftText == falseText && rightText == trueText) {
54
+ ctx.Report(node, "Prefer `Math.min` / `Math.max` over a conditional comparing the same two values.")
55
+ }
56
+ }
57
+
58
+ func init() {
59
+ Register(unicornPreferMathMinMax{})
60
+ }
@@ -0,0 +1,62 @@
1
+ // unicorn/prefer-math-trunc: `~~x` and `x | 0` are folk idioms for
2
+ // integer truncation that ride on the implicit Int32 coercion of the
3
+ // bitwise operators. They lose values outside the int32 range and
4
+ // confuse readers expecting a real math function. `Math.trunc(x)`
5
+ // expresses the intent directly and handles the full numeric range.
6
+ //
7
+ // AST-only: visit `KindBinaryExpression` and `KindPrefixUnaryExpression`.
8
+ // Fire on:
9
+ //
10
+ // - `x | 0` — a BinaryExpression with `|` whose right operand is the
11
+ // numeric literal `0`.
12
+ // - `~~x` — a PrefixUnaryExpression with `~` whose operand is itself
13
+ // a PrefixUnaryExpression with `~` (the parser nests them as
14
+ // `~(~x)`).
15
+ //
16
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-math-trunc.md
17
+ package linthost
18
+
19
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
20
+
21
+ type unicornPreferMathTrunc struct{}
22
+
23
+ func (unicornPreferMathTrunc) Name() string { return "unicorn/prefer-math-trunc" }
24
+ func (unicornPreferMathTrunc) Visits() []shimast.Kind {
25
+ return []shimast.Kind{shimast.KindBinaryExpression, shimast.KindPrefixUnaryExpression}
26
+ }
27
+ func (unicornPreferMathTrunc) Check(ctx *Context, node *shimast.Node) {
28
+ switch node.Kind {
29
+ case shimast.KindBinaryExpression:
30
+ expr := node.AsBinaryExpression()
31
+ if expr == nil || expr.OperatorToken == nil ||
32
+ expr.OperatorToken.Kind != shimast.KindBarToken {
33
+ return
34
+ }
35
+ right := stripParens(expr.Right)
36
+ if right == nil || right.Kind != shimast.KindNumericLiteral {
37
+ return
38
+ }
39
+ if numericLiteralText(right) != "0" {
40
+ return
41
+ }
42
+ ctx.Report(node, "Prefer `Math.trunc(x)` over `~~x` / `x | 0` for integer truncation.")
43
+ case shimast.KindPrefixUnaryExpression:
44
+ outer := node.AsPrefixUnaryExpression()
45
+ if outer == nil || outer.Operator != shimast.KindTildeToken || outer.Operand == nil {
46
+ return
47
+ }
48
+ operand := stripParens(outer.Operand)
49
+ if operand == nil || operand.Kind != shimast.KindPrefixUnaryExpression {
50
+ return
51
+ }
52
+ inner := operand.AsPrefixUnaryExpression()
53
+ if inner == nil || inner.Operator != shimast.KindTildeToken {
54
+ return
55
+ }
56
+ ctx.Report(node, "Prefer `Math.trunc(x)` over `~~x` / `x | 0` for integer truncation.")
57
+ }
58
+ }
59
+
60
+ func init() {
61
+ Register(unicornPreferMathTrunc{})
62
+ }
@@ -0,0 +1,47 @@
1
+ // unicorn/prefer-modern-dom-apis: `Node#insertBefore`, `Node#replaceChild`,
2
+ // and `Element#insertAdjacentText` are the legacy mutation methods that
3
+ // still require the caller to thread a parent node and pass arguments in
4
+ // a specific order. The `before` / `after` / `replaceWith` family on
5
+ // `ChildNode` is the supported modern shape and accepts a variadic list
6
+ // of nodes and strings without needing the parent reference.
7
+ //
8
+ // AST-only: visit each `CallExpression`, match a property-access callee
9
+ // whose method identifier is one of the legacy mutation names, and fire
10
+ // on the call. Receivers and argument shapes are not validated — the
11
+ // method name alone is the signal the rule wants to discourage.
12
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-modern-dom-apis.md
13
+ package linthost
14
+
15
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
16
+
17
+ var unicornPreferModernDomApisMethods = map[string]struct{}{
18
+ "insertBefore": {},
19
+ "replaceChild": {},
20
+ "insertAdjacentText": {},
21
+ }
22
+
23
+ type unicornPreferModernDomApis struct{}
24
+
25
+ func (unicornPreferModernDomApis) Name() string { return "unicorn/prefer-modern-dom-apis" }
26
+ func (unicornPreferModernDomApis) Visits() []shimast.Kind {
27
+ return []shimast.Kind{shimast.KindCallExpression}
28
+ }
29
+ func (unicornPreferModernDomApis) Check(ctx *Context, node *shimast.Node) {
30
+ call := node.AsCallExpression()
31
+ if call == nil || call.Expression == nil || call.Expression.Kind != shimast.KindPropertyAccessExpression {
32
+ return
33
+ }
34
+ access := call.Expression.AsPropertyAccessExpression()
35
+ if access == nil {
36
+ return
37
+ }
38
+ method := identifierText(access.Name())
39
+ if _, ok := unicornPreferModernDomApisMethods[method]; !ok {
40
+ return
41
+ }
42
+ ctx.Report(node, "Prefer `before` / `after` / `replaceWith` over `"+method+"`.")
43
+ }
44
+
45
+ func init() {
46
+ Register(unicornPreferModernDomApis{})
47
+ }
@@ -0,0 +1,70 @@
1
+ // unicorn/prefer-modern-math-apis: `Math.log(x) * Math.LOG10E` is the
2
+ // classical pre-ES2015 spelling of `Math.log10(x)`. The arithmetic
3
+ // identity is exact in the abstract but loses precision once it goes
4
+ // through IEEE-754 multiplication, and the modern call also reads as
5
+ // the operation it actually performs. The rule flags the multiplication
6
+ // form for `LOG10E` and `LOG2E`.
7
+ //
8
+ // AST-only: visit `KindBinaryExpression`. Fire when the operator is `*`
9
+ // and one operand is `Math.log(...)` while the other is
10
+ // `PropertyAccess(Identifier("Math"), LOG10E)` or `LOG2E`. The
11
+ // commutative `*` operator means `Math.log(x) * Math.LOG10E` and
12
+ // `Math.LOG10E * Math.log(x)` both match.
13
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-modern-math-apis.md
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ type unicornPreferModernMathApis struct{}
19
+
20
+ func (unicornPreferModernMathApis) Name() string { return "unicorn/prefer-modern-math-apis" }
21
+ func (unicornPreferModernMathApis) Visits() []shimast.Kind {
22
+ return []shimast.Kind{shimast.KindBinaryExpression}
23
+ }
24
+ func (unicornPreferModernMathApis) Check(ctx *Context, node *shimast.Node) {
25
+ bin := node.AsBinaryExpression()
26
+ if bin == nil || bin.OperatorToken == nil ||
27
+ bin.OperatorToken.Kind != shimast.KindAsteriskToken {
28
+ return
29
+ }
30
+ left := stripParens(bin.Left)
31
+ right := stripParens(bin.Right)
32
+ if unicornPreferModernMathApisMatchesPair(left, right) ||
33
+ unicornPreferModernMathApisMatchesPair(right, left) {
34
+ ctx.Report(node, "Prefer `Math.log10(x)` / `Math.log2(x)` over `Math.log(x) * Math.LOG10E` / `Math.log(x) * Math.LOG2E`.")
35
+ }
36
+ }
37
+
38
+ // unicornPreferModernMathApisMatchesPair reports whether `callSide` is
39
+ // `Math.log(...)` and `constSide` is `Math.LOG10E` or `Math.LOG2E`.
40
+ func unicornPreferModernMathApisMatchesPair(callSide, constSide *shimast.Node) bool {
41
+ if callSide == nil || constSide == nil {
42
+ return false
43
+ }
44
+ if callSide.Kind != shimast.KindCallExpression {
45
+ return false
46
+ }
47
+ call := callSide.AsCallExpression()
48
+ if call == nil || call.Expression == nil {
49
+ return false
50
+ }
51
+ if !isMatchingPropertyAccess(call.Expression, "Math", "log") {
52
+ return false
53
+ }
54
+ if constSide.Kind != shimast.KindPropertyAccessExpression {
55
+ return false
56
+ }
57
+ prop := constSide.AsPropertyAccessExpression()
58
+ if prop == nil || identifierText(prop.Expression) != "Math" {
59
+ return false
60
+ }
61
+ switch identifierText(prop.Name()) {
62
+ case "LOG10E", "LOG2E":
63
+ return true
64
+ }
65
+ return false
66
+ }
67
+
68
+ func init() {
69
+ Register(unicornPreferModernMathApis{})
70
+ }
@@ -0,0 +1,50 @@
1
+ // unicorn/prefer-module: ES modules are the spec-blessed module
2
+ // system and provide cross-runtime semantics that CommonJS does not.
3
+ // `require(...)` is dynamic, synchronous, and tied to Node's module
4
+ // resolver; `__dirname` and `__filename` only exist inside CJS modules
5
+ // and silently turn into `undefined` under ESM. The rule flags the
6
+ // CommonJS-only constructs so the codebase converges on ESM-native
7
+ // equivalents (`import` / `import.meta.dirname` / `import.meta.filename`).
8
+ //
9
+ // AST-only: visit `CallExpression` to match bare `require(...)` calls
10
+ // and visit `Identifier` to match value-position reads of
11
+ // `__dirname` / `__filename`. Identifier matches are gated by the
12
+ // shared value-position helper so binding sites, property keys, and
13
+ // type references are filtered out.
14
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-module.md
15
+ package linthost
16
+
17
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
18
+
19
+ type unicornPreferModule struct{}
20
+
21
+ func (unicornPreferModule) Name() string { return "unicorn/prefer-module" }
22
+ func (unicornPreferModule) Visits() []shimast.Kind {
23
+ return []shimast.Kind{shimast.KindCallExpression, shimast.KindIdentifier}
24
+ }
25
+ func (unicornPreferModule) Check(ctx *Context, node *shimast.Node) {
26
+ switch node.Kind {
27
+ case shimast.KindCallExpression:
28
+ call := node.AsCallExpression()
29
+ if call == nil || call.Expression == nil {
30
+ return
31
+ }
32
+ if identifierText(call.Expression) != "require" {
33
+ return
34
+ }
35
+ ctx.Report(node, "Prefer ES modules over CommonJS — use `import` / `import.meta.dirname` / `import.meta.filename`.")
36
+ case shimast.KindIdentifier:
37
+ name := identifierText(node)
38
+ if name != "__dirname" && name != "__filename" {
39
+ return
40
+ }
41
+ if !isUnicornValuePositionIdentifier(node) {
42
+ return
43
+ }
44
+ ctx.Report(node, "Prefer ES modules over CommonJS — use `import` / `import.meta.dirname` / `import.meta.filename`.")
45
+ }
46
+ }
47
+
48
+ func init() {
49
+ Register(unicornPreferModule{})
50
+ }