@ttsc/lint 0.13.1 → 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 (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,43 @@
1
+ // unicorn/no-array-sort: `Array#sort()` mutates the array in place and
2
+ // returns the same reference, so any caller holding the original sees
3
+ // the sorted order too. ES2023 introduced `Array#toSorted()`, which
4
+ // returns a fresh sorted copy and leaves the source untouched; the rule
5
+ // pushes authors toward the non-mutating form.
6
+ //
7
+ // AST-only: visit each `CallExpression`, check that the callee is a
8
+ // property access whose method identifier is `sort`, and accept either
9
+ // zero arguments or exactly one (the optional comparator). Calls with
10
+ // two or more arguments are almost certainly a different `sort` on a
11
+ // user-defined type and are excluded by design.
12
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-array-sort.md
13
+ package linthost
14
+
15
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
16
+
17
+ type unicornNoArraySort struct{}
18
+
19
+ func (unicornNoArraySort) Name() string { return "unicorn/no-array-sort" }
20
+ func (unicornNoArraySort) Visits() []shimast.Kind {
21
+ return []shimast.Kind{shimast.KindCallExpression}
22
+ }
23
+ func (unicornNoArraySort) Check(ctx *Context, node *shimast.Node) {
24
+ call := node.AsCallExpression()
25
+ if call == nil || call.Expression == nil || call.Expression.Kind != shimast.KindPropertyAccessExpression {
26
+ return
27
+ }
28
+ access := call.Expression.AsPropertyAccessExpression()
29
+ if access == nil {
30
+ return
31
+ }
32
+ if identifierText(access.Name()) != "sort" {
33
+ return
34
+ }
35
+ if call.Arguments != nil && len(call.Arguments.Nodes) > 1 {
36
+ return
37
+ }
38
+ ctx.Report(node, "Prefer `Array#toSorted()` over the mutating `Array#sort()`.")
39
+ }
40
+
41
+ func init() {
42
+ Register(unicornNoArraySort{})
43
+ }
@@ -0,0 +1,40 @@
1
+ // unicorn/no-await-expression-member: `(await foo).bar` and
2
+ // `(await foo)[index]` mix two reading positions in one expression —
3
+ // the resolution step (`await foo`) and the projection step (`.bar`).
4
+ // Splitting them into a temporary `const value = await foo; value.bar`
5
+ // makes the order of operations explicit and lines up better with
6
+ // stepping through the async function in a debugger.
7
+ //
8
+ // AST-only: any `PropertyAccessExpression` whose receiver is an
9
+ // `AwaitExpression` (possibly wrapped in `ParenthesizedExpression`) fires.
10
+ // `ElementAccessExpression` is left out of this minimal pass — the
11
+ // PropertyAccess shape is the canonical violation cited in the upstream
12
+ // docs and matches the receiver shape directly via `stripParens`.
13
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-await-expression-member.md
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ type unicornNoAwaitExpressionMember struct{}
19
+
20
+ func (unicornNoAwaitExpressionMember) Name() string {
21
+ return "unicorn/no-await-expression-member"
22
+ }
23
+ func (unicornNoAwaitExpressionMember) Visits() []shimast.Kind {
24
+ return []shimast.Kind{shimast.KindPropertyAccessExpression}
25
+ }
26
+ func (unicornNoAwaitExpressionMember) Check(ctx *Context, node *shimast.Node) {
27
+ access := node.AsPropertyAccessExpression()
28
+ if access == nil {
29
+ return
30
+ }
31
+ receiver := stripParens(access.Expression)
32
+ if receiver == nil || receiver.Kind != shimast.KindAwaitExpression {
33
+ return
34
+ }
35
+ ctx.Report(node, "Don't use member access on an `await` expression — assign the awaited value to a variable first.")
36
+ }
37
+
38
+ func init() {
39
+ Register(unicornNoAwaitExpressionMember{})
40
+ }
@@ -0,0 +1,69 @@
1
+ // unicorn/no-await-in-promise-methods: awaiting an element inside the
2
+ // array argument of `Promise.all` / `Promise.allSettled` / `Promise.race`
3
+ // / `Promise.any` defeats the parallelism the call exists for. The
4
+ // awaits resolve serially in source order before the array is even
5
+ // handed to `Promise.<method>`, so the combinator only sees the
6
+ // already-resolved values.
7
+ //
8
+ // AST-only: visit each `CallExpression`, match the callee against
9
+ // `Promise.<method>` for the four parallel combinators, and check the
10
+ // sole argument's `ArrayLiteralExpression` elements for any
11
+ // `AwaitExpression` shape. Fire on the offending await node so the
12
+ // report anchors to the actual misuse.
13
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-await-in-promise-methods.md
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ var unicornNoAwaitInPromiseMethodsMethods = map[string]struct{}{
19
+ "all": {},
20
+ "allSettled": {},
21
+ "race": {},
22
+ "any": {},
23
+ }
24
+
25
+ type unicornNoAwaitInPromiseMethods struct{}
26
+
27
+ func (unicornNoAwaitInPromiseMethods) Name() string {
28
+ return "unicorn/no-await-in-promise-methods"
29
+ }
30
+ func (unicornNoAwaitInPromiseMethods) Visits() []shimast.Kind {
31
+ return []shimast.Kind{shimast.KindCallExpression}
32
+ }
33
+ func (unicornNoAwaitInPromiseMethods) Check(ctx *Context, node *shimast.Node) {
34
+ call := node.AsCallExpression()
35
+ if call == nil || call.Expression == nil || call.Expression.Kind != shimast.KindPropertyAccessExpression {
36
+ return
37
+ }
38
+ access := call.Expression.AsPropertyAccessExpression()
39
+ if access == nil {
40
+ return
41
+ }
42
+ if identifierText(access.Expression) != "Promise" {
43
+ return
44
+ }
45
+ method := identifierText(access.Name())
46
+ if _, ok := unicornNoAwaitInPromiseMethodsMethods[method]; !ok {
47
+ return
48
+ }
49
+ if call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
50
+ return
51
+ }
52
+ arg := call.Arguments.Nodes[0]
53
+ if arg == nil || arg.Kind != shimast.KindArrayLiteralExpression {
54
+ return
55
+ }
56
+ arr := arg.AsArrayLiteralExpression()
57
+ if arr == nil || arr.Elements == nil {
58
+ return
59
+ }
60
+ for _, elem := range arr.Elements.Nodes {
61
+ if elem != nil && elem.Kind == shimast.KindAwaitExpression {
62
+ ctx.Report(elem, "Don't `await` inside `Promise."+method+"` array members — the awaits serialize the calls.")
63
+ }
64
+ }
65
+ }
66
+
67
+ func init() {
68
+ Register(unicornNoAwaitInPromiseMethods{})
69
+ }
@@ -0,0 +1,61 @@
1
+ // unicorn/no-console-spaces: `console.log("a ", "b")` produces
2
+ // `"a b"` with a doubled space because the runtime already inserts a
3
+ // single ASCII space between arguments. Leading/trailing whitespace on
4
+ // the literal duplicates that separator and is almost always a leftover
5
+ // from hand-formatting. The rule flags every string-literal argument
6
+ // whose content starts or ends with a space so the source converges on
7
+ // argument-only content and the runtime owns the separator.
8
+ //
9
+ // AST-only and identifier-text-driven: dispatch on `CallExpression`,
10
+ // match a `console.<method>` callee against the six common log
11
+ // methods, and report each `StringLiteral` argument with a leading or
12
+ // trailing space. The receiver is matched by identifier text only;
13
+ // shadowed `console` bindings are out of scope, mirroring the other
14
+ // console-shape rules in this family.
15
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-console-spaces.md
16
+ package linthost
17
+
18
+ import (
19
+ "strings"
20
+
21
+ shimast "github.com/microsoft/typescript-go/shim/ast"
22
+ )
23
+
24
+ type unicornNoConsoleSpaces struct{}
25
+
26
+ func (unicornNoConsoleSpaces) Name() string { return "unicorn/no-console-spaces" }
27
+ func (unicornNoConsoleSpaces) Visits() []shimast.Kind {
28
+ return []shimast.Kind{shimast.KindCallExpression}
29
+ }
30
+ func (unicornNoConsoleSpaces) Check(ctx *Context, node *shimast.Node) {
31
+ call := node.AsCallExpression()
32
+ if call == nil || call.Expression == nil ||
33
+ call.Expression.Kind != shimast.KindPropertyAccessExpression {
34
+ return
35
+ }
36
+ access := call.Expression.AsPropertyAccessExpression()
37
+ if access == nil || identifierText(access.Expression) != "console" {
38
+ return
39
+ }
40
+ switch identifierText(access.Name()) {
41
+ case "log", "warn", "error", "info", "debug", "trace":
42
+ default:
43
+ return
44
+ }
45
+ if call.Arguments == nil {
46
+ return
47
+ }
48
+ for _, arg := range call.Arguments.Nodes {
49
+ if arg == nil || arg.Kind != shimast.KindStringLiteral {
50
+ continue
51
+ }
52
+ text := stringLiteralText(arg)
53
+ if strings.HasPrefix(text, " ") || strings.HasSuffix(text, " ") {
54
+ ctx.Report(arg, "Don't include leading or trailing spaces in `console.<method>` arguments.")
55
+ }
56
+ }
57
+ }
58
+
59
+ func init() {
60
+ Register(unicornNoConsoleSpaces{})
61
+ }
@@ -0,0 +1,41 @@
1
+ // unicorn/no-document-cookie: writing to (or reading) `document.cookie`
2
+ // directly mixes name/value parsing, serialization, attribute handling,
3
+ // and quoting concerns into one mutable string. The replacement is the
4
+ // async Cookie Store API (`cookieStore.set`/`cookieStore.get`) or a
5
+ // dedicated cookie wrapper — both surface attribute fields as data
6
+ // instead of string-encoded options.
7
+ //
8
+ // AST-only and identifier-text-driven: any `PropertyAccessExpression`
9
+ // whose receiver identifier is `document` and whose property name is
10
+ // `cookie` matches, so the same visit handles both the read
11
+ // (`document.cookie`) and the assignment LHS (`document.cookie = "..."`).
12
+ // Shadowed `document` bindings and computed/optional access are out of
13
+ // scope, mirroring `unicorn/no-process-exit`.
14
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-document-cookie.md
15
+ package linthost
16
+
17
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
18
+
19
+ type unicornNoDocumentCookie struct{}
20
+
21
+ func (unicornNoDocumentCookie) Name() string { return "unicorn/no-document-cookie" }
22
+ func (unicornNoDocumentCookie) Visits() []shimast.Kind {
23
+ return []shimast.Kind{shimast.KindPropertyAccessExpression}
24
+ }
25
+ func (unicornNoDocumentCookie) Check(ctx *Context, node *shimast.Node) {
26
+ access := node.AsPropertyAccessExpression()
27
+ if access == nil {
28
+ return
29
+ }
30
+ if identifierText(access.Expression) != "document" {
31
+ return
32
+ }
33
+ if identifierText(access.Name()) != "cookie" {
34
+ return
35
+ }
36
+ ctx.Report(node, "Don't use `document.cookie` directly; use the Cookie Store API or a wrapper.")
37
+ }
38
+
39
+ func init() {
40
+ Register(unicornNoDocumentCookie{})
41
+ }
@@ -0,0 +1,44 @@
1
+ // unicorn/no-empty-file: a source file with no executable contribution
2
+ // — every statement is a bare `;` empty-statement (or there are no
3
+ // statements at all) — usually exists by accident: a placeholder kept
4
+ // around past its purpose, a generator output for a missing input, or
5
+ // a copy of a file whose body was deleted. The rule flags these so the
6
+ // file is either filled with content or removed.
7
+ //
8
+ // SourceFile dispatch: the engine fires `KindSourceFile` visits once
9
+ // per file at the file root (see engine.runFile). For visibility into
10
+ // where the diagnostic lands when reporters render `path:line:col`, the
11
+ // rule reports on the first statement node when one exists (so the
12
+ // pointer matches the file's source line); when the file truly has no
13
+ // statements at all it falls back to `ReportRange(0, 0, …)` so the
14
+ // diagnostic still surfaces.
15
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-empty-file.md
16
+ package linthost
17
+
18
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
19
+
20
+ type unicornNoEmptyFile struct{}
21
+
22
+ func (unicornNoEmptyFile) Name() string { return "unicorn/no-empty-file" }
23
+ func (unicornNoEmptyFile) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindSourceFile} }
24
+ func (unicornNoEmptyFile) Check(ctx *Context, node *shimast.Node) {
25
+ if ctx.File == nil {
26
+ return
27
+ }
28
+ statements := ctx.File.Statements
29
+ const message = "Empty files are not allowed."
30
+ if statements == nil || len(statements.Nodes) == 0 {
31
+ ctx.ReportRange(0, 0, message)
32
+ return
33
+ }
34
+ for _, stmt := range statements.Nodes {
35
+ if stmt == nil || stmt.Kind != shimast.KindEmptyStatement {
36
+ return
37
+ }
38
+ }
39
+ ctx.Report(statements.Nodes[0], message)
40
+ }
41
+
42
+ func init() {
43
+ Register(unicornNoEmptyFile{})
44
+ }
@@ -0,0 +1,102 @@
1
+ // unicorn/no-for-loop: the classic `for (let i = 0; i < arr.length; i++)`
2
+ // pattern is an index-based array walk that has a direct `for…of`
3
+ // translation. The index variable, the length re-read, and the manual
4
+ // increment are all incidental bookkeeping the language now expresses
5
+ // with one keyword.
6
+ //
7
+ // AST-only and syntactic: dispatch on `ForStatement` and match the
8
+ // three classic shapes — `let i = 0` initializer, `i < X.length`
9
+ // condition (the RHS must be a `.length` access; bare counters
10
+ // `i < n` are not flagged because the suggested `for…of` rewrite does
11
+ // not apply), and `i++` incrementor. The length operand is not
12
+ // required to resolve to an array at the type level; the syntactic
13
+ // shape is the signal the rule wants to discourage.
14
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-for-loop.md
15
+ package linthost
16
+
17
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
18
+
19
+ type unicornNoForLoop struct{}
20
+
21
+ func (unicornNoForLoop) Name() string { return "unicorn/no-for-loop" }
22
+ func (unicornNoForLoop) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindForStatement} }
23
+ func (unicornNoForLoop) Check(ctx *Context, node *shimast.Node) {
24
+ stmt := node.AsForStatement()
25
+ if stmt == nil || stmt.Initializer == nil || stmt.Condition == nil || stmt.Incrementor == nil {
26
+ return
27
+ }
28
+ indexName := indexInitializerName(stmt.Initializer)
29
+ if indexName == "" {
30
+ return
31
+ }
32
+ if !isLessThanCondition(stmt.Condition, indexName) {
33
+ return
34
+ }
35
+ if !isPostfixIncrementOf(stmt.Incrementor, indexName) {
36
+ return
37
+ }
38
+ ctx.Report(node, "Use `for…of` over an index-based `for` loop over an array.")
39
+ }
40
+
41
+ // indexInitializerName returns the variable name of a `let i = 0`
42
+ // initializer, or "" when the initializer is anything else.
43
+ func indexInitializerName(init *shimast.Node) string {
44
+ if init == nil || init.Kind != shimast.KindVariableDeclarationList {
45
+ return ""
46
+ }
47
+ list := init.AsVariableDeclarationList()
48
+ if list == nil || list.Declarations == nil || len(list.Declarations.Nodes) != 1 {
49
+ return ""
50
+ }
51
+ decl := list.Declarations.Nodes[0].AsVariableDeclaration()
52
+ if decl == nil || decl.Initializer == nil {
53
+ return ""
54
+ }
55
+ if numericLiteralText(stripParens(decl.Initializer)) != "0" {
56
+ return ""
57
+ }
58
+ return identifierText(decl.Name())
59
+ }
60
+
61
+ // isLessThanCondition reports whether `cond` has the shape
62
+ // `<name> < <something>.length`. The right-hand operand must be a
63
+ // property access ending in `length`; bare counter loops such as
64
+ // `for (let i = 0; i < n; i++)` are NOT flagged because the rule's
65
+ // suggested rewrite (`for…of`) only applies to array iteration.
66
+ func isLessThanCondition(cond *shimast.Node, name string) bool {
67
+ node := stripParens(cond)
68
+ if node == nil || node.Kind != shimast.KindBinaryExpression {
69
+ return false
70
+ }
71
+ bin := node.AsBinaryExpression()
72
+ if bin == nil || bin.OperatorToken == nil ||
73
+ bin.OperatorToken.Kind != shimast.KindLessThanToken {
74
+ return false
75
+ }
76
+ if identifierText(stripParens(bin.Left)) != name {
77
+ return false
78
+ }
79
+ right := stripParens(bin.Right)
80
+ if right == nil || right.Kind != shimast.KindPropertyAccessExpression {
81
+ return false
82
+ }
83
+ access := right.AsPropertyAccessExpression()
84
+ return access != nil && identifierText(access.Name()) == "length"
85
+ }
86
+
87
+ // isPostfixIncrementOf reports whether `inc` has the shape `<name>++`.
88
+ func isPostfixIncrementOf(inc *shimast.Node, name string) bool {
89
+ node := stripParens(inc)
90
+ if node == nil || node.Kind != shimast.KindPostfixUnaryExpression {
91
+ return false
92
+ }
93
+ post := node.AsPostfixUnaryExpression()
94
+ if post == nil || post.Operator != shimast.KindPlusPlusToken {
95
+ return false
96
+ }
97
+ return identifierText(post.Operand) == name
98
+ }
99
+
100
+ func init() {
101
+ Register(unicornNoForLoop{})
102
+ }
@@ -0,0 +1,42 @@
1
+ // unicorn/no-hex-escape: `\xHH` escapes inside string and template
2
+ // literals are legal but they read worse than the equivalent
3
+ // `\u00HH` Unicode escape — there's only one way to write a Unicode
4
+ // escape, while a hex escape silently widens to a Unicode escape at
5
+ // runtime anyway. The rule nudges authors toward the Unicode form.
6
+ //
7
+ // AST-only: visit `KindStringLiteral` and `KindNoSubstitutionTemplateLiteral`,
8
+ // read the raw source text via `nodeText` (the parser already decodes
9
+ // escapes into the `.Text` value, so a normal accessor would see `©`
10
+ // instead of `\xA9`), and fire when the source contains a `\xHH`
11
+ // occurrence where HH is two hex digits.
12
+ //
13
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-hex-escape.md
14
+ package linthost
15
+
16
+ import (
17
+ "regexp"
18
+
19
+ shimast "github.com/microsoft/typescript-go/shim/ast"
20
+ )
21
+
22
+ var unicornNoHexEscapePattern = regexp.MustCompile(`\\x[0-9A-Fa-f]{2}`)
23
+
24
+ type unicornNoHexEscape struct{}
25
+
26
+ func (unicornNoHexEscape) Name() string { return "unicorn/no-hex-escape" }
27
+ func (unicornNoHexEscape) Visits() []shimast.Kind {
28
+ return []shimast.Kind{shimast.KindStringLiteral, shimast.KindNoSubstitutionTemplateLiteral}
29
+ }
30
+ func (unicornNoHexEscape) Check(ctx *Context, node *shimast.Node) {
31
+ source := nodeText(ctx.File, node)
32
+ if source == "" {
33
+ return
34
+ }
35
+ if unicornNoHexEscapePattern.MatchString(source) {
36
+ ctx.Report(node, "Prefer Unicode escapes (`\\uXXXX`) over hex escapes (`\\xHH`).")
37
+ }
38
+ }
39
+
40
+ func init() {
41
+ Register(unicornNoHexEscape{})
42
+ }
@@ -0,0 +1,90 @@
1
+ // unicorn/no-immediate-mutation: mutating an expression on the same
2
+ // statement that produces it — e.g. `[1, 2, 3].push(4)` or
3
+ // `arr.map(...).sort()` — discards the mutator's return value (which is
4
+ // either the new length or `void`) and obscures whether the author
5
+ // wanted the array, the count, or the side effect. The rule splits the
6
+ // two operations: construct first, then mutate (or use the non-mutating
7
+ // counterpart).
8
+ //
9
+ // AST-only: visit each `CallExpression`. Match when the callee is a
10
+ // `PropertyAccessExpression(receiver, name)` where `name` is one of the
11
+ // mutating array methods AND the receiver (after `stripParens`) is
12
+ // either an `ArrayLiteralExpression` or another call expression whose
13
+ // callee is a non-mutating array method that produces a fresh array.
14
+ // Fire on the outer call.
15
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-immediate-mutation.md
16
+ package linthost
17
+
18
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
19
+
20
+ var unicornNoImmediateMutationMethods = map[string]struct{}{
21
+ "push": {},
22
+ "pop": {},
23
+ "shift": {},
24
+ "unshift": {},
25
+ "splice": {},
26
+ "sort": {},
27
+ "reverse": {},
28
+ "copyWithin": {},
29
+ "fill": {},
30
+ }
31
+
32
+ var unicornNoImmediateMutationFreshMethods = map[string]struct{}{
33
+ "map": {},
34
+ "filter": {},
35
+ "slice": {},
36
+ "concat": {},
37
+ "flat": {},
38
+ "flatMap": {},
39
+ }
40
+
41
+ type unicornNoImmediateMutation struct{}
42
+
43
+ func (unicornNoImmediateMutation) Name() string { return "unicorn/no-immediate-mutation" }
44
+ func (unicornNoImmediateMutation) Visits() []shimast.Kind {
45
+ return []shimast.Kind{shimast.KindCallExpression}
46
+ }
47
+ func (unicornNoImmediateMutation) Check(ctx *Context, node *shimast.Node) {
48
+ call := node.AsCallExpression()
49
+ if call == nil || call.Expression == nil {
50
+ return
51
+ }
52
+ if call.Expression.Kind != shimast.KindPropertyAccessExpression {
53
+ return
54
+ }
55
+ access := call.Expression.AsPropertyAccessExpression()
56
+ if access == nil {
57
+ return
58
+ }
59
+ method := identifierText(access.Name())
60
+ if _, ok := unicornNoImmediateMutationMethods[method]; !ok {
61
+ return
62
+ }
63
+ receiver := stripParens(access.Expression)
64
+ if receiver == nil {
65
+ return
66
+ }
67
+ if receiver.Kind == shimast.KindArrayLiteralExpression {
68
+ ctx.Report(node, "Don't mutate a freshly built array — separate the construction and the mutation, or use a non-mutating method.")
69
+ return
70
+ }
71
+ if receiver.Kind == shimast.KindCallExpression {
72
+ inner := receiver.AsCallExpression()
73
+ if inner == nil || inner.Expression == nil ||
74
+ inner.Expression.Kind != shimast.KindPropertyAccessExpression {
75
+ return
76
+ }
77
+ innerAccess := inner.Expression.AsPropertyAccessExpression()
78
+ if innerAccess == nil {
79
+ return
80
+ }
81
+ innerName := identifierText(innerAccess.Name())
82
+ if _, ok := unicornNoImmediateMutationFreshMethods[innerName]; ok {
83
+ ctx.Report(node, "Don't mutate a freshly built array — separate the construction and the mutation, or use a non-mutating method.")
84
+ }
85
+ }
86
+ }
87
+
88
+ func init() {
89
+ Register(unicornNoImmediateMutation{})
90
+ }
@@ -0,0 +1,66 @@
1
+ // unicorn/no-instanceof-builtins: `x instanceof Array` (and the other
2
+ // built-in container constructors) is broken across realms and for
3
+ // user-defined subclasses. The cross-realm hazard is well known —
4
+ // `Array` in an iframe is a different constructor than the host
5
+ // `Array`, so a cross-realm value fails the check despite being an
6
+ // array; the subclass hazard is subtler — `instanceof` walks the
7
+ // prototype chain, so a `MyError extends Error` still passes
8
+ // `x instanceof Error` and obscures the actual type.
9
+ //
10
+ // AST-only: visit each `BinaryExpression` whose operator token is
11
+ // `instanceof`. The right-hand operand must be a bare identifier whose
12
+ // text appears in the built-in allowlist. Property-access or computed
13
+ // right-hand operands are out of scope because they cannot be matched
14
+ // syntactically against the global names.
15
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-instanceof-builtins.md
16
+ package linthost
17
+
18
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
19
+
20
+ var unicornNoInstanceofBuiltinsNames = map[string]struct{}{
21
+ "Array": {},
22
+ "Error": {},
23
+ "EvalError": {},
24
+ "RangeError": {},
25
+ "ReferenceError": {},
26
+ "SyntaxError": {},
27
+ "TypeError": {},
28
+ "URIError": {},
29
+ "AggregateError": {},
30
+ "Map": {},
31
+ "Set": {},
32
+ "WeakMap": {},
33
+ "WeakSet": {},
34
+ "Date": {},
35
+ "RegExp": {},
36
+ "Promise": {},
37
+ "Function": {},
38
+ }
39
+
40
+ type unicornNoInstanceofBuiltins struct{}
41
+
42
+ func (unicornNoInstanceofBuiltins) Name() string { return "unicorn/no-instanceof-builtins" }
43
+ func (unicornNoInstanceofBuiltins) Visits() []shimast.Kind {
44
+ return []shimast.Kind{shimast.KindBinaryExpression}
45
+ }
46
+ func (unicornNoInstanceofBuiltins) Check(ctx *Context, node *shimast.Node) {
47
+ bin := node.AsBinaryExpression()
48
+ if bin == nil || bin.OperatorToken == nil || bin.Right == nil {
49
+ return
50
+ }
51
+ if bin.OperatorToken.Kind != shimast.KindInstanceOfKeyword {
52
+ return
53
+ }
54
+ name := identifierText(bin.Right)
55
+ if name == "" {
56
+ return
57
+ }
58
+ if _, ok := unicornNoInstanceofBuiltinsNames[name]; !ok {
59
+ return
60
+ }
61
+ ctx.Report(node, "Don't use `instanceof <Builtin>` — it breaks across realms and for subclasses. Use a type predicate or duck-typing instead.")
62
+ }
63
+
64
+ func init() {
65
+ Register(unicornNoInstanceofBuiltins{})
66
+ }
@@ -0,0 +1,79 @@
1
+ // unicorn/no-invalid-fetch-options: passing a `body` together with a
2
+ // `GET` or `HEAD` `fetch()` call throws at runtime because the spec
3
+ // forbids a request body for those methods. The rule catches the
4
+ // mismatch at parse time so the throw never reaches production.
5
+ //
6
+ // AST-only: visit each `CallExpression`, match when the callee is a
7
+ // bare `fetch` identifier and the second argument is an object literal
8
+ // containing both a string-literal `method` of `GET` / `HEAD`
9
+ // (case-insensitive) AND a `body` property of any shape. Report on the
10
+ // call so the diagnostic lands at the offending site.
11
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-invalid-fetch-options.md
12
+ package linthost
13
+
14
+ import (
15
+ "strings"
16
+
17
+ shimast "github.com/microsoft/typescript-go/shim/ast"
18
+ )
19
+
20
+ type unicornNoInvalidFetchOptions struct{}
21
+
22
+ func (unicornNoInvalidFetchOptions) Name() string { return "unicorn/no-invalid-fetch-options" }
23
+ func (unicornNoInvalidFetchOptions) Visits() []shimast.Kind {
24
+ return []shimast.Kind{shimast.KindCallExpression}
25
+ }
26
+ func (unicornNoInvalidFetchOptions) Check(ctx *Context, node *shimast.Node) {
27
+ call := node.AsCallExpression()
28
+ if call == nil {
29
+ return
30
+ }
31
+ if identifierText(call.Expression) != "fetch" {
32
+ return
33
+ }
34
+ if call.Arguments == nil || len(call.Arguments.Nodes) < 2 {
35
+ return
36
+ }
37
+ init := stripParens(call.Arguments.Nodes[1])
38
+ if init == nil || init.Kind != shimast.KindObjectLiteralExpression {
39
+ return
40
+ }
41
+ obj := init.AsObjectLiteralExpression()
42
+ if obj == nil || obj.Properties == nil {
43
+ return
44
+ }
45
+ hasBody := false
46
+ methodIsBodyless := false
47
+ for _, prop := range obj.Properties.Nodes {
48
+ if prop == nil || prop.Kind != shimast.KindPropertyAssignment {
49
+ continue
50
+ }
51
+ assignment := prop.AsPropertyAssignment()
52
+ if assignment == nil || assignment.Name() == nil {
53
+ continue
54
+ }
55
+ key := identifierText(assignment.Name())
56
+ if key == "" && assignment.Name().Kind == shimast.KindStringLiteral {
57
+ key = stringLiteralText(assignment.Name())
58
+ }
59
+ switch key {
60
+ case "body":
61
+ hasBody = true
62
+ case "method":
63
+ value := stripParens(assignment.Initializer)
64
+ if value != nil && value.Kind == shimast.KindStringLiteral {
65
+ m := strings.ToLower(stringLiteralText(value))
66
+ if m == "get" || m == "head" {
67
+ methodIsBodyless = true
68
+ }
69
+ }
70
+ }
71
+ }
72
+ if hasBody && methodIsBodyless {
73
+ ctx.Report(node, "Don't pass `body` with GET/HEAD `fetch` — it throws at runtime.")
74
+ }
75
+ }
76
+
77
+ func init() {
78
+ Register(unicornNoInvalidFetchOptions{})
79
+ }