@ttsc/lint 0.13.1 → 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 (495) 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 +35 -10
  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/config.go +118 -71
  125. package/linthost/config_format.go +270 -104
  126. package/linthost/directives.go +67 -25
  127. package/linthost/dispatch.go +14 -3
  128. package/linthost/engine.go +152 -31
  129. package/linthost/fix.go +10 -3
  130. package/linthost/format.go +222 -25
  131. package/linthost/format_editor_settings.go +262 -0
  132. package/linthost/lsp.go +898 -0
  133. package/linthost/print_dispatch.go +5 -2
  134. package/linthost/print_engine.go +5 -5
  135. package/linthost/print_nodes_call.go +149 -67
  136. package/linthost/print_nodes_function.go +27 -2
  137. package/linthost/print_nodes_list.go +40 -5
  138. package/linthost/print_nodes_object.go +1 -1
  139. package/linthost/print_nodes_ternary.go +86 -0
  140. package/linthost/rule_names.go +14 -0
  141. package/linthost/rules_arrays.go +2 -2
  142. package/linthost/rules_boundaries.go +532 -0
  143. package/linthost/rules_camelcase.go +133 -0
  144. package/linthost/rules_complexity.go +95 -0
  145. package/linthost/rules_consistent_return.go +130 -0
  146. package/linthost/rules_console.go +1 -1
  147. package/linthost/rules_core_extra.go +739 -0
  148. package/linthost/rules_curly.go +70 -0
  149. package/linthost/rules_cypress.go +608 -0
  150. package/linthost/rules_debugger.go +2 -2
  151. package/linthost/rules_default_case.go +39 -0
  152. package/linthost/rules_default_case_last.go +46 -0
  153. package/linthost/rules_dupes.go +3 -3
  154. package/linthost/rules_empty.go +3 -3
  155. package/linthost/rules_escape.go +44 -24
  156. package/linthost/rules_eval.go +2 -2
  157. package/linthost/rules_finally.go +2 -2
  158. package/linthost/rules_format_arrow_parens.go +167 -0
  159. package/linthost/rules_format_bracket_spacing.go +117 -0
  160. package/linthost/rules_format_clause_join.go +172 -0
  161. package/linthost/rules_format_declaration_header.go +595 -0
  162. package/linthost/rules_format_indent.go +372 -0
  163. package/linthost/rules_format_jsdoc.go +5 -5
  164. package/linthost/rules_format_orphan_semi.go +106 -0
  165. package/linthost/rules_format_parameter_properties.go +175 -0
  166. package/linthost/rules_format_print_width.go +66 -55
  167. package/linthost/rules_format_quote_props.go +169 -0
  168. package/linthost/rules_format_quotes.go +76 -30
  169. package/linthost/rules_format_semi.go +186 -11
  170. package/linthost/rules_format_sort_imports.go +437 -118
  171. package/linthost/rules_format_statement_split.go +343 -0
  172. package/linthost/rules_format_ternary_nullish_parens.go +77 -0
  173. package/linthost/rules_format_trailing_comma.go +22 -3
  174. package/linthost/rules_format_whitespace.go +336 -0
  175. package/linthost/rules_functional.go +967 -0
  176. package/linthost/rules_gap.go +24 -45
  177. package/linthost/rules_grouped_accessor_pairs.go +87 -0
  178. package/linthost/rules_guard_for_in.go +198 -0
  179. package/linthost/rules_id_length.go +77 -0
  180. package/linthost/rules_imports.go +70 -2
  181. package/linthost/rules_init_declarations.go +53 -0
  182. package/linthost/rules_jest.go +618 -0
  183. package/linthost/rules_jsdoc.go +502 -0
  184. package/linthost/rules_jsx_a11y.go +1264 -0
  185. package/linthost/rules_logic.go +12 -12
  186. package/linthost/rules_loops.go +1 -1
  187. package/linthost/rules_max_classes_per_file.go +58 -0
  188. package/linthost/rules_max_depth.go +83 -0
  189. package/linthost/rules_max_lines.go +101 -0
  190. package/linthost/rules_max_lines_per_function.go +57 -0
  191. package/linthost/rules_max_nested_callbacks.go +61 -0
  192. package/linthost/rules_max_params.go +49 -0
  193. package/linthost/rules_max_statements.go +59 -0
  194. package/linthost/rules_misc.go +1 -1
  195. package/linthost/rules_nextjs.go +697 -0
  196. package/linthost/rules_no_else_return.go +75 -0
  197. package/linthost/rules_no_empty_named_blocks.go +91 -0
  198. package/linthost/rules_no_extend_native.go +51 -0
  199. package/linthost/rules_no_import_assign.go +140 -0
  200. package/linthost/rules_no_invalid_this.go +52 -0
  201. package/linthost/rules_no_loop_func.go +85 -0
  202. package/linthost/rules_no_magic_numbers.go +123 -0
  203. package/linthost/rules_no_mixed_operators.go +80 -0
  204. package/linthost/rules_no_param_reassign.go +98 -0
  205. package/linthost/rules_no_redeclare.go +270 -0
  206. package/linthost/rules_no_restricted_imports.go +105 -0
  207. package/linthost/rules_no_restricted_syntax.go +49 -0
  208. package/linthost/rules_no_shadow.go +147 -0
  209. package/linthost/rules_no_unreachable.go +77 -0
  210. package/linthost/rules_no_useless_assignment.go +120 -0
  211. package/linthost/rules_no_useless_constructor.go +245 -0
  212. package/linthost/rules_no_useless_return.go +51 -0
  213. package/linthost/rules_params.go +1 -1
  214. package/linthost/rules_playwright.go +788 -0
  215. package/linthost/rules_prefer_arrow_callback.go +124 -0
  216. package/linthost/rules_prefer_destructuring.go +98 -0
  217. package/linthost/rules_prefer_named_capture_group.go +129 -0
  218. package/linthost/rules_prefer_rest_params.go +94 -0
  219. package/linthost/rules_problems.go +41 -30
  220. package/linthost/rules_promise.go +1057 -2
  221. package/linthost/rules_protos.go +2 -2
  222. package/linthost/rules_react.go +773 -0
  223. package/linthost/rules_react_extras.go +227 -0
  224. package/linthost/rules_react_hooks.go +848 -0
  225. package/linthost/rules_react_perf.go +293 -0
  226. package/linthost/rules_react_refresh.go +583 -0
  227. package/linthost/rules_regexp.go +410 -0
  228. package/linthost/rules_security.go +830 -0
  229. package/linthost/rules_self.go +2 -2
  230. package/linthost/rules_solid.go +1073 -0
  231. package/linthost/rules_sort_imports.go +69 -0
  232. package/linthost/rules_sort_keys.go +134 -0
  233. package/linthost/rules_storybook.go +1176 -0
  234. package/linthost/rules_strings.go +4 -4
  235. package/linthost/rules_suggestions.go +38 -38
  236. package/linthost/rules_tanstack_query.go +844 -0
  237. package/linthost/rules_testing_library.go +1204 -0
  238. package/linthost/rules_throw.go +1 -1
  239. package/linthost/rules_ts.go +19 -19
  240. package/linthost/rules_ts_async.go +399 -0
  241. package/linthost/rules_ts_class_literal_property_style.go +115 -0
  242. package/linthost/rules_ts_consistent_type_exports.go +256 -0
  243. package/linthost/rules_ts_explicit_function_return_type.go +67 -0
  244. package/linthost/rules_ts_extra.go +159 -36
  245. package/linthost/rules_ts_no_base_to_string.go +218 -0
  246. package/linthost/rules_ts_no_confusing_void.go +72 -0
  247. package/linthost/rules_ts_no_deprecated.go +195 -0
  248. package/linthost/rules_ts_no_for_in_array.go +84 -0
  249. package/linthost/rules_ts_no_magic_numbers.go +124 -0
  250. package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
  251. package/linthost/rules_ts_no_misused_spread.go +104 -0
  252. package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
  253. package/linthost/rules_ts_no_restricted_types.go +62 -0
  254. package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
  255. package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
  256. package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
  257. package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
  258. package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
  259. package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
  260. package/linthost/rules_ts_no_unsafe_argument.go +82 -0
  261. package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
  262. package/linthost/rules_ts_no_unsafe_call.go +82 -0
  263. package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
  264. package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
  265. package/linthost/rules_ts_no_unsafe_return.go +126 -0
  266. package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
  267. package/linthost/rules_ts_no_useless_constructor.go +52 -0
  268. package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
  269. package/linthost/rules_ts_parameter_properties.go +38 -0
  270. package/linthost/rules_ts_prefer_find.go +178 -0
  271. package/linthost/rules_ts_prefer_includes.go +255 -0
  272. package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
  273. package/linthost/rules_ts_prefer_optional_chain.go +228 -0
  274. package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
  275. package/linthost/rules_ts_prefer_readonly.go +73 -0
  276. package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
  277. package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
  278. package/linthost/rules_ts_prefer_return_this_type.go +135 -0
  279. package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
  280. package/linthost/rules_ts_promise_function_async.go +77 -0
  281. package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
  282. package/linthost/rules_ts_require_array_sort_compare.go +96 -0
  283. package/linthost/rules_ts_restrict_plus_operands.go +127 -0
  284. package/linthost/rules_ts_restrict_template_expressions.go +95 -0
  285. package/linthost/rules_ts_simple.go +387 -0
  286. package/linthost/rules_ts_sort_type_constituents.go +144 -0
  287. package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
  288. package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
  289. package/linthost/rules_ts_unbound_method.go +126 -0
  290. package/linthost/rules_tsdoc.go +136 -0
  291. package/linthost/rules_unicorn_better_regex.go +27 -0
  292. package/linthost/rules_unicorn_catch_error_name.go +46 -0
  293. package/linthost/rules_unicorn_consistent_assert.go +47 -0
  294. package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
  295. package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
  296. package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
  297. package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
  298. package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
  299. package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
  300. package/linthost/rules_unicorn_custom_error_definition.go +138 -0
  301. package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
  302. package/linthost/rules_unicorn_error_message.go +64 -0
  303. package/linthost/rules_unicorn_escape_case.go +51 -0
  304. package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
  305. package/linthost/rules_unicorn_explicit_length_check.go +88 -0
  306. package/linthost/rules_unicorn_filename_case.go +29 -0
  307. package/linthost/rules_unicorn_import_style.go +28 -0
  308. package/linthost/rules_unicorn_isolated_functions.go +29 -0
  309. package/linthost/rules_unicorn_new_for_builtins.go +87 -0
  310. package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
  311. package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
  312. package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
  313. package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
  314. package/linthost/rules_unicorn_no_array_for_each.go +40 -0
  315. package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
  316. package/linthost/rules_unicorn_no_array_reduce.go +41 -0
  317. package/linthost/rules_unicorn_no_array_reverse.go +44 -0
  318. package/linthost/rules_unicorn_no_array_sort.go +43 -0
  319. package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
  320. package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
  321. package/linthost/rules_unicorn_no_console_spaces.go +61 -0
  322. package/linthost/rules_unicorn_no_document_cookie.go +41 -0
  323. package/linthost/rules_unicorn_no_empty_file.go +44 -0
  324. package/linthost/rules_unicorn_no_for_loop.go +102 -0
  325. package/linthost/rules_unicorn_no_hex_escape.go +42 -0
  326. package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
  327. package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
  328. package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
  329. package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
  330. package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
  331. package/linthost/rules_unicorn_no_lonely_if.go +44 -0
  332. package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
  333. package/linthost/rules_unicorn_no_named_default.go +54 -0
  334. package/linthost/rules_unicorn_no_negated_condition.go +85 -0
  335. package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
  336. package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
  337. package/linthost/rules_unicorn_no_new_array.go +30 -0
  338. package/linthost/rules_unicorn_no_new_buffer.go +31 -0
  339. package/linthost/rules_unicorn_no_null.go +24 -0
  340. package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
  341. package/linthost/rules_unicorn_no_process_exit.go +43 -0
  342. package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
  343. package/linthost/rules_unicorn_no_static_only_class.go +56 -0
  344. package/linthost/rules_unicorn_no_thenable.go +74 -0
  345. package/linthost/rules_unicorn_no_this_assignment.go +35 -0
  346. package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
  347. package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
  348. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
  349. package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
  350. package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
  351. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
  352. package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
  353. package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
  354. package/linthost/rules_unicorn_no_unused_properties.go +30 -0
  355. package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
  356. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
  357. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
  358. package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
  359. package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
  360. package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
  361. package/linthost/rules_unicorn_no_useless_spread.go +67 -0
  362. package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
  363. package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
  364. package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
  365. package/linthost/rules_unicorn_number_literal_case.go +69 -0
  366. package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
  367. package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
  368. package/linthost/rules_unicorn_prefer_array_find.go +51 -0
  369. package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
  370. package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
  371. package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
  372. package/linthost/rules_unicorn_prefer_array_some.go +67 -0
  373. package/linthost/rules_unicorn_prefer_at.go +77 -0
  374. package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
  375. package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
  376. package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
  377. package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
  378. package/linthost/rules_unicorn_prefer_code_point.go +49 -0
  379. package/linthost/rules_unicorn_prefer_date_now.go +78 -0
  380. package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
  381. package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
  382. package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
  383. package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
  384. package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
  385. package/linthost/rules_unicorn_prefer_event_target.go +36 -0
  386. package/linthost/rules_unicorn_prefer_export_from.go +129 -0
  387. package/linthost/rules_unicorn_prefer_global_this.go +127 -0
  388. package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
  389. package/linthost/rules_unicorn_prefer_includes.go +149 -0
  390. package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
  391. package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
  392. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
  393. package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
  394. package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
  395. package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
  396. package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
  397. package/linthost/rules_unicorn_prefer_module.go +50 -0
  398. package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
  399. package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
  400. package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
  401. package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
  402. package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
  403. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
  404. package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
  405. package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
  406. package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
  407. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
  408. package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
  409. package/linthost/rules_unicorn_prefer_set_has.go +42 -0
  410. package/linthost/rules_unicorn_prefer_set_size.go +48 -0
  411. package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
  412. package/linthost/rules_unicorn_prefer_single_call.go +96 -0
  413. package/linthost/rules_unicorn_prefer_spread.go +51 -0
  414. package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
  415. package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
  416. package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
  417. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
  418. package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
  419. package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
  420. package/linthost/rules_unicorn_prefer_switch.go +103 -0
  421. package/linthost/rules_unicorn_prefer_ternary.go +71 -0
  422. package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
  423. package/linthost/rules_unicorn_prefer_type_error.go +127 -0
  424. package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
  425. package/linthost/rules_unicorn_relative_url_style.go +49 -0
  426. package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
  427. package/linthost/rules_unicorn_require_module_attributes.go +54 -0
  428. package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
  429. package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
  430. package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
  431. package/linthost/rules_unicorn_string_content.go +27 -0
  432. package/linthost/rules_unicorn_switch_case_braces.go +42 -0
  433. package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
  434. package/linthost/rules_unicorn_template_indent.go +28 -0
  435. package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
  436. package/linthost/rules_unicorn_throw_new_error.go +61 -0
  437. package/linthost/rules_var.go +4 -4
  438. package/linthost/rules_vitest.go +568 -0
  439. package/package.json +3 -3
  440. package/plugin/main.go +49 -3
  441. package/rule/astutil/astutil.go +10 -3
  442. package/rule/rule.go +12 -10
  443. package/src/defaultFormat.ts +17 -10
  444. package/src/index.ts +40 -16
  445. package/src/structures/ITtscLintConfig.ts +14 -8
  446. package/src/structures/TtscLintRuleSetting.ts +55 -0
  447. package/src/structures/format/ITtscLintFormat.ts +141 -0
  448. package/src/structures/format/ITtscLintFormatJsDoc.ts +18 -0
  449. package/src/structures/format/ITtscLintFormatSortImports.ts +62 -0
  450. package/src/structures/format/index.ts +3 -0
  451. package/src/structures/index.ts +3 -4
  452. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +117 -0
  453. package/src/structures/rules/ITtscLintBoundariesRules.ts +91 -0
  454. package/src/structures/rules/ITtscLintContributorRules.ts +20 -0
  455. package/src/structures/rules/ITtscLintCoreRules.ts +1378 -0
  456. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
  457. package/src/structures/rules/ITtscLintCypressRules.ts +141 -0
  458. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +200 -0
  459. package/src/structures/rules/ITtscLintFunctionalRules.ts +197 -0
  460. package/src/structures/rules/ITtscLintJestRules.ts +209 -0
  461. package/src/structures/rules/ITtscLintJsdocRules.ts +146 -0
  462. package/src/structures/rules/ITtscLintJsxA11yRules.ts +331 -0
  463. package/src/structures/rules/ITtscLintNextjsRules.ts +201 -0
  464. package/src/structures/rules/ITtscLintPlaywrightRules.ts +343 -0
  465. package/src/structures/rules/ITtscLintPromiseRules.ts +196 -0
  466. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
  467. package/src/structures/rules/ITtscLintReactPerfRules.ts +53 -0
  468. package/src/structures/rules/ITtscLintReactRuleOptions.ts +41 -0
  469. package/src/structures/rules/ITtscLintReactRules.ts +308 -0
  470. package/src/structures/rules/ITtscLintRegexpRules.ts +204 -0
  471. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +88 -0
  472. package/src/structures/rules/ITtscLintRules.ts +77 -0
  473. package/src/structures/rules/ITtscLintSecurityRules.ts +155 -0
  474. package/src/structures/rules/ITtscLintSolidRules.ts +199 -0
  475. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +22 -0
  476. package/src/structures/rules/ITtscLintStorybookRules.ts +184 -0
  477. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +96 -0
  478. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +23 -0
  479. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +325 -0
  480. package/src/structures/rules/ITtscLintTypeScriptRules.ts +1172 -0
  481. package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
  482. package/src/structures/rules/ITtscLintVitestRules.ts +146 -0
  483. package/src/structures/rules/index.ts +31 -0
  484. package/lib/structures/ITtscLintFormatConfig.d.ts +0 -153
  485. package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
  486. package/lib/structures/TtscLintRule.d.ts +0 -17
  487. package/lib/structures/TtscLintRule.js.map +0 -1
  488. package/lib/structures/TtscLintRuleMap.d.ts +0 -46
  489. package/lib/structures/TtscLintRuleMap.js.map +0 -1
  490. package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
  491. package/lib/structures/TtscLintRuleOptions.js.map +0 -1
  492. package/src/structures/ITtscLintFormatConfig.ts +0 -168
  493. package/src/structures/TtscLintRule.ts +0 -160
  494. package/src/structures/TtscLintRuleMap.ts +0 -55
  495. package/src/structures/TtscLintRuleOptions.ts +0 -151
@@ -0,0 +1,96 @@
1
+ // unicorn/prefer-single-call: `xs.push(1); xs.push(2);` repeats the
2
+ // `xs.push` lookup and the call dispatch for what is conceptually one
3
+ // "append these values" operation. Variadic methods like `push`,
4
+ // `unshift`, `addEventListener`, and `removeEventListener` accept
5
+ // multiple arguments specifically so authors can collapse the back-to-
6
+ // back form into a single call.
7
+ //
8
+ // AST-only: visit each `Block` AND `SourceFile`, scan the statement
9
+ // list for any pair of consecutive `ExpressionStatement`s whose
10
+ // expressions are `CallExpression`s targeting
11
+ // `PropertyAccess(<sameReceiverText>, <sameMethod>)` where the method
12
+ // is one of the variadic appenders. Receiver equivalence is decided
13
+ // by source-text comparison so chained receivers (e.g. `obj.list.push`)
14
+ // line up exactly. Report on the second statement so the diagnostic
15
+ // anchors to the redundant call.
16
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-single-call.md
17
+ package linthost
18
+
19
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
20
+
21
+ type unicornPreferSingleCall struct{}
22
+
23
+ func (unicornPreferSingleCall) Name() string { return "unicorn/prefer-single-call" }
24
+ func (unicornPreferSingleCall) Visits() []shimast.Kind {
25
+ return []shimast.Kind{shimast.KindBlock, shimast.KindSourceFile}
26
+ }
27
+ func (unicornPreferSingleCall) Check(ctx *Context, node *shimast.Node) {
28
+ var stmts []*shimast.Node
29
+ switch node.Kind {
30
+ case shimast.KindBlock:
31
+ block := node.AsBlock()
32
+ if block == nil || block.Statements == nil {
33
+ return
34
+ }
35
+ stmts = block.Statements.Nodes
36
+ case shimast.KindSourceFile:
37
+ file := node.AsSourceFile()
38
+ if file == nil || file.Statements == nil {
39
+ return
40
+ }
41
+ stmts = file.Statements.Nodes
42
+ default:
43
+ return
44
+ }
45
+ for i := 1; i < len(stmts); i++ {
46
+ prevReceiver, prevMethod := unicornPreferSingleCallExtract(ctx, stmts[i-1])
47
+ if prevReceiver == "" {
48
+ continue
49
+ }
50
+ currReceiver, currMethod := unicornPreferSingleCallExtract(ctx, stmts[i])
51
+ if currReceiver == "" {
52
+ continue
53
+ }
54
+ if prevReceiver != currReceiver || prevMethod != currMethod {
55
+ continue
56
+ }
57
+ ctx.Report(stmts[i], "Combine consecutive `"+currMethod+"` calls with multiple arguments into a single call.")
58
+ }
59
+ }
60
+
61
+ // unicornPreferSingleCallExtract returns (receiverText, methodName) for a
62
+ // statement of the shape `<receiver>.<method>(…);` where `method` is one
63
+ // of the variadic appenders the rule targets. Returns ("", "") for any
64
+ // other shape.
65
+ func unicornPreferSingleCallExtract(ctx *Context, stmt *shimast.Node) (string, string) {
66
+ if stmt == nil || stmt.Kind != shimast.KindExpressionStatement {
67
+ return "", ""
68
+ }
69
+ exprStmt := stmt.AsExpressionStatement()
70
+ if exprStmt == nil || exprStmt.Expression == nil {
71
+ return "", ""
72
+ }
73
+ call := stripParens(exprStmt.Expression)
74
+ if call == nil || call.Kind != shimast.KindCallExpression {
75
+ return "", ""
76
+ }
77
+ c := call.AsCallExpression()
78
+ if c == nil || c.Expression == nil || c.Expression.Kind != shimast.KindPropertyAccessExpression {
79
+ return "", ""
80
+ }
81
+ access := c.Expression.AsPropertyAccessExpression()
82
+ if access == nil || access.Expression == nil {
83
+ return "", ""
84
+ }
85
+ method := identifierText(access.Name())
86
+ switch method {
87
+ case "push", "unshift", "addEventListener", "removeEventListener":
88
+ default:
89
+ return "", ""
90
+ }
91
+ return nodeText(ctx.File, access.Expression), method
92
+ }
93
+
94
+ func init() {
95
+ Register(unicornPreferSingleCall{})
96
+ }
@@ -0,0 +1,51 @@
1
+ // unicorn/prefer-spread: `Array.from(x)` with a single iterable argument
2
+ // is equivalent to a spread copy `[...x]`. The spread form is shorter,
3
+ // reads as a value-level operation rather than a constructor call, and
4
+ // removes the `Array` global from the read path entirely.
5
+ //
6
+ // AST-only: visit each `CallExpression`, match `Array.from(x)` — a
7
+ // callee that is a property access reading `from` on a bare identifier
8
+ // `Array`, with exactly one argument. The single-argument restriction
9
+ // is load-bearing: `Array.from(x, mapFn)` and `Array.from(x, mapFn,
10
+ // thisArg)` have observable behavior the spread does not (the mapper
11
+ // receives the index, and `thisArg` is bound on a non-arrow mapper), so
12
+ // the rule deliberately stays away from them.
13
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-spread.md
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ type unicornPreferSpread struct{}
19
+
20
+ func (unicornPreferSpread) Name() string { return "unicorn/prefer-spread" }
21
+ func (unicornPreferSpread) Visits() []shimast.Kind {
22
+ return []shimast.Kind{shimast.KindCallExpression}
23
+ }
24
+ func (unicornPreferSpread) Check(ctx *Context, node *shimast.Node) {
25
+ call := node.AsCallExpression()
26
+ if call == nil || call.Expression == nil {
27
+ return
28
+ }
29
+ if call.Expression.Kind != shimast.KindPropertyAccessExpression {
30
+ return
31
+ }
32
+ access := call.Expression.AsPropertyAccessExpression()
33
+ if access == nil {
34
+ return
35
+ }
36
+ if identifierText(access.Name()) != "from" {
37
+ return
38
+ }
39
+ receiver := stripParens(access.Expression)
40
+ if identifierText(receiver) != "Array" {
41
+ return
42
+ }
43
+ if call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
44
+ return
45
+ }
46
+ ctx.Report(node, "Prefer spread `[...x]` over `Array.from(x)` for single-arg shallow copies.")
47
+ }
48
+
49
+ func init() {
50
+ Register(unicornPreferSpread{})
51
+ }
@@ -0,0 +1,43 @@
1
+ // unicorn/prefer-string-raw: a string literal whose source contains
2
+ // `\\` (an escaped backslash) is using the escape syntax to represent a
3
+ // literal backslash. The same value, written through `String.raw` as
4
+ // a template literal, drops every backslash escape and reads as the
5
+ // literal text the author meant — particularly noticeable for Windows
6
+ // paths, regex source strings, and TeX-shaped snippets.
7
+ //
8
+ // AST-only: visit `KindStringLiteral` and
9
+ // `KindNoSubstitutionTemplateLiteral`. The match keys on the raw source
10
+ // bytes of the literal node — `nodeText` returns the as-written source
11
+ // — and fires when those bytes contain the two-character sequence `\\`,
12
+ // i.e. an escaped backslash that `String.raw` would render literally.
13
+ // Untagged template literals with substitutions are out of scope; this
14
+ // rule only addresses the "single literal of fixed text" case.
15
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-raw.md
16
+ package linthost
17
+
18
+ import (
19
+ "strings"
20
+
21
+ shimast "github.com/microsoft/typescript-go/shim/ast"
22
+ )
23
+
24
+ type unicornPreferStringRaw struct{}
25
+
26
+ func (unicornPreferStringRaw) Name() string { return "unicorn/prefer-string-raw" }
27
+ func (unicornPreferStringRaw) Visits() []shimast.Kind {
28
+ return []shimast.Kind{shimast.KindStringLiteral, shimast.KindNoSubstitutionTemplateLiteral}
29
+ }
30
+ func (unicornPreferStringRaw) Check(ctx *Context, node *shimast.Node) {
31
+ raw := nodeText(ctx.File, node)
32
+ if raw == "" {
33
+ return
34
+ }
35
+ if !strings.Contains(raw, `\\`) {
36
+ return
37
+ }
38
+ ctx.Report(node, "Prefer `String.raw` for strings with backslash escapes.")
39
+ }
40
+
41
+ func init() {
42
+ Register(unicornPreferStringRaw{})
43
+ }
@@ -0,0 +1,95 @@
1
+ // unicorn/prefer-string-replace-all: `"abc".replace(/a/g, "x")` is the
2
+ // pre-ES2021 idiom for "replace every occurrence". ES2021's
3
+ // `String#replaceAll` does the same thing without the regex flag
4
+ // detour. The rule fires on `.replace(/<pattern>/g, replacement)` so
5
+ // authors switch to the explicit method.
6
+ //
7
+ // AST-only: a `CallExpression` whose callee is `.replace` AND whose
8
+ // first argument is a `RegularExpressionLiteral` carrying the `g` flag
9
+ // in its trailing flag block matches. The flag is read from the raw
10
+ // source text — the AST does not split pattern from flags — using the
11
+ // shared `nodeText` accessor.
12
+ //
13
+ // To preserve semantics, the pattern body must also be literal — any
14
+ // regex metacharacter (`\`, `.`, `*`, `+`, `?`, `[`, `]`, `(`, `)`,
15
+ // `{`, `}`, `|`, `^`, `$`) disqualifies the rewrite, because
16
+ // `/<pat>/g` and `.replaceAll(<pat>, ...)` mean different things when
17
+ // the pattern is anything but a fixed string.
18
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-replace-all.md
19
+ package linthost
20
+
21
+ import (
22
+ "strings"
23
+
24
+ shimast "github.com/microsoft/typescript-go/shim/ast"
25
+ )
26
+
27
+ type unicornPreferStringReplaceAll struct{}
28
+
29
+ func (unicornPreferStringReplaceAll) Name() string { return "unicorn/prefer-string-replace-all" }
30
+ func (unicornPreferStringReplaceAll) Visits() []shimast.Kind {
31
+ return []shimast.Kind{shimast.KindCallExpression}
32
+ }
33
+ func (unicornPreferStringReplaceAll) Check(ctx *Context, node *shimast.Node) {
34
+ call := node.AsCallExpression()
35
+ if call == nil || call.Expression == nil ||
36
+ call.Expression.Kind != shimast.KindPropertyAccessExpression {
37
+ return
38
+ }
39
+ access := call.Expression.AsPropertyAccessExpression()
40
+ if access == nil || identifierText(access.Name()) != "replace" {
41
+ return
42
+ }
43
+ if call.Arguments == nil || len(call.Arguments.Nodes) < 1 {
44
+ return
45
+ }
46
+ first := stripParens(call.Arguments.Nodes[0])
47
+ if first == nil || first.Kind != shimast.KindRegularExpressionLiteral {
48
+ return
49
+ }
50
+ raw := nodeText(ctx.File, first)
51
+ if !unicornPreferStringReplaceAllHasGlobalFlag(raw) {
52
+ return
53
+ }
54
+ if !unicornPreferStringReplaceAllIsLiteralPattern(raw) {
55
+ return
56
+ }
57
+ ctx.Report(node, "Prefer `String#replaceAll(literal, replacement)` over `replace(/literal/g, replacement)`.")
58
+ }
59
+
60
+ // unicornPreferStringReplaceAllHasGlobalFlag returns true when `raw` (the
61
+ // source text of a RegularExpressionLiteral, including the surrounding
62
+ // `/` delimiters and trailing flag block) carries the `g` flag.
63
+ func unicornPreferStringReplaceAllHasGlobalFlag(raw string) bool {
64
+ if len(raw) < 3 || raw[0] != '/' {
65
+ return false
66
+ }
67
+ closing := strings.LastIndexByte(raw, '/')
68
+ if closing <= 0 {
69
+ return false
70
+ }
71
+ flags := raw[closing+1:]
72
+ return strings.ContainsRune(flags, 'g')
73
+ }
74
+
75
+ // unicornPreferStringReplaceAllIsLiteralPattern returns true when the
76
+ // pattern body of `raw` (the source text of a RegularExpressionLiteral)
77
+ // contains no regex metacharacters. Conservative: any metachar — even
78
+ // an escaped one like `\.` — disqualifies the rewrite, because
79
+ // recovering the original character cleanly from raw source requires
80
+ // regex-aware parsing we don't do here.
81
+ func unicornPreferStringReplaceAllIsLiteralPattern(raw string) bool {
82
+ if len(raw) < 3 || raw[0] != '/' {
83
+ return false
84
+ }
85
+ closing := strings.LastIndexByte(raw, '/')
86
+ if closing <= 0 {
87
+ return false
88
+ }
89
+ body := raw[1:closing]
90
+ return !strings.ContainsAny(body, `\.*+?[](){}|^$`)
91
+ }
92
+
93
+ func init() {
94
+ Register(unicornPreferStringReplaceAll{})
95
+ }
@@ -0,0 +1,43 @@
1
+ // unicorn/prefer-string-slice: `String#substr` is deprecated and
2
+ // `String#substring` has surprising "swap arguments when end < start"
3
+ // semantics. `String#slice` is the single modern alternative whose
4
+ // behavior matches author intent. The rule fires on any `.substr(…)`
5
+ // or `.substring(…)` callsite so the codebase converges on `.slice`.
6
+ //
7
+ // AST-only: a `CallExpression` whose callee is a
8
+ // `PropertyAccessExpression` ending in `substr` or `substring`
9
+ // matches. Receiver typing is intentionally not checked — both names
10
+ // exist almost exclusively on strings in real code, and the
11
+ // upstream rule treats them as banned regardless.
12
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-slice.md
13
+ package linthost
14
+
15
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
16
+
17
+ type unicornPreferStringSlice struct{}
18
+
19
+ func (unicornPreferStringSlice) Name() string { return "unicorn/prefer-string-slice" }
20
+ func (unicornPreferStringSlice) Visits() []shimast.Kind {
21
+ return []shimast.Kind{shimast.KindCallExpression}
22
+ }
23
+ func (unicornPreferStringSlice) Check(ctx *Context, node *shimast.Node) {
24
+ call := node.AsCallExpression()
25
+ if call == nil || call.Expression == nil ||
26
+ call.Expression.Kind != shimast.KindPropertyAccessExpression {
27
+ return
28
+ }
29
+ access := call.Expression.AsPropertyAccessExpression()
30
+ if access == nil {
31
+ return
32
+ }
33
+ switch identifierText(access.Name()) {
34
+ case "substr", "substring":
35
+ default:
36
+ return
37
+ }
38
+ ctx.Report(node, "Prefer `String#slice()` over `substr` / `substring`.")
39
+ }
40
+
41
+ func init() {
42
+ Register(unicornPreferStringSlice{})
43
+ }
@@ -0,0 +1,148 @@
1
+ // unicorn/prefer-string-starts-ends-with: `s.slice(0, 4) === "http"` and
2
+ // `s.slice(-3) === "abc"` are the legacy spellings of `s.startsWith(...)`
3
+ // and `s.endsWith(...)`. The String methods are clearer about intent, do
4
+ // not allocate the intermediate substring, and have been available for
5
+ // over a decade.
6
+ //
7
+ // AST-only: visit each `BinaryExpression` whose operator is `===` or
8
+ // `!==`. One operand must be a `CallExpression` of the shape
9
+ // `_.slice(0, N)` or `_.slice(-N)` (the `-N` form being a unary minus
10
+ // over a numeric literal) and the other operand must be a string literal
11
+ // whose text length matches N. Reports on the binary expression.
12
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-starts-ends-with.md
13
+ package linthost
14
+
15
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
16
+
17
+ type unicornPreferStringStartsEndsWith struct{}
18
+
19
+ func (unicornPreferStringStartsEndsWith) Name() string {
20
+ return "unicorn/prefer-string-starts-ends-with"
21
+ }
22
+ func (unicornPreferStringStartsEndsWith) Visits() []shimast.Kind {
23
+ return []shimast.Kind{shimast.KindBinaryExpression}
24
+ }
25
+ func (unicornPreferStringStartsEndsWith) Check(ctx *Context, node *shimast.Node) {
26
+ bin := node.AsBinaryExpression()
27
+ if bin == nil || bin.OperatorToken == nil || bin.Left == nil || bin.Right == nil {
28
+ return
29
+ }
30
+ switch bin.OperatorToken.Kind {
31
+ case shimast.KindEqualsEqualsEqualsToken,
32
+ shimast.KindExclamationEqualsEqualsToken:
33
+ default:
34
+ return
35
+ }
36
+ left := stripParens(bin.Left)
37
+ right := stripParens(bin.Right)
38
+ if unicornPreferStringStartsEndsWithMatches(left, right) ||
39
+ unicornPreferStringStartsEndsWithMatches(right, left) {
40
+ ctx.Report(node, "Prefer `String#startsWith()` / `String#endsWith()` over slice-and-compare.")
41
+ }
42
+ }
43
+
44
+ // unicornPreferStringStartsEndsWithMatches reports whether `callSide` is
45
+ // the slice call and `literalSide` is a matching string literal.
46
+ func unicornPreferStringStartsEndsWithMatches(callSide, literalSide *shimast.Node) bool {
47
+ if callSide == nil || literalSide == nil {
48
+ return false
49
+ }
50
+ if callSide.Kind != shimast.KindCallExpression {
51
+ return false
52
+ }
53
+ if literalSide.Kind != shimast.KindStringLiteral &&
54
+ literalSide.Kind != shimast.KindNoSubstitutionTemplateLiteral {
55
+ return false
56
+ }
57
+ call := callSide.AsCallExpression()
58
+ if call == nil || call.Expression == nil ||
59
+ call.Expression.Kind != shimast.KindPropertyAccessExpression {
60
+ return false
61
+ }
62
+ access := call.Expression.AsPropertyAccessExpression()
63
+ if access == nil || identifierText(access.Name()) != "slice" {
64
+ return false
65
+ }
66
+ if call.Arguments == nil {
67
+ return false
68
+ }
69
+ args := call.Arguments.Nodes
70
+ wantLen := -1
71
+ switch len(args) {
72
+ case 2:
73
+ first := stripParens(args[0])
74
+ second := stripParens(args[1])
75
+ if first == nil || first.Kind != shimast.KindNumericLiteral ||
76
+ numericLiteralText(first) != "0" {
77
+ return false
78
+ }
79
+ if second == nil || second.Kind != shimast.KindNumericLiteral {
80
+ return false
81
+ }
82
+ if !unicornPreferStringStartsEndsWithDigits(numericLiteralText(second)) {
83
+ return false
84
+ }
85
+ wantLen = unicornPreferStringStartsEndsWithToInt(numericLiteralText(second))
86
+ case 1:
87
+ // `.slice(-N)` — a unary minus over a positive numeric literal.
88
+ only := stripParens(args[0])
89
+ if only == nil || only.Kind != shimast.KindPrefixUnaryExpression {
90
+ return false
91
+ }
92
+ prefix := only.AsPrefixUnaryExpression()
93
+ if prefix == nil || prefix.Operator != shimast.KindMinusToken ||
94
+ prefix.Operand == nil ||
95
+ prefix.Operand.Kind != shimast.KindNumericLiteral {
96
+ return false
97
+ }
98
+ text := numericLiteralText(prefix.Operand)
99
+ if !unicornPreferStringStartsEndsWithDigits(text) {
100
+ return false
101
+ }
102
+ wantLen = unicornPreferStringStartsEndsWithToInt(text)
103
+ default:
104
+ return false
105
+ }
106
+ if wantLen <= 0 {
107
+ return false
108
+ }
109
+ return len(stringLiteralText(literalSide)) == wantLen
110
+ }
111
+
112
+ // unicornPreferStringStartsEndsWithDigits reports whether `text` is a
113
+ // non-empty ASCII decimal-integer literal. Decimals, hex, and `e`-notation
114
+ // are rejected since the rule only handles fixed-length prefixes.
115
+ func unicornPreferStringStartsEndsWithDigits(text string) bool {
116
+ if text == "" {
117
+ return false
118
+ }
119
+ for i := 0; i < len(text); i++ {
120
+ c := text[i]
121
+ if c < '0' || c > '9' {
122
+ return false
123
+ }
124
+ }
125
+ return true
126
+ }
127
+
128
+ // unicornPreferStringStartsEndsWithToInt parses an ASCII decimal-integer
129
+ // literal into an int. Callers must have validated the input first; this
130
+ // helper returns -1 only as a defensive fallback for an overflow guard.
131
+ func unicornPreferStringStartsEndsWithToInt(text string) int {
132
+ n := 0
133
+ for i := 0; i < len(text); i++ {
134
+ c := text[i]
135
+ if c < '0' || c > '9' {
136
+ return -1
137
+ }
138
+ n = n*10 + int(c-'0')
139
+ if n > 1<<30 {
140
+ return -1
141
+ }
142
+ }
143
+ return n
144
+ }
145
+
146
+ func init() {
147
+ Register(unicornPreferStringStartsEndsWith{})
148
+ }
@@ -0,0 +1,48 @@
1
+ // unicorn/prefer-string-trim-start-end: `String#trimLeft` and
2
+ // `String#trimRight` are the deprecated names for what
3
+ // `String#trimStart` / `String#trimEnd` express directly. The deprecated
4
+ // names are still callable but should be replaced for consistency with
5
+ // the modern naming. The rule fires on zero-argument calls to either
6
+ // deprecated method.
7
+ //
8
+ // AST-only: a `CallExpression` whose callee is `.trimLeft` or
9
+ // `.trimRight` and whose argument list is empty matches. Arguments are
10
+ // theoretically not allowed on either method, but the AST does not
11
+ // know that — the rule defends against the syntactic shape only.
12
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-trim-start-end.md
13
+ package linthost
14
+
15
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
16
+
17
+ type unicornPreferStringTrimStartEnd struct{}
18
+
19
+ func (unicornPreferStringTrimStartEnd) Name() string {
20
+ return "unicorn/prefer-string-trim-start-end"
21
+ }
22
+ func (unicornPreferStringTrimStartEnd) Visits() []shimast.Kind {
23
+ return []shimast.Kind{shimast.KindCallExpression}
24
+ }
25
+ func (unicornPreferStringTrimStartEnd) Check(ctx *Context, node *shimast.Node) {
26
+ call := node.AsCallExpression()
27
+ if call == nil || call.Expression == nil ||
28
+ call.Expression.Kind != shimast.KindPropertyAccessExpression {
29
+ return
30
+ }
31
+ access := call.Expression.AsPropertyAccessExpression()
32
+ if access == nil {
33
+ return
34
+ }
35
+ switch identifierText(access.Name()) {
36
+ case "trimLeft", "trimRight":
37
+ default:
38
+ return
39
+ }
40
+ if call.Arguments != nil && len(call.Arguments.Nodes) > 0 {
41
+ return
42
+ }
43
+ ctx.Report(node, "Prefer `String#trimStart` / `String#trimEnd` over the deprecated `trimLeft` / `trimRight`.")
44
+ }
45
+
46
+ func init() {
47
+ Register(unicornPreferStringTrimStartEnd{})
48
+ }
@@ -0,0 +1,71 @@
1
+ // unicorn/prefer-structured-clone: `JSON.parse(JSON.stringify(x))` is
2
+ // the historical deep-clone idiom. It silently drops everything JSON
3
+ // cannot round-trip — `Date`, `Map`, `Set`, typed arrays, cyclic
4
+ // references — and re-allocates a large intermediate string. The
5
+ // platform-native `structuredClone(x)` handles every transferable type,
6
+ // supports cycles, and avoids the string round-trip entirely.
7
+ //
8
+ // AST-only: visit each `CallExpression`, match `JSON.parse(arg)` whose
9
+ // single `arg` is itself a `JSON.stringify(...)` call. Both gates lock
10
+ // the receiver to the bare `JSON` identifier so member-access chains
11
+ // reading `parse`/`stringify` on a renamed alias do not trip the rule.
12
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-structured-clone.md
13
+ package linthost
14
+
15
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
16
+
17
+ type unicornPreferStructuredClone struct{}
18
+
19
+ func (unicornPreferStructuredClone) Name() string {
20
+ return "unicorn/prefer-structured-clone"
21
+ }
22
+ func (unicornPreferStructuredClone) Visits() []shimast.Kind {
23
+ return []shimast.Kind{shimast.KindCallExpression}
24
+ }
25
+ func (unicornPreferStructuredClone) Check(ctx *Context, node *shimast.Node) {
26
+ if !isJSONMethodCall(node, "parse") {
27
+ return
28
+ }
29
+ outer := node.AsCallExpression()
30
+ if outer == nil || outer.Arguments == nil || len(outer.Arguments.Nodes) != 1 {
31
+ return
32
+ }
33
+ arg := stripParens(outer.Arguments.Nodes[0])
34
+ if arg == nil || arg.Kind != shimast.KindCallExpression {
35
+ return
36
+ }
37
+ if !isJSONMethodCall(arg, "stringify") {
38
+ return
39
+ }
40
+ ctx.Report(node, "Prefer `structuredClone(x)` over `JSON.parse(JSON.stringify(x))`.")
41
+ }
42
+
43
+ // isJSONMethodCall reports whether `node` is a CallExpression whose
44
+ // callee is `JSON.<method>` — a property access reading `method` on a
45
+ // bare `JSON` identifier. The bare-identifier gate keeps the rule from
46
+ // firing on `aliased.parse(...)` shapes that happen to share the
47
+ // method name.
48
+ func isJSONMethodCall(node *shimast.Node, method string) bool {
49
+ if node == nil || node.Kind != shimast.KindCallExpression {
50
+ return false
51
+ }
52
+ call := node.AsCallExpression()
53
+ if call == nil || call.Expression == nil {
54
+ return false
55
+ }
56
+ if call.Expression.Kind != shimast.KindPropertyAccessExpression {
57
+ return false
58
+ }
59
+ access := call.Expression.AsPropertyAccessExpression()
60
+ if access == nil {
61
+ return false
62
+ }
63
+ if identifierText(access.Name()) != method {
64
+ return false
65
+ }
66
+ return identifierText(stripParens(access.Expression)) == "JSON"
67
+ }
68
+
69
+ func init() {
70
+ Register(unicornPreferStructuredClone{})
71
+ }