@ttsc/lint 0.13.0 → 0.14.0-dev.20250530.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 (498) hide show
  1. package/README.md +955 -85
  2. package/lib/defaultFormat.d.ts +15 -8
  3. package/lib/defaultFormat.js +15 -8
  4. package/lib/defaultFormat.js.map +1 -1
  5. package/lib/index.d.ts +46 -0
  6. package/lib/index.js +60 -37
  7. package/lib/index.js.map +1 -1
  8. package/lib/structures/ITtscLintConfig.d.ts +12 -6
  9. package/lib/structures/TtscLintRuleSetting.d.ts +49 -0
  10. package/lib/structures/{TtscLintRuleOptions.js → TtscLintRuleSetting.js} +1 -1
  11. package/lib/structures/TtscLintRuleSetting.js.map +1 -0
  12. package/lib/structures/format/ITtscLintFormat.d.ts +128 -0
  13. package/lib/structures/{TtscLintRuleMap.js → format/ITtscLintFormat.js} +1 -1
  14. package/lib/structures/format/ITtscLintFormat.js.map +1 -0
  15. package/lib/structures/format/ITtscLintFormatJsDoc.d.ts +17 -0
  16. package/lib/structures/{ITtscLintFormatConfig.js → format/ITtscLintFormatJsDoc.js} +1 -1
  17. package/lib/structures/format/ITtscLintFormatJsDoc.js.map +1 -0
  18. package/lib/structures/format/ITtscLintFormatSortImports.d.ts +54 -0
  19. package/lib/structures/format/ITtscLintFormatSortImports.js +3 -0
  20. package/lib/structures/format/ITtscLintFormatSortImports.js.map +1 -0
  21. package/lib/structures/format/index.d.ts +3 -0
  22. package/lib/structures/format/index.js +20 -0
  23. package/lib/structures/format/index.js.map +1 -0
  24. package/lib/structures/index.d.ts +3 -4
  25. package/lib/structures/index.js +3 -4
  26. package/lib/structures/index.js.map +1 -1
  27. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +95 -0
  28. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +13 -0
  29. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
  30. package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +75 -0
  31. package/lib/structures/rules/ITtscLintBoundariesRules.js +3 -0
  32. package/lib/structures/rules/ITtscLintBoundariesRules.js.map +1 -0
  33. package/lib/structures/rules/ITtscLintContributorRules.d.ts +16 -0
  34. package/lib/structures/rules/ITtscLintContributorRules.js +3 -0
  35. package/lib/structures/rules/ITtscLintContributorRules.js.map +1 -0
  36. package/lib/structures/rules/ITtscLintCoreRules.d.ts +1229 -0
  37. package/lib/structures/rules/ITtscLintCoreRules.js +3 -0
  38. package/lib/structures/rules/ITtscLintCoreRules.js.map +1 -0
  39. package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +17 -0
  40. package/lib/structures/rules/ITtscLintCypressRuleOptions.js +10 -0
  41. package/lib/structures/rules/ITtscLintCypressRuleOptions.js.map +1 -0
  42. package/lib/structures/rules/ITtscLintCypressRules.d.ts +125 -0
  43. package/lib/structures/rules/ITtscLintCypressRules.js +3 -0
  44. package/lib/structures/rules/ITtscLintCypressRules.js.map +1 -0
  45. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +154 -0
  46. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +13 -0
  47. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js.map +1 -0
  48. package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +162 -0
  49. package/lib/structures/rules/ITtscLintFunctionalRules.js +3 -0
  50. package/lib/structures/rules/ITtscLintFunctionalRules.js.map +1 -0
  51. package/lib/structures/rules/ITtscLintJestRules.d.ts +190 -0
  52. package/lib/structures/rules/ITtscLintJestRules.js +3 -0
  53. package/lib/structures/rules/ITtscLintJestRules.js.map +1 -0
  54. package/lib/structures/rules/ITtscLintJsdocRules.d.ts +133 -0
  55. package/lib/structures/rules/ITtscLintJsdocRules.js +3 -0
  56. package/lib/structures/rules/ITtscLintJsdocRules.js.map +1 -0
  57. package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +294 -0
  58. package/lib/structures/rules/ITtscLintJsxA11yRules.js +3 -0
  59. package/lib/structures/rules/ITtscLintJsxA11yRules.js.map +1 -0
  60. package/lib/structures/rules/ITtscLintNextjsRules.d.ts +180 -0
  61. package/lib/structures/rules/ITtscLintNextjsRules.js +3 -0
  62. package/lib/structures/rules/ITtscLintNextjsRules.js.map +1 -0
  63. package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +312 -0
  64. package/lib/structures/rules/ITtscLintPlaywrightRules.js +3 -0
  65. package/lib/structures/rules/ITtscLintPlaywrightRules.js.map +1 -0
  66. package/lib/structures/rules/ITtscLintPromiseRules.d.ts +179 -0
  67. package/lib/structures/rules/ITtscLintPromiseRules.js +3 -0
  68. package/lib/structures/rules/ITtscLintPromiseRules.js.map +1 -0
  69. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +18 -0
  70. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js +8 -0
  71. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js.map +1 -0
  72. package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +49 -0
  73. package/lib/structures/rules/ITtscLintReactPerfRules.js +3 -0
  74. package/lib/structures/rules/ITtscLintReactPerfRules.js.map +1 -0
  75. package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +37 -0
  76. package/lib/structures/rules/ITtscLintReactRuleOptions.js +11 -0
  77. package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
  78. package/lib/structures/rules/ITtscLintReactRules.d.ts +276 -0
  79. package/lib/structures/rules/ITtscLintReactRules.js +3 -0
  80. package/lib/structures/rules/ITtscLintReactRules.js.map +1 -0
  81. package/lib/structures/rules/ITtscLintRegexpRules.d.ts +182 -0
  82. package/lib/structures/rules/ITtscLintRegexpRules.js +3 -0
  83. package/lib/structures/rules/ITtscLintRegexpRules.js.map +1 -0
  84. package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +65 -0
  85. package/lib/structures/rules/ITtscLintRuleOptionsMap.js +3 -0
  86. package/lib/structures/rules/ITtscLintRuleOptionsMap.js.map +1 -0
  87. package/lib/structures/rules/ITtscLintRules.d.ts +55 -0
  88. package/lib/structures/{TtscLintRule.js → rules/ITtscLintRules.js} +1 -1
  89. package/lib/structures/rules/ITtscLintRules.js.map +1 -0
  90. package/lib/structures/rules/ITtscLintSecurityRules.d.ts +141 -0
  91. package/lib/structures/rules/ITtscLintSecurityRules.js +3 -0
  92. package/lib/structures/rules/ITtscLintSecurityRules.js.map +1 -0
  93. package/lib/structures/rules/ITtscLintSolidRules.d.ts +178 -0
  94. package/lib/structures/rules/ITtscLintSolidRules.js +3 -0
  95. package/lib/structures/rules/ITtscLintSolidRules.js.map +1 -0
  96. package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +20 -0
  97. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js +9 -0
  98. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js.map +1 -0
  99. package/lib/structures/rules/ITtscLintStorybookRules.d.ts +165 -0
  100. package/lib/structures/rules/ITtscLintStorybookRules.js +3 -0
  101. package/lib/structures/rules/ITtscLintStorybookRules.js.map +1 -0
  102. package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +88 -0
  103. package/lib/structures/rules/ITtscLintTanstackQueryRules.js +3 -0
  104. package/lib/structures/rules/ITtscLintTanstackQueryRules.js.map +1 -0
  105. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +21 -0
  106. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js +10 -0
  107. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js.map +1 -0
  108. package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +293 -0
  109. package/lib/structures/rules/ITtscLintTestingLibraryRules.js +3 -0
  110. package/lib/structures/rules/ITtscLintTestingLibraryRules.js.map +1 -0
  111. package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +1074 -0
  112. package/lib/structures/rules/ITtscLintTypeScriptRules.js +3 -0
  113. package/lib/structures/rules/ITtscLintTypeScriptRules.js.map +1 -0
  114. package/lib/structures/rules/ITtscLintUnicornRules.d.ts +997 -0
  115. package/lib/structures/rules/ITtscLintUnicornRules.js +3 -0
  116. package/lib/structures/rules/ITtscLintUnicornRules.js.map +1 -0
  117. package/lib/structures/rules/ITtscLintVitestRules.d.ts +133 -0
  118. package/lib/structures/rules/ITtscLintVitestRules.js +3 -0
  119. package/lib/structures/rules/ITtscLintVitestRules.js.map +1 -0
  120. package/lib/structures/rules/index.d.ts +31 -0
  121. package/lib/structures/rules/index.js +48 -0
  122. package/lib/structures/rules/index.js.map +1 -0
  123. package/linthost/ast_helpers.go +30 -5
  124. package/linthost/compile.go +33 -2
  125. package/linthost/config.go +118 -71
  126. package/linthost/config_format.go +270 -104
  127. package/linthost/directives.go +67 -25
  128. package/linthost/dispatch.go +14 -3
  129. package/linthost/engine.go +160 -40
  130. package/linthost/fix.go +10 -3
  131. package/linthost/flags_gen.go +17 -15
  132. package/linthost/format.go +222 -25
  133. package/linthost/format_editor_settings.go +262 -0
  134. package/linthost/host.go +40 -3
  135. package/linthost/lsp.go +898 -0
  136. package/linthost/print_dispatch.go +5 -2
  137. package/linthost/print_engine.go +5 -5
  138. package/linthost/print_nodes_call.go +149 -67
  139. package/linthost/print_nodes_function.go +27 -2
  140. package/linthost/print_nodes_list.go +40 -5
  141. package/linthost/print_nodes_object.go +1 -1
  142. package/linthost/print_nodes_ternary.go +86 -0
  143. package/linthost/rule_names.go +14 -0
  144. package/linthost/rules_arrays.go +2 -2
  145. package/linthost/rules_boundaries.go +532 -0
  146. package/linthost/rules_camelcase.go +133 -0
  147. package/linthost/rules_complexity.go +95 -0
  148. package/linthost/rules_consistent_return.go +130 -0
  149. package/linthost/rules_console.go +1 -1
  150. package/linthost/rules_core_extra.go +739 -0
  151. package/linthost/rules_curly.go +70 -0
  152. package/linthost/rules_cypress.go +608 -0
  153. package/linthost/rules_debugger.go +2 -2
  154. package/linthost/rules_default_case.go +39 -0
  155. package/linthost/rules_default_case_last.go +46 -0
  156. package/linthost/rules_dupes.go +3 -3
  157. package/linthost/rules_empty.go +3 -3
  158. package/linthost/rules_escape.go +44 -24
  159. package/linthost/rules_eval.go +2 -2
  160. package/linthost/rules_finally.go +2 -2
  161. package/linthost/rules_format_arrow_parens.go +167 -0
  162. package/linthost/rules_format_bracket_spacing.go +117 -0
  163. package/linthost/rules_format_clause_join.go +172 -0
  164. package/linthost/rules_format_declaration_header.go +595 -0
  165. package/linthost/rules_format_indent.go +372 -0
  166. package/linthost/rules_format_jsdoc.go +5 -5
  167. package/linthost/rules_format_orphan_semi.go +106 -0
  168. package/linthost/rules_format_parameter_properties.go +175 -0
  169. package/linthost/rules_format_print_width.go +66 -55
  170. package/linthost/rules_format_quote_props.go +169 -0
  171. package/linthost/rules_format_quotes.go +76 -30
  172. package/linthost/rules_format_semi.go +186 -11
  173. package/linthost/rules_format_sort_imports.go +437 -118
  174. package/linthost/rules_format_statement_split.go +343 -0
  175. package/linthost/rules_format_ternary_nullish_parens.go +77 -0
  176. package/linthost/rules_format_trailing_comma.go +22 -3
  177. package/linthost/rules_format_whitespace.go +336 -0
  178. package/linthost/rules_functional.go +967 -0
  179. package/linthost/rules_gap.go +24 -45
  180. package/linthost/rules_grouped_accessor_pairs.go +87 -0
  181. package/linthost/rules_guard_for_in.go +198 -0
  182. package/linthost/rules_id_length.go +77 -0
  183. package/linthost/rules_imports.go +70 -2
  184. package/linthost/rules_init_declarations.go +53 -0
  185. package/linthost/rules_jest.go +618 -0
  186. package/linthost/rules_jsdoc.go +502 -0
  187. package/linthost/rules_jsx_a11y.go +1264 -0
  188. package/linthost/rules_logic.go +12 -12
  189. package/linthost/rules_loops.go +1 -1
  190. package/linthost/rules_max_classes_per_file.go +58 -0
  191. package/linthost/rules_max_depth.go +83 -0
  192. package/linthost/rules_max_lines.go +101 -0
  193. package/linthost/rules_max_lines_per_function.go +57 -0
  194. package/linthost/rules_max_nested_callbacks.go +61 -0
  195. package/linthost/rules_max_params.go +49 -0
  196. package/linthost/rules_max_statements.go +59 -0
  197. package/linthost/rules_misc.go +1 -1
  198. package/linthost/rules_nextjs.go +697 -0
  199. package/linthost/rules_no_else_return.go +75 -0
  200. package/linthost/rules_no_empty_named_blocks.go +91 -0
  201. package/linthost/rules_no_extend_native.go +51 -0
  202. package/linthost/rules_no_import_assign.go +140 -0
  203. package/linthost/rules_no_invalid_this.go +52 -0
  204. package/linthost/rules_no_loop_func.go +85 -0
  205. package/linthost/rules_no_magic_numbers.go +123 -0
  206. package/linthost/rules_no_mixed_operators.go +80 -0
  207. package/linthost/rules_no_param_reassign.go +98 -0
  208. package/linthost/rules_no_redeclare.go +270 -0
  209. package/linthost/rules_no_restricted_imports.go +105 -0
  210. package/linthost/rules_no_restricted_syntax.go +49 -0
  211. package/linthost/rules_no_shadow.go +147 -0
  212. package/linthost/rules_no_unreachable.go +77 -0
  213. package/linthost/rules_no_useless_assignment.go +120 -0
  214. package/linthost/rules_no_useless_constructor.go +245 -0
  215. package/linthost/rules_no_useless_return.go +51 -0
  216. package/linthost/rules_params.go +1 -1
  217. package/linthost/rules_playwright.go +788 -0
  218. package/linthost/rules_prefer_arrow_callback.go +124 -0
  219. package/linthost/rules_prefer_destructuring.go +98 -0
  220. package/linthost/rules_prefer_named_capture_group.go +129 -0
  221. package/linthost/rules_prefer_rest_params.go +94 -0
  222. package/linthost/rules_problems.go +41 -30
  223. package/linthost/rules_promise.go +1057 -2
  224. package/linthost/rules_protos.go +2 -2
  225. package/linthost/rules_react.go +773 -0
  226. package/linthost/rules_react_extras.go +227 -0
  227. package/linthost/rules_react_hooks.go +848 -0
  228. package/linthost/rules_react_perf.go +293 -0
  229. package/linthost/rules_react_refresh.go +583 -0
  230. package/linthost/rules_regexp.go +410 -0
  231. package/linthost/rules_security.go +830 -0
  232. package/linthost/rules_self.go +2 -2
  233. package/linthost/rules_solid.go +1073 -0
  234. package/linthost/rules_sort_imports.go +69 -0
  235. package/linthost/rules_sort_keys.go +134 -0
  236. package/linthost/rules_storybook.go +1176 -0
  237. package/linthost/rules_strings.go +4 -4
  238. package/linthost/rules_suggestions.go +38 -38
  239. package/linthost/rules_tanstack_query.go +844 -0
  240. package/linthost/rules_testing_library.go +1204 -0
  241. package/linthost/rules_throw.go +1 -1
  242. package/linthost/rules_ts.go +19 -19
  243. package/linthost/rules_ts_async.go +399 -0
  244. package/linthost/rules_ts_class_literal_property_style.go +115 -0
  245. package/linthost/rules_ts_consistent_type_exports.go +256 -0
  246. package/linthost/rules_ts_explicit_function_return_type.go +67 -0
  247. package/linthost/rules_ts_extra.go +159 -36
  248. package/linthost/rules_ts_no_base_to_string.go +218 -0
  249. package/linthost/rules_ts_no_confusing_void.go +72 -0
  250. package/linthost/rules_ts_no_deprecated.go +195 -0
  251. package/linthost/rules_ts_no_for_in_array.go +84 -0
  252. package/linthost/rules_ts_no_magic_numbers.go +124 -0
  253. package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
  254. package/linthost/rules_ts_no_misused_spread.go +104 -0
  255. package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
  256. package/linthost/rules_ts_no_restricted_types.go +62 -0
  257. package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
  258. package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
  259. package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
  260. package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
  261. package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
  262. package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
  263. package/linthost/rules_ts_no_unsafe_argument.go +82 -0
  264. package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
  265. package/linthost/rules_ts_no_unsafe_call.go +82 -0
  266. package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
  267. package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
  268. package/linthost/rules_ts_no_unsafe_return.go +126 -0
  269. package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
  270. package/linthost/rules_ts_no_useless_constructor.go +52 -0
  271. package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
  272. package/linthost/rules_ts_parameter_properties.go +38 -0
  273. package/linthost/rules_ts_prefer_find.go +178 -0
  274. package/linthost/rules_ts_prefer_includes.go +255 -0
  275. package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
  276. package/linthost/rules_ts_prefer_optional_chain.go +228 -0
  277. package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
  278. package/linthost/rules_ts_prefer_readonly.go +73 -0
  279. package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
  280. package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
  281. package/linthost/rules_ts_prefer_return_this_type.go +135 -0
  282. package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
  283. package/linthost/rules_ts_promise_function_async.go +77 -0
  284. package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
  285. package/linthost/rules_ts_require_array_sort_compare.go +96 -0
  286. package/linthost/rules_ts_restrict_plus_operands.go +127 -0
  287. package/linthost/rules_ts_restrict_template_expressions.go +95 -0
  288. package/linthost/rules_ts_simple.go +387 -0
  289. package/linthost/rules_ts_sort_type_constituents.go +144 -0
  290. package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
  291. package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
  292. package/linthost/rules_ts_unbound_method.go +126 -0
  293. package/linthost/rules_tsdoc.go +136 -0
  294. package/linthost/rules_unicorn_better_regex.go +27 -0
  295. package/linthost/rules_unicorn_catch_error_name.go +46 -0
  296. package/linthost/rules_unicorn_consistent_assert.go +47 -0
  297. package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
  298. package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
  299. package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
  300. package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
  301. package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
  302. package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
  303. package/linthost/rules_unicorn_custom_error_definition.go +138 -0
  304. package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
  305. package/linthost/rules_unicorn_error_message.go +64 -0
  306. package/linthost/rules_unicorn_escape_case.go +51 -0
  307. package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
  308. package/linthost/rules_unicorn_explicit_length_check.go +88 -0
  309. package/linthost/rules_unicorn_filename_case.go +29 -0
  310. package/linthost/rules_unicorn_import_style.go +28 -0
  311. package/linthost/rules_unicorn_isolated_functions.go +29 -0
  312. package/linthost/rules_unicorn_new_for_builtins.go +87 -0
  313. package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
  314. package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
  315. package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
  316. package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
  317. package/linthost/rules_unicorn_no_array_for_each.go +40 -0
  318. package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
  319. package/linthost/rules_unicorn_no_array_reduce.go +41 -0
  320. package/linthost/rules_unicorn_no_array_reverse.go +44 -0
  321. package/linthost/rules_unicorn_no_array_sort.go +43 -0
  322. package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
  323. package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
  324. package/linthost/rules_unicorn_no_console_spaces.go +61 -0
  325. package/linthost/rules_unicorn_no_document_cookie.go +41 -0
  326. package/linthost/rules_unicorn_no_empty_file.go +44 -0
  327. package/linthost/rules_unicorn_no_for_loop.go +102 -0
  328. package/linthost/rules_unicorn_no_hex_escape.go +42 -0
  329. package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
  330. package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
  331. package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
  332. package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
  333. package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
  334. package/linthost/rules_unicorn_no_lonely_if.go +44 -0
  335. package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
  336. package/linthost/rules_unicorn_no_named_default.go +54 -0
  337. package/linthost/rules_unicorn_no_negated_condition.go +85 -0
  338. package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
  339. package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
  340. package/linthost/rules_unicorn_no_new_array.go +30 -0
  341. package/linthost/rules_unicorn_no_new_buffer.go +31 -0
  342. package/linthost/rules_unicorn_no_null.go +24 -0
  343. package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
  344. package/linthost/rules_unicorn_no_process_exit.go +43 -0
  345. package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
  346. package/linthost/rules_unicorn_no_static_only_class.go +56 -0
  347. package/linthost/rules_unicorn_no_thenable.go +74 -0
  348. package/linthost/rules_unicorn_no_this_assignment.go +35 -0
  349. package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
  350. package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
  351. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
  352. package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
  353. package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
  354. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
  355. package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
  356. package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
  357. package/linthost/rules_unicorn_no_unused_properties.go +30 -0
  358. package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
  359. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
  360. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
  361. package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
  362. package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
  363. package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
  364. package/linthost/rules_unicorn_no_useless_spread.go +67 -0
  365. package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
  366. package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
  367. package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
  368. package/linthost/rules_unicorn_number_literal_case.go +69 -0
  369. package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
  370. package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
  371. package/linthost/rules_unicorn_prefer_array_find.go +51 -0
  372. package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
  373. package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
  374. package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
  375. package/linthost/rules_unicorn_prefer_array_some.go +67 -0
  376. package/linthost/rules_unicorn_prefer_at.go +77 -0
  377. package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
  378. package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
  379. package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
  380. package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
  381. package/linthost/rules_unicorn_prefer_code_point.go +49 -0
  382. package/linthost/rules_unicorn_prefer_date_now.go +78 -0
  383. package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
  384. package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
  385. package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
  386. package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
  387. package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
  388. package/linthost/rules_unicorn_prefer_event_target.go +36 -0
  389. package/linthost/rules_unicorn_prefer_export_from.go +129 -0
  390. package/linthost/rules_unicorn_prefer_global_this.go +127 -0
  391. package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
  392. package/linthost/rules_unicorn_prefer_includes.go +149 -0
  393. package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
  394. package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
  395. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
  396. package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
  397. package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
  398. package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
  399. package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
  400. package/linthost/rules_unicorn_prefer_module.go +50 -0
  401. package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
  402. package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
  403. package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
  404. package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
  405. package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
  406. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
  407. package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
  408. package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
  409. package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
  410. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
  411. package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
  412. package/linthost/rules_unicorn_prefer_set_has.go +42 -0
  413. package/linthost/rules_unicorn_prefer_set_size.go +48 -0
  414. package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
  415. package/linthost/rules_unicorn_prefer_single_call.go +96 -0
  416. package/linthost/rules_unicorn_prefer_spread.go +51 -0
  417. package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
  418. package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
  419. package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
  420. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
  421. package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
  422. package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
  423. package/linthost/rules_unicorn_prefer_switch.go +103 -0
  424. package/linthost/rules_unicorn_prefer_ternary.go +71 -0
  425. package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
  426. package/linthost/rules_unicorn_prefer_type_error.go +127 -0
  427. package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
  428. package/linthost/rules_unicorn_relative_url_style.go +49 -0
  429. package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
  430. package/linthost/rules_unicorn_require_module_attributes.go +54 -0
  431. package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
  432. package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
  433. package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
  434. package/linthost/rules_unicorn_string_content.go +27 -0
  435. package/linthost/rules_unicorn_switch_case_braces.go +42 -0
  436. package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
  437. package/linthost/rules_unicorn_template_indent.go +28 -0
  438. package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
  439. package/linthost/rules_unicorn_throw_new_error.go +61 -0
  440. package/linthost/rules_var.go +10 -4
  441. package/linthost/rules_vitest.go +568 -0
  442. package/package.json +3 -3
  443. package/plugin/main.go +49 -3
  444. package/rule/astutil/astutil.go +10 -3
  445. package/rule/rule.go +12 -10
  446. package/src/defaultFormat.ts +17 -10
  447. package/src/index.ts +65 -43
  448. package/src/structures/ITtscLintConfig.ts +14 -8
  449. package/src/structures/TtscLintRuleSetting.ts +55 -0
  450. package/src/structures/format/ITtscLintFormat.ts +141 -0
  451. package/src/structures/format/ITtscLintFormatJsDoc.ts +18 -0
  452. package/src/structures/format/ITtscLintFormatSortImports.ts +62 -0
  453. package/src/structures/format/index.ts +3 -0
  454. package/src/structures/index.ts +3 -4
  455. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +117 -0
  456. package/src/structures/rules/ITtscLintBoundariesRules.ts +91 -0
  457. package/src/structures/rules/ITtscLintContributorRules.ts +20 -0
  458. package/src/structures/rules/ITtscLintCoreRules.ts +1378 -0
  459. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
  460. package/src/structures/rules/ITtscLintCypressRules.ts +141 -0
  461. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +200 -0
  462. package/src/structures/rules/ITtscLintFunctionalRules.ts +197 -0
  463. package/src/structures/rules/ITtscLintJestRules.ts +209 -0
  464. package/src/structures/rules/ITtscLintJsdocRules.ts +146 -0
  465. package/src/structures/rules/ITtscLintJsxA11yRules.ts +331 -0
  466. package/src/structures/rules/ITtscLintNextjsRules.ts +201 -0
  467. package/src/structures/rules/ITtscLintPlaywrightRules.ts +343 -0
  468. package/src/structures/rules/ITtscLintPromiseRules.ts +196 -0
  469. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
  470. package/src/structures/rules/ITtscLintReactPerfRules.ts +53 -0
  471. package/src/structures/rules/ITtscLintReactRuleOptions.ts +41 -0
  472. package/src/structures/rules/ITtscLintReactRules.ts +308 -0
  473. package/src/structures/rules/ITtscLintRegexpRules.ts +204 -0
  474. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +88 -0
  475. package/src/structures/rules/ITtscLintRules.ts +77 -0
  476. package/src/structures/rules/ITtscLintSecurityRules.ts +155 -0
  477. package/src/structures/rules/ITtscLintSolidRules.ts +199 -0
  478. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +22 -0
  479. package/src/structures/rules/ITtscLintStorybookRules.ts +184 -0
  480. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +96 -0
  481. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +23 -0
  482. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +325 -0
  483. package/src/structures/rules/ITtscLintTypeScriptRules.ts +1172 -0
  484. package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
  485. package/src/structures/rules/ITtscLintVitestRules.ts +146 -0
  486. package/src/structures/rules/index.ts +31 -0
  487. package/lib/structures/ITtscLintFormatConfig.d.ts +0 -153
  488. package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
  489. package/lib/structures/TtscLintRule.d.ts +0 -17
  490. package/lib/structures/TtscLintRule.js.map +0 -1
  491. package/lib/structures/TtscLintRuleMap.d.ts +0 -46
  492. package/lib/structures/TtscLintRuleMap.js.map +0 -1
  493. package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
  494. package/lib/structures/TtscLintRuleOptions.js.map +0 -1
  495. package/src/structures/ITtscLintFormatConfig.ts +0 -168
  496. package/src/structures/TtscLintRule.ts +0 -160
  497. package/src/structures/TtscLintRuleMap.ts +0 -55
  498. package/src/structures/TtscLintRuleOptions.ts +0 -151
@@ -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
+ }
@@ -0,0 +1,51 @@
1
+ // unicorn/no-invalid-remove-event-listener: passing a fresh function
2
+ // literal to `removeEventListener` is a no-op because event-target
3
+ // internals match listeners by reference identity. The handler that was
4
+ // originally registered still fires; the call silently does nothing.
5
+ //
6
+ // AST-only: visit each `CallExpression`, match when the callee is a
7
+ // `PropertyAccessExpression(_, removeEventListener)` and the second
8
+ // argument (after stripping parens) is a fresh arrow function or
9
+ // function expression. Fire on the call so the diagnostic lands at the
10
+ // no-op site.
11
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-invalid-remove-event-listener.md
12
+ package linthost
13
+
14
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
15
+
16
+ type unicornNoInvalidRemoveEventListener struct{}
17
+
18
+ func (unicornNoInvalidRemoveEventListener) Name() string {
19
+ return "unicorn/no-invalid-remove-event-listener"
20
+ }
21
+ func (unicornNoInvalidRemoveEventListener) Visits() []shimast.Kind {
22
+ return []shimast.Kind{shimast.KindCallExpression}
23
+ }
24
+ func (unicornNoInvalidRemoveEventListener) 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 || identifierText(access.Name()) != "removeEventListener" {
34
+ return
35
+ }
36
+ if call.Arguments == nil || len(call.Arguments.Nodes) < 2 {
37
+ return
38
+ }
39
+ handler := stripParens(call.Arguments.Nodes[1])
40
+ if handler == nil {
41
+ return
42
+ }
43
+ switch handler.Kind {
44
+ case shimast.KindArrowFunction, shimast.KindFunctionExpression:
45
+ ctx.Report(node, "Calling `removeEventListener` with a fresh function reference removes nothing — store and reuse the handler.")
46
+ }
47
+ }
48
+
49
+ func init() {
50
+ Register(unicornNoInvalidRemoveEventListener{})
51
+ }
@@ -0,0 +1,101 @@
1
+ // unicorn/no-keyword-prefix: identifiers like `newFoo` or `classBar`
2
+ // embed a reserved word at the prefix position so the reader has to
3
+ // re-parse the identifier each time. The rule discourages the prefix in
4
+ // declarations so the codebase converges on names whose first segment
5
+ // is not a JavaScript keyword.
6
+ //
7
+ // AST-only: visit every `Identifier` and fire only on declaration
8
+ // positions (parameter, variable, function, class, method, accessor,
9
+ // property, binding-element names). Reads of an already-named binding
10
+ // are NOT flagged — the diagnostic is anchored on the declaration so
11
+ // the rename happens once. Uses the same value-position-gate logic as
12
+ // `prefer-global-this`, inverted: this rule needs the identifier to be
13
+ // in a *name* slot, not a value-expression slot.
14
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-keyword-prefix.md
15
+ package linthost
16
+
17
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
18
+
19
+ type unicornNoKeywordPrefix struct{}
20
+
21
+ func (unicornNoKeywordPrefix) Name() string { return "unicorn/no-keyword-prefix" }
22
+ func (unicornNoKeywordPrefix) Visits() []shimast.Kind {
23
+ return []shimast.Kind{shimast.KindIdentifier}
24
+ }
25
+ func (unicornNoKeywordPrefix) Check(ctx *Context, node *shimast.Node) {
26
+ name := identifierText(node)
27
+ if !hasKeywordPrefix(name) {
28
+ return
29
+ }
30
+ if !isUnicornDeclarationPositionIdentifier(node) {
31
+ return
32
+ }
33
+ ctx.Report(node, "Don't prefix identifiers with a reserved word (`new` / `class`).")
34
+ }
35
+
36
+ // hasKeywordPrefix reports whether `name` starts with `new` or `class`
37
+ // followed by an uppercase ASCII letter. The case-sensitive prefix +
38
+ // the uppercase next letter together pin the camelCase pattern the rule
39
+ // targets (`newFoo`, `classBar`); plain words like `news` or `classic`
40
+ // share the prefix bytes but not the camelCase break and are out of
41
+ // scope.
42
+ func hasKeywordPrefix(name string) bool {
43
+ for _, prefix := range []string{"new", "class"} {
44
+ if len(name) <= len(prefix) {
45
+ continue
46
+ }
47
+ if name[:len(prefix)] != prefix {
48
+ continue
49
+ }
50
+ next := name[len(prefix)]
51
+ if next >= 'A' && next <= 'Z' {
52
+ return true
53
+ }
54
+ }
55
+ return false
56
+ }
57
+
58
+ // isUnicornDeclarationPositionIdentifier reports whether `node` (a bare
59
+ // Identifier) appears as a *name* slot of a declaration, i.e. the slot
60
+ // reserved by the language for introducing a new binding. Reads,
61
+ // property keys on accesses, type references, and labels are filtered
62
+ // out so the rule only fires on declarations.
63
+ func isUnicornDeclarationPositionIdentifier(node *shimast.Node) bool {
64
+ if node == nil || node.Kind != shimast.KindIdentifier || node.Parent == nil {
65
+ return false
66
+ }
67
+ parent := node.Parent
68
+ switch parent.Kind {
69
+ case shimast.KindVariableDeclaration:
70
+ decl := parent.AsVariableDeclaration()
71
+ return decl != nil && decl.Name() == node
72
+ case shimast.KindBindingElement:
73
+ elem := parent.AsBindingElement()
74
+ return elem != nil && elem.Name() == node
75
+ case shimast.KindParameter:
76
+ param := parent.AsParameterDeclaration()
77
+ return param != nil && param.Name() == node
78
+ case shimast.KindFunctionDeclaration:
79
+ fn := parent.AsFunctionDeclaration()
80
+ return fn != nil && fn.Name() == node
81
+ case shimast.KindFunctionExpression:
82
+ fn := parent.AsFunctionExpression()
83
+ return fn != nil && fn.Name() == node
84
+ case shimast.KindClassDeclaration:
85
+ cls := parent.AsClassDeclaration()
86
+ return cls != nil && cls.Name() == node
87
+ case shimast.KindClassExpression:
88
+ cls := parent.AsClassExpression()
89
+ return cls != nil && cls.Name() == node
90
+ case shimast.KindMethodDeclaration,
91
+ shimast.KindGetAccessor,
92
+ shimast.KindSetAccessor,
93
+ shimast.KindPropertyDeclaration:
94
+ return true
95
+ }
96
+ return false
97
+ }
98
+
99
+ func init() {
100
+ Register(unicornNoKeywordPrefix{})
101
+ }
@@ -0,0 +1,44 @@
1
+ // unicorn/no-lonely-if: `else { if (cond) { … } }` collapses to
2
+ // `else if (cond) { … }`. Wrapping a single `if` in an `else` block
3
+ // adds an extra brace pair and an extra indentation level without
4
+ // changing semantics, so the rule flags it as redundant punctuation.
5
+ //
6
+ // AST-only and parent-walking: visit every `IfStatement`, then check
7
+ // whether its parent is a `Block` containing exactly this one
8
+ // statement AND that block is the `ElseStatement` of an outer
9
+ // `IfStatement`. Mirrors the core `no-lonely-if` rule shape.
10
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-lonely-if.md
11
+ package linthost
12
+
13
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
14
+
15
+ type unicornNoLonelyIf struct{}
16
+
17
+ func (unicornNoLonelyIf) Name() string { return "unicorn/no-lonely-if" }
18
+ func (unicornNoLonelyIf) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindIfStatement} }
19
+ func (unicornNoLonelyIf) Check(ctx *Context, node *shimast.Node) {
20
+ parent := node.Parent
21
+ if parent == nil || parent.Kind != shimast.KindBlock {
22
+ return
23
+ }
24
+ block := parent.AsBlock()
25
+ if block == nil || block.Statements == nil {
26
+ return
27
+ }
28
+ if len(block.Statements.Nodes) != 1 {
29
+ return
30
+ }
31
+ grand := parent.Parent
32
+ if grand == nil || grand.Kind != shimast.KindIfStatement {
33
+ return
34
+ }
35
+ gif := grand.AsIfStatement()
36
+ if gif == nil || gif.ElseStatement != parent {
37
+ return
38
+ }
39
+ ctx.Report(node, "Use `else if` instead of an `if` as the only statement inside an `else` block.")
40
+ }
41
+
42
+ func init() {
43
+ Register(unicornNoLonelyIf{})
44
+ }