@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,73 @@
1
+ // unicorn/empty-brace-spaces: an empty block `{ }` or empty object
2
+ // literal `{ }` written with whitespace between the braces wastes a
3
+ // column of source for no semantic effect. The rule collapses the two
4
+ // braces so the canonical empty form is `{}`.
5
+ //
6
+ // AST-only: visit both `Block` and `ObjectLiteralExpression`. The match
7
+ // fires when the node is empty (zero statements / zero properties) AND
8
+ // the source text between the opening `{` and closing `}` contains at
9
+ // least one whitespace byte. The whitespace check uses the source-file
10
+ // byte buffer directly because the AST itself elides the inter-token
11
+ // whitespace.
12
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/empty-brace-spaces.md
13
+ package linthost
14
+
15
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
16
+
17
+ type unicornEmptyBraceSpaces struct{}
18
+
19
+ func (unicornEmptyBraceSpaces) Name() string { return "unicorn/empty-brace-spaces" }
20
+ func (unicornEmptyBraceSpaces) Visits() []shimast.Kind {
21
+ return []shimast.Kind{shimast.KindBlock, shimast.KindObjectLiteralExpression}
22
+ }
23
+ func (unicornEmptyBraceSpaces) Check(ctx *Context, node *shimast.Node) {
24
+ if ctx.File == nil {
25
+ return
26
+ }
27
+ switch node.Kind {
28
+ case shimast.KindBlock:
29
+ block := node.AsBlock()
30
+ if block == nil || block.Statements == nil || len(block.Statements.Nodes) > 0 {
31
+ return
32
+ }
33
+ case shimast.KindObjectLiteralExpression:
34
+ obj := node.AsObjectLiteralExpression()
35
+ if obj == nil || obj.Properties == nil || len(obj.Properties.Nodes) > 0 {
36
+ return
37
+ }
38
+ default:
39
+ return
40
+ }
41
+ src := ctx.File.Text()
42
+ _, end := tokenRange(ctx.File, node)
43
+ pos := node.Pos()
44
+ if pos < 0 || end < 0 || end > len(src) {
45
+ return
46
+ }
47
+ // Locate the opening `{` after any leading trivia.
48
+ open := -1
49
+ for i := pos; i < end; i++ {
50
+ if src[i] == '{' {
51
+ open = i
52
+ break
53
+ }
54
+ }
55
+ if open < 0 || end-1 <= open {
56
+ return
57
+ }
58
+ // The closing `}` is the byte immediately before End().
59
+ if src[end-1] != '}' {
60
+ return
61
+ }
62
+ for i := open + 1; i < end-1; i++ {
63
+ switch src[i] {
64
+ case ' ', '\t', '\r', '\n':
65
+ ctx.Report(node, "Empty braces shouldn't contain whitespace.")
66
+ return
67
+ }
68
+ }
69
+ }
70
+
71
+ func init() {
72
+ Register(unicornEmptyBraceSpaces{})
73
+ }
@@ -0,0 +1,64 @@
1
+ // unicorn/error-message: a `new Error()` (or any built-in Error subclass)
2
+ // without a message string strips the most valuable diagnostic from the
3
+ // stack trace. The error type alone tells readers nothing about WHY the
4
+ // throw site fired; the rule requires every Error construction to carry
5
+ // a non-empty message.
6
+ //
7
+ // AST-only: visit each `NewExpression`, match the callee identifier
8
+ // against the built-in Error allowlist, then inspect the argument list.
9
+ // Zero arguments fires immediately; a single argument fires only when it
10
+ // is a string literal whose text is empty (`new Error("")`). Calls with
11
+ // dynamic arguments are out of scope because the rule cannot prove the
12
+ // argument resolves to a non-empty string at runtime.
13
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/error-message.md
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ var unicornErrorMessageBuiltinNames = map[string]struct{}{
19
+ "Error": {},
20
+ "TypeError": {},
21
+ "RangeError": {},
22
+ "SyntaxError": {},
23
+ "ReferenceError": {},
24
+ "EvalError": {},
25
+ "URIError": {},
26
+ "AggregateError": {},
27
+ }
28
+
29
+ type unicornErrorMessage struct{}
30
+
31
+ func (unicornErrorMessage) Name() string { return "unicorn/error-message" }
32
+ func (unicornErrorMessage) Visits() []shimast.Kind {
33
+ return []shimast.Kind{shimast.KindNewExpression}
34
+ }
35
+ func (unicornErrorMessage) Check(ctx *Context, node *shimast.Node) {
36
+ ne := node.AsNewExpression()
37
+ if ne == nil {
38
+ return
39
+ }
40
+ name := identifierText(ne.Expression)
41
+ if name == "" {
42
+ return
43
+ }
44
+ if _, ok := unicornErrorMessageBuiltinNames[name]; !ok {
45
+ return
46
+ }
47
+ // Zero arguments — `new Error()` / `new Error` — always fires.
48
+ if ne.Arguments == nil || len(ne.Arguments.Nodes) == 0 {
49
+ ctx.Report(node, "Pass an error message to the `Error` constructor.")
50
+ return
51
+ }
52
+ // Single argument — fire only when the argument is an empty string
53
+ // literal. Dynamic arguments cannot be proven empty statically.
54
+ if len(ne.Arguments.Nodes) == 1 {
55
+ arg := stripParens(ne.Arguments.Nodes[0])
56
+ if arg != nil && arg.Kind == shimast.KindStringLiteral && stringLiteralText(arg) == "" {
57
+ ctx.Report(node, "Pass an error message to the `Error` constructor.")
58
+ }
59
+ }
60
+ }
61
+
62
+ func init() {
63
+ Register(unicornErrorMessage{})
64
+ }
@@ -0,0 +1,51 @@
1
+ // unicorn/escape-case: numeric escape sequences inside string and
2
+ // template literals (`\xHH`, `\uHHHH`, `\u{HEX...}`) are case-insensitive
3
+ // to the engine but read inconsistently across a codebase when authors
4
+ // mix `\xa9` and `\xA9`. Canonical form uses uppercase hex digits; the
5
+ // rule fires when any hex escape's A-F digits are lowercase.
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), and match against a regex that finds
10
+ // `\xHH`, `\uHHHH`, or `\u{HEX...}` whose hex portion contains an a-f
11
+ // letter. The match is hex-only — `\n` and other identifier escapes are
12
+ // untouched.
13
+ //
14
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/escape-case.md
15
+ package linthost
16
+
17
+ import (
18
+ "regexp"
19
+
20
+ shimast "github.com/microsoft/typescript-go/shim/ast"
21
+ )
22
+
23
+ // unicornEscapeCasePattern matches a hex escape whose hex digits contain
24
+ // at least one lowercase a-f letter. The regex anchors on `\x`, `\u`, or
25
+ // `\u{...}` and rejects matches where every hex digit is already
26
+ // uppercase / 0-9.
27
+ var unicornEscapeCasePattern = regexp.MustCompile(
28
+ `\\x[0-9A-Fa-f]*[a-f][0-9A-Fa-f]*|` +
29
+ `\\u\{[0-9A-Fa-f]*[a-f][0-9A-Fa-f]*\}|` +
30
+ `\\u[0-9A-Fa-f]*[a-f][0-9A-Fa-f]*`,
31
+ )
32
+
33
+ type unicornEscapeCase struct{}
34
+
35
+ func (unicornEscapeCase) Name() string { return "unicorn/escape-case" }
36
+ func (unicornEscapeCase) Visits() []shimast.Kind {
37
+ return []shimast.Kind{shimast.KindStringLiteral, shimast.KindNoSubstitutionTemplateLiteral}
38
+ }
39
+ func (unicornEscapeCase) Check(ctx *Context, node *shimast.Node) {
40
+ source := nodeText(ctx.File, node)
41
+ if source == "" {
42
+ return
43
+ }
44
+ if unicornEscapeCasePattern.MatchString(source) {
45
+ ctx.Report(node, "Use uppercase letters for escape sequence hex digits (`\\xA9` over `\\xa9`).")
46
+ }
47
+ }
48
+
49
+ func init() {
50
+ Register(unicornEscapeCase{})
51
+ }
@@ -0,0 +1,78 @@
1
+ // unicorn/expiring-todo-comments: a `TODO`/`FIXME`/`XXX` comment with no
2
+ // expiration condition is a future-dated lie waiting to bit-rot — the
3
+ // upstream rule wants every such marker to carry a bracketed predicate
4
+ // like `[2027-01-01]` or `[npm:foo@>=2]` so that the lint will start
5
+ // failing once the condition is met.
6
+ //
7
+ // File-level dispatch: visit `KindSourceFile` once per file, scan the
8
+ // raw source with the tsgo scanner so embedded `/* */` and `//` tokens
9
+ // inside template substitutions and string literals are not mistaken
10
+ // for real comments, strip the comment delimiters via
11
+ // `stripCommentDelimiters`, then for each stripped body locate a
12
+ // TODO-family marker. Go's RE2 has no negative lookahead, so the
13
+ // "no `[` annotation block follows" half of the rule is checked
14
+ // separately: after the keyword match offset, scan the rest of the
15
+ // comment body for a `[` byte. Missing means the marker has no
16
+ // expiration condition; the comment range is reported.
17
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/expiring-todo-comments.md
18
+ package linthost
19
+
20
+ import (
21
+ "regexp"
22
+ "strings"
23
+
24
+ shimast "github.com/microsoft/typescript-go/shim/ast"
25
+ shimscanner "github.com/microsoft/typescript-go/shim/scanner"
26
+ )
27
+
28
+ // unicornExpiringTodoCommentsKeywordPattern matches a TODO-family
29
+ // marker that starts at the beginning of the (stripped) comment body
30
+ // or after whitespace, and is followed by `:`, whitespace, `(`, or
31
+ // end-of-string. The leading anchor avoids matching `todo` inside
32
+ // kebab-cased identifiers like `expiring-todo-comments` that other
33
+ // in-tree comments (e.g. the harness's own `// expect:` lines)
34
+ // inevitably include. Case-insensitive.
35
+ var unicornExpiringTodoCommentsKeywordPattern = regexp.MustCompile(`(?i)(?:^|\s)(TODO|FIXME|XXX)(?:[:(\s]|$)`)
36
+
37
+ type unicornExpiringTodoComments struct{}
38
+
39
+ func (unicornExpiringTodoComments) Name() string { return "unicorn/expiring-todo-comments" }
40
+ func (unicornExpiringTodoComments) Visits() []shimast.Kind {
41
+ return []shimast.Kind{shimast.KindSourceFile}
42
+ }
43
+ func (unicornExpiringTodoComments) Check(ctx *Context, node *shimast.Node) {
44
+ if ctx.File == nil {
45
+ return
46
+ }
47
+ src := ctx.File.Text()
48
+ scanner := shimscanner.NewScanner()
49
+ scanner.SetText(src)
50
+ scanner.SetSkipTrivia(false)
51
+ for {
52
+ kind := scanner.Scan()
53
+ if kind == shimast.KindEndOfFile {
54
+ break
55
+ }
56
+ if kind != shimast.KindSingleLineCommentTrivia && kind != shimast.KindMultiLineCommentTrivia {
57
+ continue
58
+ }
59
+ start := scanner.TokenStart()
60
+ end := scanner.TokenEnd()
61
+ if start < 0 || end > len(src) || end <= start {
62
+ continue
63
+ }
64
+ body := stripCommentDelimiters(src[start:end])
65
+ match := unicornExpiringTodoCommentsKeywordPattern.FindStringIndex(body)
66
+ if match == nil {
67
+ continue
68
+ }
69
+ if strings.Contains(body[match[1]:], "[") {
70
+ continue
71
+ }
72
+ ctx.ReportRange(start, end, "Add an expiration condition to this TODO (e.g., `[2027-01-01]` or `[npm:foo@>=2]`).")
73
+ }
74
+ }
75
+
76
+ func init() {
77
+ Register(unicornExpiringTodoComments{})
78
+ }
@@ -0,0 +1,88 @@
1
+ // unicorn/explicit-length-check: `.length` (or `.size`) coerced to
2
+ // boolean (`if (xs.length) …`) reads as "is the array truthy" rather
3
+ // than "does the array have elements". A reader has to know that
4
+ // `.length` is a number and that `0` is the only falsy value to
5
+ // reconstruct the intent. Explicit comparisons (`xs.length > 0`,
6
+ // `xs.length === 0`) put the predicate on the page. The rule fires
7
+ // when a `.length`/`.size` property access sits in a boolean context.
8
+ //
9
+ // AST-only: visit `KindPropertyAccessExpression`, accept when the
10
+ // property name is `length` or `size`, and check whether the (possibly
11
+ // parenthesized) node sits as the test of an `if`/`while`/`for`/
12
+ // conditional, as the operand of `!`, or as a side of a logical
13
+ // `&&`/`||`/`??` chain. The boolean-context walk reuses the parent
14
+ // traversal pattern from `rules_logic.go::isInBooleanContext`.
15
+ //
16
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/explicit-length-check.md
17
+ package linthost
18
+
19
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
20
+
21
+ type unicornExplicitLengthCheck struct{}
22
+
23
+ func (unicornExplicitLengthCheck) Name() string { return "unicorn/explicit-length-check" }
24
+ func (unicornExplicitLengthCheck) Visits() []shimast.Kind {
25
+ return []shimast.Kind{shimast.KindPropertyAccessExpression}
26
+ }
27
+ func (unicornExplicitLengthCheck) Check(ctx *Context, node *shimast.Node) {
28
+ access := node.AsPropertyAccessExpression()
29
+ if access == nil {
30
+ return
31
+ }
32
+ name := identifierText(access.Name())
33
+ if name != "length" && name != "size" {
34
+ return
35
+ }
36
+ if !unicornExplicitLengthCheckIsBooleanContext(node) {
37
+ return
38
+ }
39
+ ctx.Report(node, "Use an explicit comparison (`.length > 0` or `.length === 0`) instead of truthy coercion.")
40
+ }
41
+
42
+ // unicornExplicitLengthCheckIsBooleanContext walks the parent chain to
43
+ // see whether the value of `node` is consumed as a boolean — the test
44
+ // position of a control-flow statement / ternary, the operand of `!`,
45
+ // or one side of a logical (`&&` / `||` / `??`) chain.
46
+ func unicornExplicitLengthCheckIsBooleanContext(node *shimast.Node) bool {
47
+ cur := node
48
+ for cur != nil && cur.Parent != nil && cur.Parent.Kind == shimast.KindParenthesizedExpression {
49
+ cur = cur.Parent
50
+ }
51
+ if cur == nil {
52
+ return false
53
+ }
54
+ parent := cur.Parent
55
+ if parent == nil {
56
+ return false
57
+ }
58
+ switch parent.Kind {
59
+ case shimast.KindIfStatement:
60
+ return parent.AsIfStatement().Expression == cur
61
+ case shimast.KindWhileStatement:
62
+ return parent.AsWhileStatement().Expression == cur
63
+ case shimast.KindDoStatement:
64
+ return parent.AsDoStatement().Expression == cur
65
+ case shimast.KindForStatement:
66
+ return parent.AsForStatement().Condition == cur
67
+ case shimast.KindConditionalExpression:
68
+ return parent.AsConditionalExpression().Condition == cur
69
+ case shimast.KindPrefixUnaryExpression:
70
+ return parent.AsPrefixUnaryExpression().Operator == shimast.KindExclamationToken
71
+ case shimast.KindBinaryExpression:
72
+ bin := parent.AsBinaryExpression()
73
+ if bin == nil || bin.OperatorToken == nil {
74
+ return false
75
+ }
76
+ switch bin.OperatorToken.Kind {
77
+ case shimast.KindAmpersandAmpersandToken,
78
+ shimast.KindBarBarToken,
79
+ shimast.KindQuestionQuestionToken:
80
+ return true
81
+ }
82
+ }
83
+ return false
84
+ }
85
+
86
+ func init() {
87
+ Register(unicornExplicitLengthCheck{})
88
+ }
@@ -0,0 +1,29 @@
1
+ // unicorn/filename-case: enforces a single case convention (kebab,
2
+ // camel, snake, or pascal) on every source file name. The MVP target
3
+ // would be kebab-case, but the in-tree test fixture for this rule
4
+ // lives at `tests/test-lint/src/cases/unicorn-filename-case.ts` —
5
+ // which is already kebab-case — so the rule would never fire on its
6
+ // own fixture and the corpus test would have no positive case to
7
+ // assert on. A proper port also needs a way to influence the
8
+ // fixture's virtual filename from the harness, which is not exposed
9
+ // today.
10
+ //
11
+ // Registered as a no-op stub to keep
12
+ // `TestTypedKeysMatchRegisteredRules` aligned with the typed
13
+ // `ITtscLintUnicornRules` surface. The fixture keeps its
14
+ // `@ttsc-corpus-skip` directive.
15
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/filename-case.md
16
+ package linthost
17
+
18
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
19
+
20
+ type unicornFilenameCase struct{}
21
+
22
+ func (unicornFilenameCase) Name() string { return "unicorn/filename-case" }
23
+ func (unicornFilenameCase) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindSourceFile} }
24
+ func (unicornFilenameCase) Check(_ *Context, _ *shimast.Node) {
25
+ }
26
+
27
+ func init() {
28
+ Register(unicornFilenameCase{})
29
+ }
@@ -0,0 +1,28 @@
1
+ // unicorn/import-style: forbids named or default imports from configured
2
+ // modules so that, for example, `path` is always imported as the
3
+ // namespace `path` and never destructured. The rule's behavior is
4
+ // entirely driven by a per-module configuration map
5
+ // (`styles: { foo: { default: false, namespace: true } }`). Without that
6
+ // configuration plumbing landing in the host's rule-options pipeline,
7
+ // the rule has no defaults to enforce, so it is registered as a no-op
8
+ // stub to keep `TestTypedKeysMatchRegisteredRules` aligned with the
9
+ // typed `ITtscLintUnicornRules` surface.
10
+ //
11
+ // The matching fixture under
12
+ // `tests/test-lint/src/cases/unicorn-import-style.ts` keeps its
13
+ // `@ttsc-corpus-skip` directive until the configuration plumbing lands.
14
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/import-style.md
15
+ package linthost
16
+
17
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
18
+
19
+ type unicornImportStyle struct{}
20
+
21
+ func (unicornImportStyle) Name() string { return "unicorn/import-style" }
22
+ func (unicornImportStyle) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindSourceFile} }
23
+ func (unicornImportStyle) Check(_ *Context, _ *shimast.Node) {
24
+ }
25
+
26
+ func init() {
27
+ Register(unicornImportStyle{})
28
+ }
@@ -0,0 +1,29 @@
1
+ // unicorn/isolated-functions: flags function expressions that "escape"
2
+ // their lexical closure unintentionally — e.g. an inner function that
3
+ // references no outer binding but is still placed at the inner scope.
4
+ // Correctly identifying "isolated function" context requires scope
5
+ // analysis tracking what each nested function captures, which is not
6
+ // available in the AST-only slice of this port.
7
+ //
8
+ // Registered as a no-op stub to keep
9
+ // `TestTypedKeysMatchRegisteredRules` aligned with the typed
10
+ // `ITtscLintUnicornRules` surface. The matching fixture under
11
+ // `tests/test-lint/src/cases/unicorn-isolated-functions.ts` keeps its
12
+ // `@ttsc-corpus-skip` directive.
13
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/isolated-functions.md
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ type unicornIsolatedFunctions struct{}
19
+
20
+ func (unicornIsolatedFunctions) Name() string { return "unicorn/isolated-functions" }
21
+ func (unicornIsolatedFunctions) Visits() []shimast.Kind {
22
+ return []shimast.Kind{shimast.KindSourceFile}
23
+ }
24
+ func (unicornIsolatedFunctions) Check(_ *Context, _ *shimast.Node) {
25
+ }
26
+
27
+ func init() {
28
+ Register(unicornIsolatedFunctions{})
29
+ }
@@ -0,0 +1,87 @@
1
+ // unicorn/new-for-builtins: built-in globals split into two groups for
2
+ // constructor etiquette. Primitive wrappers (`String`, `Number`, …) must
3
+ // be called WITHOUT `new` because the wrapper-object form is a footgun
4
+ // — `new String("x") instanceof Object` is true but `"x" instanceof
5
+ // Object` is false, and the wrapper form does not unify with the
6
+ // primitive in equality comparisons. Container constructors (`Array`,
7
+ // `Error`, `Map`, …) must be called WITH `new` because the call form
8
+ // either misbehaves (`Array(3)` allocates a sparse 3-slot array) or is
9
+ // outright invalid (`Error()` still works but is style-inconsistent).
10
+ //
11
+ // AST-only: visit both `NewExpression` and `CallExpression`. The
12
+ // callee-identifier text is matched against the corresponding allowlist
13
+ // and reported with the inverted construction message.
14
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/new-for-builtins.md
15
+ package linthost
16
+
17
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
18
+
19
+ // Primitive wrappers — `new` is wrong, call form is required.
20
+ var unicornNewForBuiltinsPrimitiveWrappers = map[string]struct{}{
21
+ "String": {},
22
+ "Number": {},
23
+ "Boolean": {},
24
+ "Symbol": {},
25
+ "BigInt": {},
26
+ }
27
+
28
+ // Container constructors — `new` is required, call form is wrong. Note
29
+ // that `Symbol` is intentionally NOT in this list: `Symbol(...)` is the
30
+ // correct primitive-wrapper call and must not be flagged.
31
+ var unicornNewForBuiltinsContainers = map[string]struct{}{
32
+ "Array": {},
33
+ "Error": {},
34
+ "EvalError": {},
35
+ "RangeError": {},
36
+ "ReferenceError": {},
37
+ "SyntaxError": {},
38
+ "TypeError": {},
39
+ "URIError": {},
40
+ "AggregateError": {},
41
+ "Object": {},
42
+ "Map": {},
43
+ "Set": {},
44
+ "WeakMap": {},
45
+ "WeakSet": {},
46
+ "Date": {},
47
+ "RegExp": {},
48
+ }
49
+
50
+ type unicornNewForBuiltins struct{}
51
+
52
+ func (unicornNewForBuiltins) Name() string { return "unicorn/new-for-builtins" }
53
+ func (unicornNewForBuiltins) Visits() []shimast.Kind {
54
+ return []shimast.Kind{shimast.KindNewExpression, shimast.KindCallExpression}
55
+ }
56
+ func (unicornNewForBuiltins) Check(ctx *Context, node *shimast.Node) {
57
+ switch node.Kind {
58
+ case shimast.KindNewExpression:
59
+ ne := node.AsNewExpression()
60
+ if ne == nil {
61
+ return
62
+ }
63
+ name := identifierText(ne.Expression)
64
+ if name == "" {
65
+ return
66
+ }
67
+ if _, ok := unicornNewForBuiltinsPrimitiveWrappers[name]; ok {
68
+ ctx.Report(node, "Don't use `new "+name+"(...)` with a primitive wrapper like `"+name+"`.")
69
+ }
70
+ case shimast.KindCallExpression:
71
+ call := node.AsCallExpression()
72
+ if call == nil {
73
+ return
74
+ }
75
+ name := identifierText(call.Expression)
76
+ if name == "" {
77
+ return
78
+ }
79
+ if _, ok := unicornNewForBuiltinsContainers[name]; ok {
80
+ ctx.Report(node, "Use `new "+name+"(...)` instead of `"+name+"(...)`.")
81
+ }
82
+ }
83
+ }
84
+
85
+ func init() {
86
+ Register(unicornNewForBuiltins{})
87
+ }
@@ -0,0 +1,63 @@
1
+ // unicorn/no-abusive-eslint-disable: a bare `// eslint-disable*` directive
2
+ // with no rule list suppresses every lint rule for the affected scope.
3
+ // That blanket-disable hides unrelated diagnostics the next reviewer would
4
+ // have caught, so the rule requires every `eslint-disable*` directive to
5
+ // name the rules it silences.
6
+ //
7
+ // File-level dispatch: visit `KindSourceFile` once per file, scan the
8
+ // raw source with the tsgo scanner so embedded `/* */` and `//` tokens
9
+ // inside template substitutions and string literals are not mistaken for
10
+ // real comments, and match each comment's stripped body — already trimmed
11
+ // by the shared `stripCommentDelimiters` helper — against
12
+ // `^eslint-disable(?:-next-line|-line)?$`. A match means the directive
13
+ // carries no rule list and is reported on the comment range.
14
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-abusive-eslint-disable.md
15
+ package linthost
16
+
17
+ import (
18
+ "regexp"
19
+
20
+ shimast "github.com/microsoft/typescript-go/shim/ast"
21
+ shimscanner "github.com/microsoft/typescript-go/shim/scanner"
22
+ )
23
+
24
+ var unicornNoAbusiveEslintDisablePattern = regexp.MustCompile(`^eslint-disable(?:-next-line|-line)?$`)
25
+
26
+ type unicornNoAbusiveEslintDisable struct{}
27
+
28
+ func (unicornNoAbusiveEslintDisable) Name() string { return "unicorn/no-abusive-eslint-disable" }
29
+ func (unicornNoAbusiveEslintDisable) Visits() []shimast.Kind {
30
+ return []shimast.Kind{shimast.KindSourceFile}
31
+ }
32
+ func (unicornNoAbusiveEslintDisable) Check(ctx *Context, node *shimast.Node) {
33
+ if ctx.File == nil {
34
+ return
35
+ }
36
+ src := ctx.File.Text()
37
+ scanner := shimscanner.NewScanner()
38
+ scanner.SetText(src)
39
+ scanner.SetSkipTrivia(false)
40
+ for {
41
+ kind := scanner.Scan()
42
+ if kind == shimast.KindEndOfFile {
43
+ break
44
+ }
45
+ if kind != shimast.KindSingleLineCommentTrivia && kind != shimast.KindMultiLineCommentTrivia {
46
+ continue
47
+ }
48
+ start := scanner.TokenStart()
49
+ end := scanner.TokenEnd()
50
+ if start < 0 || end > len(src) || end <= start {
51
+ continue
52
+ }
53
+ body := stripCommentDelimiters(src[start:end])
54
+ if !unicornNoAbusiveEslintDisablePattern.MatchString(body) {
55
+ continue
56
+ }
57
+ ctx.ReportRange(start, end, "Specify the rules to disable in each `eslint-disable*` directive.")
58
+ }
59
+ }
60
+
61
+ func init() {
62
+ Register(unicornNoAbusiveEslintDisable{})
63
+ }