@ttsc/lint 0.13.1 → 0.14.0-dev.20260528.1

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 (464) 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 +35 -10
  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/config.go +48 -17
  116. package/linthost/config_format.go +9 -9
  117. package/linthost/directives.go +67 -25
  118. package/linthost/dispatch.go +14 -3
  119. package/linthost/engine.go +152 -31
  120. package/linthost/fix.go +2 -2
  121. package/linthost/lsp.go +747 -0
  122. package/linthost/print_dispatch.go +2 -2
  123. package/linthost/print_nodes_function.go +2 -2
  124. package/linthost/print_nodes_object.go +1 -1
  125. package/linthost/rule_names.go +14 -0
  126. package/linthost/rules_arrays.go +2 -2
  127. package/linthost/rules_boundaries.go +532 -0
  128. package/linthost/rules_camelcase.go +133 -0
  129. package/linthost/rules_complexity.go +94 -0
  130. package/linthost/rules_consistent_return.go +130 -0
  131. package/linthost/rules_console.go +1 -1
  132. package/linthost/rules_core_extra.go +739 -0
  133. package/linthost/rules_curly.go +70 -0
  134. package/linthost/rules_cypress.go +608 -0
  135. package/linthost/rules_debugger.go +2 -2
  136. package/linthost/rules_default_case.go +39 -0
  137. package/linthost/rules_default_case_last.go +46 -0
  138. package/linthost/rules_dupes.go +3 -3
  139. package/linthost/rules_empty.go +3 -3
  140. package/linthost/rules_escape.go +44 -24
  141. package/linthost/rules_eval.go +2 -2
  142. package/linthost/rules_finally.go +2 -2
  143. package/linthost/rules_format_jsdoc.go +1 -1
  144. package/linthost/rules_format_print_width.go +9 -9
  145. package/linthost/rules_format_quotes.go +1 -1
  146. package/linthost/rules_format_semi.go +1 -1
  147. package/linthost/rules_format_sort_imports.go +1 -1
  148. package/linthost/rules_format_trailing_comma.go +1 -1
  149. package/linthost/rules_functional.go +967 -0
  150. package/linthost/rules_gap.go +24 -45
  151. package/linthost/rules_grouped_accessor_pairs.go +87 -0
  152. package/linthost/rules_guard_for_in.go +198 -0
  153. package/linthost/rules_id_length.go +77 -0
  154. package/linthost/rules_imports.go +70 -2
  155. package/linthost/rules_init_declarations.go +53 -0
  156. package/linthost/rules_jest.go +618 -0
  157. package/linthost/rules_jsdoc.go +502 -0
  158. package/linthost/rules_jsx_a11y.go +1264 -0
  159. package/linthost/rules_logic.go +12 -12
  160. package/linthost/rules_loops.go +1 -1
  161. package/linthost/rules_max_classes_per_file.go +58 -0
  162. package/linthost/rules_max_depth.go +83 -0
  163. package/linthost/rules_max_lines.go +101 -0
  164. package/linthost/rules_max_lines_per_function.go +57 -0
  165. package/linthost/rules_max_nested_callbacks.go +61 -0
  166. package/linthost/rules_max_params.go +49 -0
  167. package/linthost/rules_max_statements.go +59 -0
  168. package/linthost/rules_misc.go +1 -1
  169. package/linthost/rules_nextjs.go +697 -0
  170. package/linthost/rules_no_else_return.go +75 -0
  171. package/linthost/rules_no_empty_named_blocks.go +91 -0
  172. package/linthost/rules_no_extend_native.go +51 -0
  173. package/linthost/rules_no_import_assign.go +140 -0
  174. package/linthost/rules_no_invalid_this.go +52 -0
  175. package/linthost/rules_no_loop_func.go +85 -0
  176. package/linthost/rules_no_magic_numbers.go +123 -0
  177. package/linthost/rules_no_mixed_operators.go +80 -0
  178. package/linthost/rules_no_param_reassign.go +98 -0
  179. package/linthost/rules_no_redeclare.go +270 -0
  180. package/linthost/rules_no_restricted_imports.go +105 -0
  181. package/linthost/rules_no_restricted_syntax.go +49 -0
  182. package/linthost/rules_no_shadow.go +147 -0
  183. package/linthost/rules_no_unreachable.go +77 -0
  184. package/linthost/rules_no_useless_assignment.go +120 -0
  185. package/linthost/rules_no_useless_constructor.go +245 -0
  186. package/linthost/rules_no_useless_return.go +51 -0
  187. package/linthost/rules_params.go +1 -1
  188. package/linthost/rules_playwright.go +788 -0
  189. package/linthost/rules_prefer_arrow_callback.go +124 -0
  190. package/linthost/rules_prefer_destructuring.go +98 -0
  191. package/linthost/rules_prefer_named_capture_group.go +129 -0
  192. package/linthost/rules_prefer_rest_params.go +94 -0
  193. package/linthost/rules_problems.go +41 -30
  194. package/linthost/rules_promise.go +1128 -73
  195. package/linthost/rules_protos.go +2 -2
  196. package/linthost/rules_react.go +773 -0
  197. package/linthost/rules_react_extras.go +227 -0
  198. package/linthost/rules_react_hooks.go +848 -0
  199. package/linthost/rules_react_perf.go +293 -0
  200. package/linthost/rules_react_refresh.go +583 -0
  201. package/linthost/rules_regexp.go +410 -0
  202. package/linthost/rules_security.go +830 -0
  203. package/linthost/rules_self.go +2 -2
  204. package/linthost/rules_solid.go +1073 -0
  205. package/linthost/rules_sort_imports.go +69 -0
  206. package/linthost/rules_sort_keys.go +134 -0
  207. package/linthost/rules_storybook.go +1176 -0
  208. package/linthost/rules_strings.go +4 -4
  209. package/linthost/rules_suggestions.go +38 -38
  210. package/linthost/rules_tanstack_query.go +844 -0
  211. package/linthost/rules_testing_library.go +1204 -0
  212. package/linthost/rules_throw.go +1 -1
  213. package/linthost/rules_ts.go +19 -19
  214. package/linthost/rules_ts_async.go +399 -0
  215. package/linthost/rules_ts_class_literal_property_style.go +115 -0
  216. package/linthost/rules_ts_consistent_type_exports.go +256 -0
  217. package/linthost/rules_ts_explicit_function_return_type.go +67 -0
  218. package/linthost/rules_ts_extra.go +155 -36
  219. package/linthost/rules_ts_no_base_to_string.go +218 -0
  220. package/linthost/rules_ts_no_confusing_void.go +72 -0
  221. package/linthost/rules_ts_no_deprecated.go +195 -0
  222. package/linthost/rules_ts_no_for_in_array.go +84 -0
  223. package/linthost/rules_ts_no_magic_numbers.go +124 -0
  224. package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
  225. package/linthost/rules_ts_no_misused_spread.go +104 -0
  226. package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
  227. package/linthost/rules_ts_no_restricted_types.go +62 -0
  228. package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
  229. package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
  230. package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
  231. package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
  232. package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
  233. package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
  234. package/linthost/rules_ts_no_unsafe_argument.go +82 -0
  235. package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
  236. package/linthost/rules_ts_no_unsafe_call.go +82 -0
  237. package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
  238. package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
  239. package/linthost/rules_ts_no_unsafe_return.go +126 -0
  240. package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
  241. package/linthost/rules_ts_no_useless_constructor.go +52 -0
  242. package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
  243. package/linthost/rules_ts_parameter_properties.go +38 -0
  244. package/linthost/rules_ts_prefer_find.go +178 -0
  245. package/linthost/rules_ts_prefer_includes.go +255 -0
  246. package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
  247. package/linthost/rules_ts_prefer_optional_chain.go +228 -0
  248. package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
  249. package/linthost/rules_ts_prefer_readonly.go +73 -0
  250. package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
  251. package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
  252. package/linthost/rules_ts_prefer_return_this_type.go +135 -0
  253. package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
  254. package/linthost/rules_ts_promise_function_async.go +77 -0
  255. package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
  256. package/linthost/rules_ts_require_array_sort_compare.go +96 -0
  257. package/linthost/rules_ts_restrict_plus_operands.go +127 -0
  258. package/linthost/rules_ts_restrict_template_expressions.go +95 -0
  259. package/linthost/rules_ts_simple.go +387 -0
  260. package/linthost/rules_ts_sort_type_constituents.go +144 -0
  261. package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
  262. package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
  263. package/linthost/rules_ts_unbound_method.go +126 -0
  264. package/linthost/rules_tsdoc.go +136 -0
  265. package/linthost/rules_unicorn_better_regex.go +27 -0
  266. package/linthost/rules_unicorn_catch_error_name.go +46 -0
  267. package/linthost/rules_unicorn_consistent_assert.go +47 -0
  268. package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
  269. package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
  270. package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
  271. package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
  272. package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
  273. package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
  274. package/linthost/rules_unicorn_custom_error_definition.go +138 -0
  275. package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
  276. package/linthost/rules_unicorn_error_message.go +64 -0
  277. package/linthost/rules_unicorn_escape_case.go +51 -0
  278. package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
  279. package/linthost/rules_unicorn_explicit_length_check.go +88 -0
  280. package/linthost/rules_unicorn_filename_case.go +29 -0
  281. package/linthost/rules_unicorn_import_style.go +28 -0
  282. package/linthost/rules_unicorn_isolated_functions.go +29 -0
  283. package/linthost/rules_unicorn_new_for_builtins.go +87 -0
  284. package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
  285. package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
  286. package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
  287. package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
  288. package/linthost/rules_unicorn_no_array_for_each.go +40 -0
  289. package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
  290. package/linthost/rules_unicorn_no_array_reduce.go +41 -0
  291. package/linthost/rules_unicorn_no_array_reverse.go +44 -0
  292. package/linthost/rules_unicorn_no_array_sort.go +43 -0
  293. package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
  294. package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
  295. package/linthost/rules_unicorn_no_console_spaces.go +61 -0
  296. package/linthost/rules_unicorn_no_document_cookie.go +41 -0
  297. package/linthost/rules_unicorn_no_empty_file.go +44 -0
  298. package/linthost/rules_unicorn_no_for_loop.go +102 -0
  299. package/linthost/rules_unicorn_no_hex_escape.go +42 -0
  300. package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
  301. package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
  302. package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
  303. package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
  304. package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
  305. package/linthost/rules_unicorn_no_lonely_if.go +44 -0
  306. package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
  307. package/linthost/rules_unicorn_no_named_default.go +54 -0
  308. package/linthost/rules_unicorn_no_negated_condition.go +85 -0
  309. package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
  310. package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
  311. package/linthost/rules_unicorn_no_new_array.go +30 -0
  312. package/linthost/rules_unicorn_no_new_buffer.go +31 -0
  313. package/linthost/rules_unicorn_no_null.go +24 -0
  314. package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
  315. package/linthost/rules_unicorn_no_process_exit.go +43 -0
  316. package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
  317. package/linthost/rules_unicorn_no_static_only_class.go +56 -0
  318. package/linthost/rules_unicorn_no_thenable.go +74 -0
  319. package/linthost/rules_unicorn_no_this_assignment.go +35 -0
  320. package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
  321. package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
  322. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
  323. package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
  324. package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
  325. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
  326. package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
  327. package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
  328. package/linthost/rules_unicorn_no_unused_properties.go +30 -0
  329. package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
  330. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
  331. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
  332. package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
  333. package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
  334. package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
  335. package/linthost/rules_unicorn_no_useless_spread.go +67 -0
  336. package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
  337. package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
  338. package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
  339. package/linthost/rules_unicorn_number_literal_case.go +69 -0
  340. package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
  341. package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
  342. package/linthost/rules_unicorn_prefer_array_find.go +51 -0
  343. package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
  344. package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
  345. package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
  346. package/linthost/rules_unicorn_prefer_array_some.go +67 -0
  347. package/linthost/rules_unicorn_prefer_at.go +77 -0
  348. package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
  349. package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
  350. package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
  351. package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
  352. package/linthost/rules_unicorn_prefer_code_point.go +49 -0
  353. package/linthost/rules_unicorn_prefer_date_now.go +78 -0
  354. package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
  355. package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
  356. package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
  357. package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
  358. package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
  359. package/linthost/rules_unicorn_prefer_event_target.go +36 -0
  360. package/linthost/rules_unicorn_prefer_export_from.go +129 -0
  361. package/linthost/rules_unicorn_prefer_global_this.go +127 -0
  362. package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
  363. package/linthost/rules_unicorn_prefer_includes.go +149 -0
  364. package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
  365. package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
  366. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
  367. package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
  368. package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
  369. package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
  370. package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
  371. package/linthost/rules_unicorn_prefer_module.go +50 -0
  372. package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
  373. package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
  374. package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
  375. package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
  376. package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
  377. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
  378. package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
  379. package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
  380. package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
  381. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
  382. package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
  383. package/linthost/rules_unicorn_prefer_set_has.go +42 -0
  384. package/linthost/rules_unicorn_prefer_set_size.go +48 -0
  385. package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
  386. package/linthost/rules_unicorn_prefer_single_call.go +96 -0
  387. package/linthost/rules_unicorn_prefer_spread.go +51 -0
  388. package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
  389. package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
  390. package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
  391. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
  392. package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
  393. package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
  394. package/linthost/rules_unicorn_prefer_switch.go +103 -0
  395. package/linthost/rules_unicorn_prefer_ternary.go +71 -0
  396. package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
  397. package/linthost/rules_unicorn_prefer_type_error.go +127 -0
  398. package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
  399. package/linthost/rules_unicorn_relative_url_style.go +49 -0
  400. package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
  401. package/linthost/rules_unicorn_require_module_attributes.go +54 -0
  402. package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
  403. package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
  404. package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
  405. package/linthost/rules_unicorn_string_content.go +27 -0
  406. package/linthost/rules_unicorn_switch_case_braces.go +42 -0
  407. package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
  408. package/linthost/rules_unicorn_template_indent.go +28 -0
  409. package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
  410. package/linthost/rules_unicorn_throw_new_error.go +61 -0
  411. package/linthost/rules_var.go +4 -4
  412. package/linthost/rules_vitest.go +568 -0
  413. package/package.json +3 -3
  414. package/plugin/main.go +49 -3
  415. package/rule/astutil/astutil.go +10 -3
  416. package/rule/rule.go +12 -10
  417. package/src/defaultFormat.ts +11 -8
  418. package/src/index.ts +40 -16
  419. package/src/structures/ITtscLintConfig.ts +12 -6
  420. package/src/structures/{ITtscLintFormatConfig.ts → ITtscLintFormat.ts} +2 -2
  421. package/src/structures/TtscLintRuleSetting.ts +55 -0
  422. package/src/structures/index.ts +3 -4
  423. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +128 -0
  424. package/src/structures/rules/ITtscLintBoundariesRules.ts +95 -0
  425. package/src/structures/rules/ITtscLintContributorRules.ts +21 -0
  426. package/src/structures/rules/ITtscLintCoreRules.ts +1406 -0
  427. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
  428. package/src/structures/rules/ITtscLintCypressRules.ts +145 -0
  429. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +213 -0
  430. package/src/structures/rules/ITtscLintFunctionalRules.ts +202 -0
  431. package/src/structures/rules/ITtscLintJestRules.ts +220 -0
  432. package/src/structures/rules/ITtscLintJsdocRules.ts +153 -0
  433. package/src/structures/rules/ITtscLintJsxA11yRules.ts +339 -0
  434. package/src/structures/rules/ITtscLintNextjsRules.ts +206 -0
  435. package/src/structures/rules/ITtscLintPlaywrightRules.ts +361 -0
  436. package/src/structures/rules/ITtscLintPromiseRules.ts +205 -0
  437. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
  438. package/src/structures/rules/ITtscLintReactPerfRules.ts +55 -0
  439. package/src/structures/rules/ITtscLintReactRuleOptions.ts +43 -0
  440. package/src/structures/rules/ITtscLintReactRules.ts +321 -0
  441. package/src/structures/rules/ITtscLintRegexpRules.ts +212 -0
  442. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +89 -0
  443. package/src/structures/rules/ITtscLintRules.ts +77 -0
  444. package/src/structures/rules/ITtscLintSecurityRules.ts +162 -0
  445. package/src/structures/rules/ITtscLintSolidRules.ts +202 -0
  446. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +23 -0
  447. package/src/structures/rules/ITtscLintStorybookRules.ts +193 -0
  448. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +102 -0
  449. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +24 -0
  450. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +342 -0
  451. package/src/structures/rules/ITtscLintTypeScriptRules.ts +1230 -0
  452. package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
  453. package/src/structures/rules/ITtscLintVitestRules.ts +154 -0
  454. package/src/structures/rules/index.ts +31 -0
  455. package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
  456. package/lib/structures/TtscLintRule.d.ts +0 -17
  457. package/lib/structures/TtscLintRule.js.map +0 -1
  458. package/lib/structures/TtscLintRuleMap.d.ts +0 -46
  459. package/lib/structures/TtscLintRuleMap.js.map +0 -1
  460. package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
  461. package/lib/structures/TtscLintRuleOptions.js.map +0 -1
  462. package/src/structures/TtscLintRule.ts +0 -160
  463. package/src/structures/TtscLintRuleMap.ts +0 -55
  464. package/src/structures/TtscLintRuleOptions.ts +0 -151
@@ -0,0 +1,80 @@
1
+ // unicorn/prefer-regexp-test: `if ("abc".match(/a/))` and
2
+ // `if (/a/.exec("abc"))` use match-array / null returns to encode a
3
+ // boolean question. `RegExp#test()` returns a boolean directly, avoids
4
+ // allocating the match result, and reads exactly like the question
5
+ // being asked.
6
+ //
7
+ // AST-only and parent-driven: visit each `CallExpression` whose callee
8
+ // is `PropertyAccess(_, match|exec)`, then confirm the call sits in a
9
+ // boolean position — the condition slot of `if`/`?:`, the operand of a
10
+ // unary `!`, or one of the short-circuit binary operators `&&`, `||`,
11
+ // `??`. Matches that aren't in a boolean position may still use the
12
+ // returned array, so they're out of scope.
13
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-regexp-test.md
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ type unicornPreferRegexpTest struct{}
19
+
20
+ func (unicornPreferRegexpTest) Name() string { return "unicorn/prefer-regexp-test" }
21
+ func (unicornPreferRegexpTest) Visits() []shimast.Kind {
22
+ return []shimast.Kind{shimast.KindCallExpression}
23
+ }
24
+ func (unicornPreferRegexpTest) Check(ctx *Context, node *shimast.Node) {
25
+ call := node.AsCallExpression()
26
+ if call == nil || call.Expression == nil ||
27
+ call.Expression.Kind != shimast.KindPropertyAccessExpression {
28
+ return
29
+ }
30
+ access := call.Expression.AsPropertyAccessExpression()
31
+ if access == nil {
32
+ return
33
+ }
34
+ switch identifierText(access.Name()) {
35
+ case "match", "exec":
36
+ default:
37
+ return
38
+ }
39
+ if !unicornPreferRegexpTestInBooleanPosition(node) {
40
+ return
41
+ }
42
+ ctx.Report(node, "Prefer `RegExp#test()` over `String#match()` / `RegExp#exec()` in a boolean context.")
43
+ }
44
+
45
+ // unicornPreferRegexpTestInBooleanPosition reports whether `node` sits in
46
+ // a position that consumes only its truthiness: the condition of an
47
+ // `if` / ternary, the operand of `!`, or one side of `&&` / `||` / `??`.
48
+ func unicornPreferRegexpTestInBooleanPosition(node *shimast.Node) bool {
49
+ parent := node.Parent
50
+ if parent == nil {
51
+ return false
52
+ }
53
+ switch parent.Kind {
54
+ case shimast.KindIfStatement:
55
+ ifStmt := parent.AsIfStatement()
56
+ return ifStmt != nil && ifStmt.Expression == node
57
+ case shimast.KindConditionalExpression:
58
+ cond := parent.AsConditionalExpression()
59
+ return cond != nil && cond.Condition == node
60
+ case shimast.KindPrefixUnaryExpression:
61
+ pre := parent.AsPrefixUnaryExpression()
62
+ return pre != nil && pre.Operator == shimast.KindExclamationToken
63
+ case shimast.KindBinaryExpression:
64
+ bin := parent.AsBinaryExpression()
65
+ if bin == nil || bin.OperatorToken == nil {
66
+ return false
67
+ }
68
+ switch bin.OperatorToken.Kind {
69
+ case shimast.KindAmpersandAmpersandToken,
70
+ shimast.KindBarBarToken,
71
+ shimast.KindQuestionQuestionToken:
72
+ return true
73
+ }
74
+ }
75
+ return false
76
+ }
77
+
78
+ func init() {
79
+ Register(unicornPreferRegexpTest{})
80
+ }
@@ -0,0 +1,53 @@
1
+ // unicorn/prefer-response-static-json: `new Response(JSON.stringify(value), …)`
2
+ // is the manual two-step recipe — stringify then construct — that the
3
+ // platform's `Response.json(value, …)` static factory now performs in
4
+ // one call. The static factory also sets `Content-Type: application/json`
5
+ // automatically; the manual form leaves the header to the author.
6
+ //
7
+ // AST-only: visit each `NewExpression`. Match when the callee identifier
8
+ // is `Response` AND the first argument is a `CallExpression` whose
9
+ // callee is the property chain `JSON.stringify`. Other arguments (init
10
+ // options) are intentionally not inspected — the rule fires regardless
11
+ // of headers/status because the simpler factory handles both shapes.
12
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-response-static-json.md
13
+ package linthost
14
+
15
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
16
+
17
+ type unicornPreferResponseStaticJson struct{}
18
+
19
+ func (unicornPreferResponseStaticJson) Name() string {
20
+ return "unicorn/prefer-response-static-json"
21
+ }
22
+ func (unicornPreferResponseStaticJson) Visits() []shimast.Kind {
23
+ return []shimast.Kind{shimast.KindNewExpression}
24
+ }
25
+ func (unicornPreferResponseStaticJson) Check(ctx *Context, node *shimast.Node) {
26
+ ne := node.AsNewExpression()
27
+ if ne == nil || identifierText(ne.Expression) != "Response" {
28
+ return
29
+ }
30
+ if ne.Arguments == nil || len(ne.Arguments.Nodes) == 0 {
31
+ return
32
+ }
33
+ first := stripParens(ne.Arguments.Nodes[0])
34
+ if first == nil || first.Kind != shimast.KindCallExpression {
35
+ return
36
+ }
37
+ call := first.AsCallExpression()
38
+ if call == nil || call.Expression == nil ||
39
+ call.Expression.Kind != shimast.KindPropertyAccessExpression {
40
+ return
41
+ }
42
+ access := call.Expression.AsPropertyAccessExpression()
43
+ if access == nil ||
44
+ identifierText(access.Expression) != "JSON" ||
45
+ identifierText(access.Name()) != "stringify" {
46
+ return
47
+ }
48
+ ctx.Report(node, "Prefer `Response.json(value)` over `new Response(JSON.stringify(value), ...)`.")
49
+ }
50
+
51
+ func init() {
52
+ Register(unicornPreferResponseStaticJson{})
53
+ }
@@ -0,0 +1,42 @@
1
+ // unicorn/prefer-set-has: `[a, b, c].includes(x)` is `O(n)` per lookup,
2
+ // while `new Set([a, b, c]).has(x)` is `O(1)` after a single `O(n)`
3
+ // construction. For repeated membership lookups against a fixed
4
+ // collection the `Set` form is meaningfully faster and clearer about
5
+ // intent.
6
+ //
7
+ // AST-only minimum-viable port: only the literal-array-receiver shape
8
+ // (`[…].includes(x)`) is reported. The upstream rule also reasons
9
+ // about typed variable receivers, which requires type-flow analysis
10
+ // out of scope for this slice; expanding to typed receivers is a
11
+ // follow-up.
12
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-set-has.md
13
+ package linthost
14
+
15
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
16
+
17
+ type unicornPreferSetHas struct{}
18
+
19
+ func (unicornPreferSetHas) Name() string { return "unicorn/prefer-set-has" }
20
+ func (unicornPreferSetHas) Visits() []shimast.Kind {
21
+ return []shimast.Kind{shimast.KindCallExpression}
22
+ }
23
+ func (unicornPreferSetHas) Check(ctx *Context, node *shimast.Node) {
24
+ call := node.AsCallExpression()
25
+ if call == nil || call.Expression == nil ||
26
+ call.Expression.Kind != shimast.KindPropertyAccessExpression {
27
+ return
28
+ }
29
+ access := call.Expression.AsPropertyAccessExpression()
30
+ if access == nil || identifierText(access.Name()) != "includes" {
31
+ return
32
+ }
33
+ receiver := stripParens(access.Expression)
34
+ if receiver == nil || receiver.Kind != shimast.KindArrayLiteralExpression {
35
+ return
36
+ }
37
+ ctx.Report(node, "Prefer `Set#has()` over `Array#includes()` for repeated membership lookups against a constant collection.")
38
+ }
39
+
40
+ func init() {
41
+ Register(unicornPreferSetHas{})
42
+ }
@@ -0,0 +1,48 @@
1
+ // unicorn/prefer-set-size: `[...set].length` materializes the entire Set
2
+ // into a throwaway array just to read its element count. `Set#size` is a
3
+ // constant-time property that returns the same value without the
4
+ // allocation, and reads more naturally for the intent the code expresses.
5
+ //
6
+ // AST-only: visit each `PropertyAccessExpression`, match when the
7
+ // accessed property is named `length` AND the receiver is an
8
+ // array-literal expression whose only element is a SpreadElement (i.e.
9
+ // `[...x]`). The contents of the spread are not inspected — the
10
+ // syntactic shape `[...x].length` is the signal regardless of whether
11
+ // the spread source is statically a Set.
12
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-set-size.md
13
+ package linthost
14
+
15
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
16
+
17
+ type unicornPreferSetSize struct{}
18
+
19
+ func (unicornPreferSetSize) Name() string { return "unicorn/prefer-set-size" }
20
+ func (unicornPreferSetSize) Visits() []shimast.Kind {
21
+ return []shimast.Kind{shimast.KindPropertyAccessExpression}
22
+ }
23
+ func (unicornPreferSetSize) Check(ctx *Context, node *shimast.Node) {
24
+ access := node.AsPropertyAccessExpression()
25
+ if access == nil {
26
+ return
27
+ }
28
+ if identifierText(access.Name()) != "length" {
29
+ return
30
+ }
31
+ receiver := stripParens(access.Expression)
32
+ if receiver == nil || receiver.Kind != shimast.KindArrayLiteralExpression {
33
+ return
34
+ }
35
+ arr := receiver.AsArrayLiteralExpression()
36
+ if arr == nil || arr.Elements == nil || len(arr.Elements.Nodes) != 1 {
37
+ return
38
+ }
39
+ only := arr.Elements.Nodes[0]
40
+ if only == nil || only.Kind != shimast.KindSpreadElement {
41
+ return
42
+ }
43
+ ctx.Report(node, "Prefer `Set#size` over `[...set].length`.")
44
+ }
45
+
46
+ func init() {
47
+ Register(unicornPreferSetSize{})
48
+ }
@@ -0,0 +1,34 @@
1
+ // unicorn/prefer-simple-condition-first: when a `&&`/`||` chain mixes
2
+ // a "simple" operand (a bare identifier, a small literal comparison)
3
+ // with a "complex" one (a function call, a property chain), short-
4
+ // circuit evaluation reads more naturally if the simple operand sits
5
+ // to the left — the cheap test is the gate, the expensive test runs
6
+ // only if the gate passes.
7
+ //
8
+ // Escape-hatch / no-op port: ranking arbitrary expressions by
9
+ // "simpleness" requires a stable complexity heuristic the upstream rule
10
+ // embeds across hundreds of lines (literal counts, identifier depth,
11
+ // call-chain weight, parenthesization). Without a faithful port of that
12
+ // heuristic the rule would either over-fire on equally-weighted operands
13
+ // or under-fire on the cases it is meant to catch; either way users get
14
+ // confusing diagnostics. Registered so the typed-key/Go-registry parity
15
+ // check passes and so users can configure the rule, but it intentionally
16
+ // reports nothing until the heuristic lands in a follow-up.
17
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-simple-condition-first.md
18
+ package linthost
19
+
20
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
21
+
22
+ type unicornPreferSimpleConditionFirst struct{}
23
+
24
+ func (unicornPreferSimpleConditionFirst) Name() string {
25
+ return "unicorn/prefer-simple-condition-first"
26
+ }
27
+ func (unicornPreferSimpleConditionFirst) Visits() []shimast.Kind { return nil }
28
+ func (unicornPreferSimpleConditionFirst) Check(_ *Context, _ *shimast.Node) {
29
+ // Intentionally empty — see file header for the escape-hatch rationale.
30
+ }
31
+
32
+ func init() {
33
+ Register(unicornPreferSimpleConditionFirst{})
34
+ }
@@ -0,0 +1,96 @@
1
+ // unicorn/prefer-single-call: `xs.push(1); xs.push(2);` repeats the
2
+ // `xs.push` lookup and the call dispatch for what is conceptually one
3
+ // "append these values" operation. Variadic methods like `push`,
4
+ // `unshift`, `addEventListener`, and `removeEventListener` accept
5
+ // multiple arguments specifically so authors can collapse the back-to-
6
+ // back form into a single call.
7
+ //
8
+ // AST-only: visit each `Block` AND `SourceFile`, scan the statement
9
+ // list for any pair of consecutive `ExpressionStatement`s whose
10
+ // expressions are `CallExpression`s targeting
11
+ // `PropertyAccess(<sameReceiverText>, <sameMethod>)` where the method
12
+ // is one of the variadic appenders. Receiver equivalence is decided
13
+ // by source-text comparison so chained receivers (e.g. `obj.list.push`)
14
+ // line up exactly. Report on the second statement so the diagnostic
15
+ // anchors to the redundant call.
16
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-single-call.md
17
+ package linthost
18
+
19
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
20
+
21
+ type unicornPreferSingleCall struct{}
22
+
23
+ func (unicornPreferSingleCall) Name() string { return "unicorn/prefer-single-call" }
24
+ func (unicornPreferSingleCall) Visits() []shimast.Kind {
25
+ return []shimast.Kind{shimast.KindBlock, shimast.KindSourceFile}
26
+ }
27
+ func (unicornPreferSingleCall) Check(ctx *Context, node *shimast.Node) {
28
+ var stmts []*shimast.Node
29
+ switch node.Kind {
30
+ case shimast.KindBlock:
31
+ block := node.AsBlock()
32
+ if block == nil || block.Statements == nil {
33
+ return
34
+ }
35
+ stmts = block.Statements.Nodes
36
+ case shimast.KindSourceFile:
37
+ file := node.AsSourceFile()
38
+ if file == nil || file.Statements == nil {
39
+ return
40
+ }
41
+ stmts = file.Statements.Nodes
42
+ default:
43
+ return
44
+ }
45
+ for i := 1; i < len(stmts); i++ {
46
+ prevReceiver, prevMethod := unicornPreferSingleCallExtract(ctx, stmts[i-1])
47
+ if prevReceiver == "" {
48
+ continue
49
+ }
50
+ currReceiver, currMethod := unicornPreferSingleCallExtract(ctx, stmts[i])
51
+ if currReceiver == "" {
52
+ continue
53
+ }
54
+ if prevReceiver != currReceiver || prevMethod != currMethod {
55
+ continue
56
+ }
57
+ ctx.Report(stmts[i], "Combine consecutive `"+currMethod+"` calls with multiple arguments into a single call.")
58
+ }
59
+ }
60
+
61
+ // unicornPreferSingleCallExtract returns (receiverText, methodName) for a
62
+ // statement of the shape `<receiver>.<method>(…);` where `method` is one
63
+ // of the variadic appenders the rule targets. Returns ("", "") for any
64
+ // other shape.
65
+ func unicornPreferSingleCallExtract(ctx *Context, stmt *shimast.Node) (string, string) {
66
+ if stmt == nil || stmt.Kind != shimast.KindExpressionStatement {
67
+ return "", ""
68
+ }
69
+ exprStmt := stmt.AsExpressionStatement()
70
+ if exprStmt == nil || exprStmt.Expression == nil {
71
+ return "", ""
72
+ }
73
+ call := stripParens(exprStmt.Expression)
74
+ if call == nil || call.Kind != shimast.KindCallExpression {
75
+ return "", ""
76
+ }
77
+ c := call.AsCallExpression()
78
+ if c == nil || c.Expression == nil || c.Expression.Kind != shimast.KindPropertyAccessExpression {
79
+ return "", ""
80
+ }
81
+ access := c.Expression.AsPropertyAccessExpression()
82
+ if access == nil || access.Expression == nil {
83
+ return "", ""
84
+ }
85
+ method := identifierText(access.Name())
86
+ switch method {
87
+ case "push", "unshift", "addEventListener", "removeEventListener":
88
+ default:
89
+ return "", ""
90
+ }
91
+ return nodeText(ctx.File, access.Expression), method
92
+ }
93
+
94
+ func init() {
95
+ Register(unicornPreferSingleCall{})
96
+ }
@@ -0,0 +1,51 @@
1
+ // unicorn/prefer-spread: `Array.from(x)` with a single iterable argument
2
+ // is equivalent to a spread copy `[...x]`. The spread form is shorter,
3
+ // reads as a value-level operation rather than a constructor call, and
4
+ // removes the `Array` global from the read path entirely.
5
+ //
6
+ // AST-only: visit each `CallExpression`, match `Array.from(x)` — a
7
+ // callee that is a property access reading `from` on a bare identifier
8
+ // `Array`, with exactly one argument. The single-argument restriction
9
+ // is load-bearing: `Array.from(x, mapFn)` and `Array.from(x, mapFn,
10
+ // thisArg)` have observable behavior the spread does not (the mapper
11
+ // receives the index, and `thisArg` is bound on a non-arrow mapper), so
12
+ // the rule deliberately stays away from them.
13
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-spread.md
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ type unicornPreferSpread struct{}
19
+
20
+ func (unicornPreferSpread) Name() string { return "unicorn/prefer-spread" }
21
+ func (unicornPreferSpread) Visits() []shimast.Kind {
22
+ return []shimast.Kind{shimast.KindCallExpression}
23
+ }
24
+ func (unicornPreferSpread) Check(ctx *Context, node *shimast.Node) {
25
+ call := node.AsCallExpression()
26
+ if call == nil || call.Expression == nil {
27
+ return
28
+ }
29
+ if call.Expression.Kind != shimast.KindPropertyAccessExpression {
30
+ return
31
+ }
32
+ access := call.Expression.AsPropertyAccessExpression()
33
+ if access == nil {
34
+ return
35
+ }
36
+ if identifierText(access.Name()) != "from" {
37
+ return
38
+ }
39
+ receiver := stripParens(access.Expression)
40
+ if identifierText(receiver) != "Array" {
41
+ return
42
+ }
43
+ if call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
44
+ return
45
+ }
46
+ ctx.Report(node, "Prefer spread `[...x]` over `Array.from(x)` for single-arg shallow copies.")
47
+ }
48
+
49
+ func init() {
50
+ Register(unicornPreferSpread{})
51
+ }
@@ -0,0 +1,43 @@
1
+ // unicorn/prefer-string-raw: a string literal whose source contains
2
+ // `\\` (an escaped backslash) is using the escape syntax to represent a
3
+ // literal backslash. The same value, written through `String.raw` as
4
+ // a template literal, drops every backslash escape and reads as the
5
+ // literal text the author meant — particularly noticeable for Windows
6
+ // paths, regex source strings, and TeX-shaped snippets.
7
+ //
8
+ // AST-only: visit `KindStringLiteral` and
9
+ // `KindNoSubstitutionTemplateLiteral`. The match keys on the raw source
10
+ // bytes of the literal node — `nodeText` returns the as-written source
11
+ // — and fires when those bytes contain the two-character sequence `\\`,
12
+ // i.e. an escaped backslash that `String.raw` would render literally.
13
+ // Untagged template literals with substitutions are out of scope; this
14
+ // rule only addresses the "single literal of fixed text" case.
15
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-raw.md
16
+ package linthost
17
+
18
+ import (
19
+ "strings"
20
+
21
+ shimast "github.com/microsoft/typescript-go/shim/ast"
22
+ )
23
+
24
+ type unicornPreferStringRaw struct{}
25
+
26
+ func (unicornPreferStringRaw) Name() string { return "unicorn/prefer-string-raw" }
27
+ func (unicornPreferStringRaw) Visits() []shimast.Kind {
28
+ return []shimast.Kind{shimast.KindStringLiteral, shimast.KindNoSubstitutionTemplateLiteral}
29
+ }
30
+ func (unicornPreferStringRaw) Check(ctx *Context, node *shimast.Node) {
31
+ raw := nodeText(ctx.File, node)
32
+ if raw == "" {
33
+ return
34
+ }
35
+ if !strings.Contains(raw, `\\`) {
36
+ return
37
+ }
38
+ ctx.Report(node, "Prefer `String.raw` for strings with backslash escapes.")
39
+ }
40
+
41
+ func init() {
42
+ Register(unicornPreferStringRaw{})
43
+ }
@@ -0,0 +1,95 @@
1
+ // unicorn/prefer-string-replace-all: `"abc".replace(/a/g, "x")` is the
2
+ // pre-ES2021 idiom for "replace every occurrence". ES2021's
3
+ // `String#replaceAll` does the same thing without the regex flag
4
+ // detour. The rule fires on `.replace(/<pattern>/g, replacement)` so
5
+ // authors switch to the explicit method.
6
+ //
7
+ // AST-only: a `CallExpression` whose callee is `.replace` AND whose
8
+ // first argument is a `RegularExpressionLiteral` carrying the `g` flag
9
+ // in its trailing flag block matches. The flag is read from the raw
10
+ // source text — the AST does not split pattern from flags — using the
11
+ // shared `nodeText` accessor.
12
+ //
13
+ // To preserve semantics, the pattern body must also be literal — any
14
+ // regex metacharacter (`\`, `.`, `*`, `+`, `?`, `[`, `]`, `(`, `)`,
15
+ // `{`, `}`, `|`, `^`, `$`) disqualifies the rewrite, because
16
+ // `/<pat>/g` and `.replaceAll(<pat>, ...)` mean different things when
17
+ // the pattern is anything but a fixed string.
18
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-replace-all.md
19
+ package linthost
20
+
21
+ import (
22
+ "strings"
23
+
24
+ shimast "github.com/microsoft/typescript-go/shim/ast"
25
+ )
26
+
27
+ type unicornPreferStringReplaceAll struct{}
28
+
29
+ func (unicornPreferStringReplaceAll) Name() string { return "unicorn/prefer-string-replace-all" }
30
+ func (unicornPreferStringReplaceAll) Visits() []shimast.Kind {
31
+ return []shimast.Kind{shimast.KindCallExpression}
32
+ }
33
+ func (unicornPreferStringReplaceAll) Check(ctx *Context, node *shimast.Node) {
34
+ call := node.AsCallExpression()
35
+ if call == nil || call.Expression == nil ||
36
+ call.Expression.Kind != shimast.KindPropertyAccessExpression {
37
+ return
38
+ }
39
+ access := call.Expression.AsPropertyAccessExpression()
40
+ if access == nil || identifierText(access.Name()) != "replace" {
41
+ return
42
+ }
43
+ if call.Arguments == nil || len(call.Arguments.Nodes) < 1 {
44
+ return
45
+ }
46
+ first := stripParens(call.Arguments.Nodes[0])
47
+ if first == nil || first.Kind != shimast.KindRegularExpressionLiteral {
48
+ return
49
+ }
50
+ raw := nodeText(ctx.File, first)
51
+ if !unicornPreferStringReplaceAllHasGlobalFlag(raw) {
52
+ return
53
+ }
54
+ if !unicornPreferStringReplaceAllIsLiteralPattern(raw) {
55
+ return
56
+ }
57
+ ctx.Report(node, "Prefer `String#replaceAll(literal, replacement)` over `replace(/literal/g, replacement)`.")
58
+ }
59
+
60
+ // unicornPreferStringReplaceAllHasGlobalFlag returns true when `raw` (the
61
+ // source text of a RegularExpressionLiteral, including the surrounding
62
+ // `/` delimiters and trailing flag block) carries the `g` flag.
63
+ func unicornPreferStringReplaceAllHasGlobalFlag(raw string) bool {
64
+ if len(raw) < 3 || raw[0] != '/' {
65
+ return false
66
+ }
67
+ closing := strings.LastIndexByte(raw, '/')
68
+ if closing <= 0 {
69
+ return false
70
+ }
71
+ flags := raw[closing+1:]
72
+ return strings.ContainsRune(flags, 'g')
73
+ }
74
+
75
+ // unicornPreferStringReplaceAllIsLiteralPattern returns true when the
76
+ // pattern body of `raw` (the source text of a RegularExpressionLiteral)
77
+ // contains no regex metacharacters. Conservative: any metachar — even
78
+ // an escaped one like `\.` — disqualifies the rewrite, because
79
+ // recovering the original character cleanly from raw source requires
80
+ // regex-aware parsing we don't do here.
81
+ func unicornPreferStringReplaceAllIsLiteralPattern(raw string) bool {
82
+ if len(raw) < 3 || raw[0] != '/' {
83
+ return false
84
+ }
85
+ closing := strings.LastIndexByte(raw, '/')
86
+ if closing <= 0 {
87
+ return false
88
+ }
89
+ body := raw[1:closing]
90
+ return !strings.ContainsAny(body, `\.*+?[](){}|^$`)
91
+ }
92
+
93
+ func init() {
94
+ Register(unicornPreferStringReplaceAll{})
95
+ }
@@ -0,0 +1,43 @@
1
+ // unicorn/prefer-string-slice: `String#substr` is deprecated and
2
+ // `String#substring` has surprising "swap arguments when end < start"
3
+ // semantics. `String#slice` is the single modern alternative whose
4
+ // behavior matches author intent. The rule fires on any `.substr(…)`
5
+ // or `.substring(…)` callsite so the codebase converges on `.slice`.
6
+ //
7
+ // AST-only: a `CallExpression` whose callee is a
8
+ // `PropertyAccessExpression` ending in `substr` or `substring`
9
+ // matches. Receiver typing is intentionally not checked — both names
10
+ // exist almost exclusively on strings in real code, and the
11
+ // upstream rule treats them as banned regardless.
12
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-slice.md
13
+ package linthost
14
+
15
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
16
+
17
+ type unicornPreferStringSlice struct{}
18
+
19
+ func (unicornPreferStringSlice) Name() string { return "unicorn/prefer-string-slice" }
20
+ func (unicornPreferStringSlice) Visits() []shimast.Kind {
21
+ return []shimast.Kind{shimast.KindCallExpression}
22
+ }
23
+ func (unicornPreferStringSlice) Check(ctx *Context, node *shimast.Node) {
24
+ call := node.AsCallExpression()
25
+ if call == nil || call.Expression == nil ||
26
+ call.Expression.Kind != shimast.KindPropertyAccessExpression {
27
+ return
28
+ }
29
+ access := call.Expression.AsPropertyAccessExpression()
30
+ if access == nil {
31
+ return
32
+ }
33
+ switch identifierText(access.Name()) {
34
+ case "substr", "substring":
35
+ default:
36
+ return
37
+ }
38
+ ctx.Report(node, "Prefer `String#slice()` over `substr` / `substring`.")
39
+ }
40
+
41
+ func init() {
42
+ Register(unicornPreferStringSlice{})
43
+ }