@ttsc/lint 0.13.0 → 0.14.0-dev.20260528

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (467) hide show
  1. package/README.md +948 -69
  2. package/lib/defaultFormat.d.ts +9 -6
  3. package/lib/defaultFormat.js +9 -6
  4. package/lib/defaultFormat.js.map +1 -1
  5. package/lib/index.d.ts +46 -0
  6. package/lib/index.js +60 -37
  7. package/lib/index.js.map +1 -1
  8. package/lib/structures/ITtscLintConfig.d.ts +12 -6
  9. package/lib/structures/{ITtscLintFormatConfig.d.ts → ITtscLintFormat.d.ts} +2 -2
  10. package/lib/structures/{TtscLintRuleMap.js → ITtscLintFormat.js} +1 -1
  11. package/lib/structures/ITtscLintFormat.js.map +1 -0
  12. package/lib/structures/TtscLintRuleSetting.d.ts +49 -0
  13. package/lib/structures/{TtscLintRuleOptions.js → TtscLintRuleSetting.js} +1 -1
  14. package/lib/structures/TtscLintRuleSetting.js.map +1 -0
  15. package/lib/structures/index.d.ts +3 -4
  16. package/lib/structures/index.js +3 -4
  17. package/lib/structures/index.js.map +1 -1
  18. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +104 -0
  19. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +14 -0
  20. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
  21. package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +79 -0
  22. package/lib/structures/rules/ITtscLintBoundariesRules.js +3 -0
  23. package/lib/structures/rules/ITtscLintBoundariesRules.js.map +1 -0
  24. package/lib/structures/rules/ITtscLintContributorRules.d.ts +17 -0
  25. package/lib/structures/rules/ITtscLintContributorRules.js +3 -0
  26. package/lib/structures/rules/ITtscLintContributorRules.js.map +1 -0
  27. package/lib/structures/rules/ITtscLintCoreRules.d.ts +1257 -0
  28. package/lib/structures/{ITtscLintFormatConfig.js → rules/ITtscLintCoreRules.js} +1 -1
  29. package/lib/structures/rules/ITtscLintCoreRules.js.map +1 -0
  30. package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +17 -0
  31. package/lib/structures/rules/ITtscLintCypressRuleOptions.js +10 -0
  32. package/lib/structures/rules/ITtscLintCypressRuleOptions.js.map +1 -0
  33. package/lib/structures/rules/ITtscLintCypressRules.d.ts +129 -0
  34. package/lib/structures/rules/ITtscLintCypressRules.js +3 -0
  35. package/lib/structures/rules/ITtscLintCypressRules.js.map +1 -0
  36. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +157 -0
  37. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +13 -0
  38. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js.map +1 -0
  39. package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +167 -0
  40. package/lib/structures/rules/ITtscLintFunctionalRules.js +3 -0
  41. package/lib/structures/rules/ITtscLintFunctionalRules.js.map +1 -0
  42. package/lib/structures/rules/ITtscLintJestRules.d.ts +201 -0
  43. package/lib/structures/rules/ITtscLintJestRules.js +3 -0
  44. package/lib/structures/rules/ITtscLintJestRules.js.map +1 -0
  45. package/lib/structures/rules/ITtscLintJsdocRules.d.ts +140 -0
  46. package/lib/structures/rules/ITtscLintJsdocRules.js +3 -0
  47. package/lib/structures/rules/ITtscLintJsdocRules.js.map +1 -0
  48. package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +302 -0
  49. package/lib/structures/rules/ITtscLintJsxA11yRules.js +3 -0
  50. package/lib/structures/rules/ITtscLintJsxA11yRules.js.map +1 -0
  51. package/lib/structures/rules/ITtscLintNextjsRules.d.ts +185 -0
  52. package/lib/structures/rules/ITtscLintNextjsRules.js +3 -0
  53. package/lib/structures/rules/ITtscLintNextjsRules.js.map +1 -0
  54. package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +330 -0
  55. package/lib/structures/rules/ITtscLintPlaywrightRules.js +3 -0
  56. package/lib/structures/rules/ITtscLintPlaywrightRules.js.map +1 -0
  57. package/lib/structures/rules/ITtscLintPromiseRules.d.ts +188 -0
  58. package/lib/structures/rules/ITtscLintPromiseRules.js +3 -0
  59. package/lib/structures/rules/ITtscLintPromiseRules.js.map +1 -0
  60. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +18 -0
  61. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js +8 -0
  62. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js.map +1 -0
  63. package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +51 -0
  64. package/lib/structures/rules/ITtscLintReactPerfRules.js +3 -0
  65. package/lib/structures/rules/ITtscLintReactPerfRules.js.map +1 -0
  66. package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +39 -0
  67. package/lib/structures/rules/ITtscLintReactRuleOptions.js +12 -0
  68. package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
  69. package/lib/structures/rules/ITtscLintReactRules.d.ts +289 -0
  70. package/lib/structures/rules/ITtscLintReactRules.js +3 -0
  71. package/lib/structures/rules/ITtscLintReactRules.js.map +1 -0
  72. package/lib/structures/rules/ITtscLintRegexpRules.d.ts +190 -0
  73. package/lib/structures/rules/ITtscLintRegexpRules.js +3 -0
  74. package/lib/structures/rules/ITtscLintRegexpRules.js.map +1 -0
  75. package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +66 -0
  76. package/lib/structures/rules/ITtscLintRuleOptionsMap.js +3 -0
  77. package/lib/structures/rules/ITtscLintRuleOptionsMap.js.map +1 -0
  78. package/lib/structures/rules/ITtscLintRules.d.ts +55 -0
  79. package/lib/structures/{TtscLintRule.js → rules/ITtscLintRules.js} +1 -1
  80. package/lib/structures/rules/ITtscLintRules.js.map +1 -0
  81. package/lib/structures/rules/ITtscLintSecurityRules.d.ts +148 -0
  82. package/lib/structures/rules/ITtscLintSecurityRules.js +3 -0
  83. package/lib/structures/rules/ITtscLintSecurityRules.js.map +1 -0
  84. package/lib/structures/rules/ITtscLintSolidRules.d.ts +181 -0
  85. package/lib/structures/rules/ITtscLintSolidRules.js +3 -0
  86. package/lib/structures/rules/ITtscLintSolidRules.js.map +1 -0
  87. package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +21 -0
  88. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js +9 -0
  89. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js.map +1 -0
  90. package/lib/structures/rules/ITtscLintStorybookRules.d.ts +174 -0
  91. package/lib/structures/rules/ITtscLintStorybookRules.js +3 -0
  92. package/lib/structures/rules/ITtscLintStorybookRules.js.map +1 -0
  93. package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +94 -0
  94. package/lib/structures/rules/ITtscLintTanstackQueryRules.js +3 -0
  95. package/lib/structures/rules/ITtscLintTanstackQueryRules.js.map +1 -0
  96. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +22 -0
  97. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js +10 -0
  98. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js.map +1 -0
  99. package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +310 -0
  100. package/lib/structures/rules/ITtscLintTestingLibraryRules.js +3 -0
  101. package/lib/structures/rules/ITtscLintTestingLibraryRules.js.map +1 -0
  102. package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +1132 -0
  103. package/lib/structures/rules/ITtscLintTypeScriptRules.js +3 -0
  104. package/lib/structures/rules/ITtscLintTypeScriptRules.js.map +1 -0
  105. package/lib/structures/rules/ITtscLintUnicornRules.d.ts +997 -0
  106. package/lib/structures/rules/ITtscLintUnicornRules.js +3 -0
  107. package/lib/structures/rules/ITtscLintUnicornRules.js.map +1 -0
  108. package/lib/structures/rules/ITtscLintVitestRules.d.ts +141 -0
  109. package/lib/structures/rules/ITtscLintVitestRules.js +3 -0
  110. package/lib/structures/rules/ITtscLintVitestRules.js.map +1 -0
  111. package/lib/structures/rules/index.d.ts +31 -0
  112. package/lib/structures/rules/index.js +48 -0
  113. package/lib/structures/rules/index.js.map +1 -0
  114. package/linthost/ast_helpers.go +30 -5
  115. package/linthost/compile.go +33 -2
  116. package/linthost/config.go +48 -17
  117. package/linthost/config_format.go +9 -9
  118. package/linthost/directives.go +67 -25
  119. package/linthost/dispatch.go +14 -3
  120. package/linthost/engine.go +160 -40
  121. package/linthost/fix.go +2 -2
  122. package/linthost/flags_gen.go +17 -15
  123. package/linthost/host.go +40 -3
  124. package/linthost/lsp.go +747 -0
  125. package/linthost/print_dispatch.go +2 -2
  126. package/linthost/print_nodes_function.go +2 -2
  127. package/linthost/print_nodes_object.go +1 -1
  128. package/linthost/rule_names.go +14 -0
  129. package/linthost/rules_arrays.go +2 -2
  130. package/linthost/rules_boundaries.go +532 -0
  131. package/linthost/rules_camelcase.go +133 -0
  132. package/linthost/rules_complexity.go +94 -0
  133. package/linthost/rules_consistent_return.go +130 -0
  134. package/linthost/rules_console.go +1 -1
  135. package/linthost/rules_core_extra.go +739 -0
  136. package/linthost/rules_curly.go +70 -0
  137. package/linthost/rules_cypress.go +608 -0
  138. package/linthost/rules_debugger.go +2 -2
  139. package/linthost/rules_default_case.go +39 -0
  140. package/linthost/rules_default_case_last.go +46 -0
  141. package/linthost/rules_dupes.go +3 -3
  142. package/linthost/rules_empty.go +3 -3
  143. package/linthost/rules_escape.go +44 -24
  144. package/linthost/rules_eval.go +2 -2
  145. package/linthost/rules_finally.go +2 -2
  146. package/linthost/rules_format_jsdoc.go +1 -1
  147. package/linthost/rules_format_print_width.go +9 -9
  148. package/linthost/rules_format_quotes.go +1 -1
  149. package/linthost/rules_format_semi.go +1 -1
  150. package/linthost/rules_format_sort_imports.go +1 -1
  151. package/linthost/rules_format_trailing_comma.go +1 -1
  152. package/linthost/rules_functional.go +967 -0
  153. package/linthost/rules_gap.go +24 -45
  154. package/linthost/rules_grouped_accessor_pairs.go +87 -0
  155. package/linthost/rules_guard_for_in.go +198 -0
  156. package/linthost/rules_id_length.go +77 -0
  157. package/linthost/rules_imports.go +70 -2
  158. package/linthost/rules_init_declarations.go +53 -0
  159. package/linthost/rules_jest.go +618 -0
  160. package/linthost/rules_jsdoc.go +502 -0
  161. package/linthost/rules_jsx_a11y.go +1264 -0
  162. package/linthost/rules_logic.go +12 -12
  163. package/linthost/rules_loops.go +1 -1
  164. package/linthost/rules_max_classes_per_file.go +58 -0
  165. package/linthost/rules_max_depth.go +83 -0
  166. package/linthost/rules_max_lines.go +101 -0
  167. package/linthost/rules_max_lines_per_function.go +57 -0
  168. package/linthost/rules_max_nested_callbacks.go +61 -0
  169. package/linthost/rules_max_params.go +49 -0
  170. package/linthost/rules_max_statements.go +59 -0
  171. package/linthost/rules_misc.go +1 -1
  172. package/linthost/rules_nextjs.go +697 -0
  173. package/linthost/rules_no_else_return.go +75 -0
  174. package/linthost/rules_no_empty_named_blocks.go +91 -0
  175. package/linthost/rules_no_extend_native.go +51 -0
  176. package/linthost/rules_no_import_assign.go +140 -0
  177. package/linthost/rules_no_invalid_this.go +52 -0
  178. package/linthost/rules_no_loop_func.go +85 -0
  179. package/linthost/rules_no_magic_numbers.go +123 -0
  180. package/linthost/rules_no_mixed_operators.go +80 -0
  181. package/linthost/rules_no_param_reassign.go +98 -0
  182. package/linthost/rules_no_redeclare.go +270 -0
  183. package/linthost/rules_no_restricted_imports.go +105 -0
  184. package/linthost/rules_no_restricted_syntax.go +49 -0
  185. package/linthost/rules_no_shadow.go +147 -0
  186. package/linthost/rules_no_unreachable.go +77 -0
  187. package/linthost/rules_no_useless_assignment.go +120 -0
  188. package/linthost/rules_no_useless_constructor.go +245 -0
  189. package/linthost/rules_no_useless_return.go +51 -0
  190. package/linthost/rules_params.go +1 -1
  191. package/linthost/rules_playwright.go +788 -0
  192. package/linthost/rules_prefer_arrow_callback.go +124 -0
  193. package/linthost/rules_prefer_destructuring.go +98 -0
  194. package/linthost/rules_prefer_named_capture_group.go +129 -0
  195. package/linthost/rules_prefer_rest_params.go +94 -0
  196. package/linthost/rules_problems.go +41 -30
  197. package/linthost/rules_promise.go +1128 -73
  198. package/linthost/rules_protos.go +2 -2
  199. package/linthost/rules_react.go +773 -0
  200. package/linthost/rules_react_extras.go +227 -0
  201. package/linthost/rules_react_hooks.go +848 -0
  202. package/linthost/rules_react_perf.go +293 -0
  203. package/linthost/rules_react_refresh.go +583 -0
  204. package/linthost/rules_regexp.go +410 -0
  205. package/linthost/rules_security.go +830 -0
  206. package/linthost/rules_self.go +2 -2
  207. package/linthost/rules_solid.go +1073 -0
  208. package/linthost/rules_sort_imports.go +69 -0
  209. package/linthost/rules_sort_keys.go +134 -0
  210. package/linthost/rules_storybook.go +1176 -0
  211. package/linthost/rules_strings.go +4 -4
  212. package/linthost/rules_suggestions.go +38 -38
  213. package/linthost/rules_tanstack_query.go +844 -0
  214. package/linthost/rules_testing_library.go +1204 -0
  215. package/linthost/rules_throw.go +1 -1
  216. package/linthost/rules_ts.go +19 -19
  217. package/linthost/rules_ts_async.go +399 -0
  218. package/linthost/rules_ts_class_literal_property_style.go +115 -0
  219. package/linthost/rules_ts_consistent_type_exports.go +256 -0
  220. package/linthost/rules_ts_explicit_function_return_type.go +67 -0
  221. package/linthost/rules_ts_extra.go +155 -36
  222. package/linthost/rules_ts_no_base_to_string.go +218 -0
  223. package/linthost/rules_ts_no_confusing_void.go +72 -0
  224. package/linthost/rules_ts_no_deprecated.go +195 -0
  225. package/linthost/rules_ts_no_for_in_array.go +84 -0
  226. package/linthost/rules_ts_no_magic_numbers.go +124 -0
  227. package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
  228. package/linthost/rules_ts_no_misused_spread.go +104 -0
  229. package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
  230. package/linthost/rules_ts_no_restricted_types.go +62 -0
  231. package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
  232. package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
  233. package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
  234. package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
  235. package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
  236. package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
  237. package/linthost/rules_ts_no_unsafe_argument.go +82 -0
  238. package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
  239. package/linthost/rules_ts_no_unsafe_call.go +82 -0
  240. package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
  241. package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
  242. package/linthost/rules_ts_no_unsafe_return.go +126 -0
  243. package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
  244. package/linthost/rules_ts_no_useless_constructor.go +52 -0
  245. package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
  246. package/linthost/rules_ts_parameter_properties.go +38 -0
  247. package/linthost/rules_ts_prefer_find.go +178 -0
  248. package/linthost/rules_ts_prefer_includes.go +255 -0
  249. package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
  250. package/linthost/rules_ts_prefer_optional_chain.go +228 -0
  251. package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
  252. package/linthost/rules_ts_prefer_readonly.go +73 -0
  253. package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
  254. package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
  255. package/linthost/rules_ts_prefer_return_this_type.go +135 -0
  256. package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
  257. package/linthost/rules_ts_promise_function_async.go +77 -0
  258. package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
  259. package/linthost/rules_ts_require_array_sort_compare.go +96 -0
  260. package/linthost/rules_ts_restrict_plus_operands.go +127 -0
  261. package/linthost/rules_ts_restrict_template_expressions.go +95 -0
  262. package/linthost/rules_ts_simple.go +387 -0
  263. package/linthost/rules_ts_sort_type_constituents.go +144 -0
  264. package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
  265. package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
  266. package/linthost/rules_ts_unbound_method.go +126 -0
  267. package/linthost/rules_tsdoc.go +136 -0
  268. package/linthost/rules_unicorn_better_regex.go +27 -0
  269. package/linthost/rules_unicorn_catch_error_name.go +46 -0
  270. package/linthost/rules_unicorn_consistent_assert.go +47 -0
  271. package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
  272. package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
  273. package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
  274. package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
  275. package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
  276. package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
  277. package/linthost/rules_unicorn_custom_error_definition.go +138 -0
  278. package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
  279. package/linthost/rules_unicorn_error_message.go +64 -0
  280. package/linthost/rules_unicorn_escape_case.go +51 -0
  281. package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
  282. package/linthost/rules_unicorn_explicit_length_check.go +88 -0
  283. package/linthost/rules_unicorn_filename_case.go +29 -0
  284. package/linthost/rules_unicorn_import_style.go +28 -0
  285. package/linthost/rules_unicorn_isolated_functions.go +29 -0
  286. package/linthost/rules_unicorn_new_for_builtins.go +87 -0
  287. package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
  288. package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
  289. package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
  290. package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
  291. package/linthost/rules_unicorn_no_array_for_each.go +40 -0
  292. package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
  293. package/linthost/rules_unicorn_no_array_reduce.go +41 -0
  294. package/linthost/rules_unicorn_no_array_reverse.go +44 -0
  295. package/linthost/rules_unicorn_no_array_sort.go +43 -0
  296. package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
  297. package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
  298. package/linthost/rules_unicorn_no_console_spaces.go +61 -0
  299. package/linthost/rules_unicorn_no_document_cookie.go +41 -0
  300. package/linthost/rules_unicorn_no_empty_file.go +44 -0
  301. package/linthost/rules_unicorn_no_for_loop.go +102 -0
  302. package/linthost/rules_unicorn_no_hex_escape.go +42 -0
  303. package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
  304. package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
  305. package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
  306. package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
  307. package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
  308. package/linthost/rules_unicorn_no_lonely_if.go +44 -0
  309. package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
  310. package/linthost/rules_unicorn_no_named_default.go +54 -0
  311. package/linthost/rules_unicorn_no_negated_condition.go +85 -0
  312. package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
  313. package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
  314. package/linthost/rules_unicorn_no_new_array.go +30 -0
  315. package/linthost/rules_unicorn_no_new_buffer.go +31 -0
  316. package/linthost/rules_unicorn_no_null.go +24 -0
  317. package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
  318. package/linthost/rules_unicorn_no_process_exit.go +43 -0
  319. package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
  320. package/linthost/rules_unicorn_no_static_only_class.go +56 -0
  321. package/linthost/rules_unicorn_no_thenable.go +74 -0
  322. package/linthost/rules_unicorn_no_this_assignment.go +35 -0
  323. package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
  324. package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
  325. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
  326. package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
  327. package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
  328. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
  329. package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
  330. package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
  331. package/linthost/rules_unicorn_no_unused_properties.go +30 -0
  332. package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
  333. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
  334. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
  335. package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
  336. package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
  337. package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
  338. package/linthost/rules_unicorn_no_useless_spread.go +67 -0
  339. package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
  340. package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
  341. package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
  342. package/linthost/rules_unicorn_number_literal_case.go +69 -0
  343. package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
  344. package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
  345. package/linthost/rules_unicorn_prefer_array_find.go +51 -0
  346. package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
  347. package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
  348. package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
  349. package/linthost/rules_unicorn_prefer_array_some.go +67 -0
  350. package/linthost/rules_unicorn_prefer_at.go +77 -0
  351. package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
  352. package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
  353. package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
  354. package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
  355. package/linthost/rules_unicorn_prefer_code_point.go +49 -0
  356. package/linthost/rules_unicorn_prefer_date_now.go +78 -0
  357. package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
  358. package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
  359. package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
  360. package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
  361. package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
  362. package/linthost/rules_unicorn_prefer_event_target.go +36 -0
  363. package/linthost/rules_unicorn_prefer_export_from.go +129 -0
  364. package/linthost/rules_unicorn_prefer_global_this.go +127 -0
  365. package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
  366. package/linthost/rules_unicorn_prefer_includes.go +149 -0
  367. package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
  368. package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
  369. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
  370. package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
  371. package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
  372. package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
  373. package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
  374. package/linthost/rules_unicorn_prefer_module.go +50 -0
  375. package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
  376. package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
  377. package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
  378. package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
  379. package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
  380. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
  381. package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
  382. package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
  383. package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
  384. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
  385. package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
  386. package/linthost/rules_unicorn_prefer_set_has.go +42 -0
  387. package/linthost/rules_unicorn_prefer_set_size.go +48 -0
  388. package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
  389. package/linthost/rules_unicorn_prefer_single_call.go +96 -0
  390. package/linthost/rules_unicorn_prefer_spread.go +51 -0
  391. package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
  392. package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
  393. package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
  394. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
  395. package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
  396. package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
  397. package/linthost/rules_unicorn_prefer_switch.go +103 -0
  398. package/linthost/rules_unicorn_prefer_ternary.go +71 -0
  399. package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
  400. package/linthost/rules_unicorn_prefer_type_error.go +127 -0
  401. package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
  402. package/linthost/rules_unicorn_relative_url_style.go +49 -0
  403. package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
  404. package/linthost/rules_unicorn_require_module_attributes.go +54 -0
  405. package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
  406. package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
  407. package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
  408. package/linthost/rules_unicorn_string_content.go +27 -0
  409. package/linthost/rules_unicorn_switch_case_braces.go +42 -0
  410. package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
  411. package/linthost/rules_unicorn_template_indent.go +28 -0
  412. package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
  413. package/linthost/rules_unicorn_throw_new_error.go +61 -0
  414. package/linthost/rules_var.go +10 -4
  415. package/linthost/rules_vitest.go +568 -0
  416. package/package.json +3 -3
  417. package/plugin/main.go +49 -3
  418. package/rule/astutil/astutil.go +10 -3
  419. package/rule/rule.go +12 -10
  420. package/src/defaultFormat.ts +11 -8
  421. package/src/index.ts +65 -43
  422. package/src/structures/ITtscLintConfig.ts +12 -6
  423. package/src/structures/{ITtscLintFormatConfig.ts → ITtscLintFormat.ts} +2 -2
  424. package/src/structures/TtscLintRuleSetting.ts +55 -0
  425. package/src/structures/index.ts +3 -4
  426. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +128 -0
  427. package/src/structures/rules/ITtscLintBoundariesRules.ts +95 -0
  428. package/src/structures/rules/ITtscLintContributorRules.ts +21 -0
  429. package/src/structures/rules/ITtscLintCoreRules.ts +1406 -0
  430. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
  431. package/src/structures/rules/ITtscLintCypressRules.ts +145 -0
  432. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +213 -0
  433. package/src/structures/rules/ITtscLintFunctionalRules.ts +202 -0
  434. package/src/structures/rules/ITtscLintJestRules.ts +220 -0
  435. package/src/structures/rules/ITtscLintJsdocRules.ts +153 -0
  436. package/src/structures/rules/ITtscLintJsxA11yRules.ts +339 -0
  437. package/src/structures/rules/ITtscLintNextjsRules.ts +206 -0
  438. package/src/structures/rules/ITtscLintPlaywrightRules.ts +361 -0
  439. package/src/structures/rules/ITtscLintPromiseRules.ts +205 -0
  440. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
  441. package/src/structures/rules/ITtscLintReactPerfRules.ts +55 -0
  442. package/src/structures/rules/ITtscLintReactRuleOptions.ts +43 -0
  443. package/src/structures/rules/ITtscLintReactRules.ts +321 -0
  444. package/src/structures/rules/ITtscLintRegexpRules.ts +212 -0
  445. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +89 -0
  446. package/src/structures/rules/ITtscLintRules.ts +77 -0
  447. package/src/structures/rules/ITtscLintSecurityRules.ts +162 -0
  448. package/src/structures/rules/ITtscLintSolidRules.ts +202 -0
  449. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +23 -0
  450. package/src/structures/rules/ITtscLintStorybookRules.ts +193 -0
  451. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +102 -0
  452. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +24 -0
  453. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +342 -0
  454. package/src/structures/rules/ITtscLintTypeScriptRules.ts +1230 -0
  455. package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
  456. package/src/structures/rules/ITtscLintVitestRules.ts +154 -0
  457. package/src/structures/rules/index.ts +31 -0
  458. package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
  459. package/lib/structures/TtscLintRule.d.ts +0 -17
  460. package/lib/structures/TtscLintRule.js.map +0 -1
  461. package/lib/structures/TtscLintRuleMap.d.ts +0 -46
  462. package/lib/structures/TtscLintRuleMap.js.map +0 -1
  463. package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
  464. package/lib/structures/TtscLintRuleOptions.js.map +0 -1
  465. package/src/structures/TtscLintRule.ts +0 -160
  466. package/src/structures/TtscLintRuleMap.ts +0 -55
  467. package/src/structures/TtscLintRuleOptions.ts +0 -151
@@ -13,7 +13,7 @@ import (
13
13
  shimscanner "github.com/microsoft/typescript-go/shim/scanner"
14
14
  )
15
15
 
16
- // no-empty-static-block: `class C { static {} }` has no effect.
16
+ // noEmptyStaticBlock: `class C { static {} }` has no effect.
17
17
  // ESLint recommended: https://eslint.org/docs/latest/rules/no-empty-static-block
18
18
  type noEmptyStaticBlock struct{}
19
19
 
@@ -32,7 +32,7 @@ func (noEmptyStaticBlock) Check(ctx *Context, node *shimast.Node) {
32
32
  }
33
33
  }
34
34
 
35
- // no-setter-return: setters must not return a value.
35
+ // noSetterReturn: setters must not return a value.
36
36
  // ESLint recommended: https://eslint.org/docs/latest/rules/no-setter-return
37
37
  type noSetterReturn struct{}
38
38
 
@@ -61,7 +61,7 @@ func isInsideDirectSetter(node *shimast.Node) bool {
61
61
  return false
62
62
  }
63
63
 
64
- // no-unused-labels: a label is useful only when a break/continue targets it.
64
+ // noUnusedLabels: a label is useful only when a break/continue targets it.
65
65
  // ESLint recommended: https://eslint.org/docs/latest/rules/no-unused-labels
66
66
  type noUnusedLabels struct{}
67
67
 
@@ -95,11 +95,11 @@ func (noUnusedLabels) Check(ctx *Context, node *shimast.Node) {
95
95
  }
96
96
  }
97
97
 
98
- // no-dynamic-delete: avoid deleting properties through dynamic keys.
98
+ // noDynamicDelete: avoid deleting properties through dynamic keys.
99
99
  // typescript-eslint strict: https://typescript-eslint.io/rules/no-dynamic-delete/
100
100
  type noDynamicDelete struct{}
101
101
 
102
- func (noDynamicDelete) Name() string { return "no-dynamic-delete" }
102
+ func (noDynamicDelete) Name() string { return "typescript/no-dynamic-delete" }
103
103
  func (noDynamicDelete) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindDeleteExpression} }
104
104
  func (noDynamicDelete) Check(ctx *Context, node *shimast.Node) {
105
105
  del := node.AsDeleteExpression()
@@ -114,7 +114,7 @@ func (noDynamicDelete) Check(ctx *Context, node *shimast.Node) {
114
114
  }
115
115
 
116
116
  // isStaticPropertyKey reports whether node is a literal key that can
117
- // appear in a delete expression without triggering no-dynamic-delete:
117
+ // appear in a delete expression without triggering noDynamicDelete:
118
118
  // string literals, no-substitution template literals, and numeric literals.
119
119
  func isStaticPropertyKey(node *shimast.Node) bool {
120
120
  node = stripParens(node)
@@ -130,12 +130,12 @@ func isStaticPropertyKey(node *shimast.Node) bool {
130
130
  return false
131
131
  }
132
132
 
133
- // no-non-null-asserted-nullish-coalescing: `foo! ?? bar` is contradictory.
133
+ // noNonNullAssertedNullishCoalescing: `foo! ?? bar` is contradictory.
134
134
  // typescript-eslint strict: https://typescript-eslint.io/rules/no-non-null-asserted-nullish-coalescing/
135
135
  type noNonNullAssertedNullishCoalescing struct{}
136
136
 
137
137
  func (noNonNullAssertedNullishCoalescing) Name() string {
138
- return "no-non-null-asserted-nullish-coalescing"
138
+ return "typescript/no-non-null-asserted-nullish-coalescing"
139
139
  }
140
140
  func (noNonNullAssertedNullishCoalescing) Visits() []shimast.Kind {
141
141
  return []shimast.Kind{shimast.KindBinaryExpression}
@@ -153,11 +153,11 @@ func (noNonNullAssertedNullishCoalescing) Check(ctx *Context, node *shimast.Node
153
153
  }
154
154
  }
155
155
 
156
- // no-unnecessary-type-constraint: `<T extends any>` / `<T extends unknown>`.
156
+ // noUnnecessaryTypeConstraint: `<T extends any>` / `<T extends unknown>`.
157
157
  // typescript-eslint recommended: https://typescript-eslint.io/rules/no-unnecessary-type-constraint/
158
158
  type noUnnecessaryTypeConstraint struct{}
159
159
 
160
- func (noUnnecessaryTypeConstraint) Name() string { return "no-unnecessary-type-constraint" }
160
+ func (noUnnecessaryTypeConstraint) Name() string { return "typescript/no-unnecessary-type-constraint" }
161
161
  func (noUnnecessaryTypeConstraint) Visits() []shimast.Kind {
162
162
  return []shimast.Kind{shimast.KindTypeParameter}
163
163
  }
@@ -184,11 +184,11 @@ func (noUnnecessaryTypeConstraint) Check(ctx *Context, node *shimast.Node) {
184
184
  )
185
185
  }
186
186
 
187
- // no-unsafe-function-type: `Function` accepts any callable shape.
187
+ // noUnsafeFunctionType: `Function` accepts any callable shape.
188
188
  // typescript-eslint recommended: https://typescript-eslint.io/rules/no-unsafe-function-type/
189
189
  type noUnsafeFunctionType struct{}
190
190
 
191
- func (noUnsafeFunctionType) Name() string { return "no-unsafe-function-type" }
191
+ func (noUnsafeFunctionType) Name() string { return "typescript/no-unsafe-function-type" }
192
192
  func (noUnsafeFunctionType) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindTypeReference} }
193
193
  func (noUnsafeFunctionType) Check(ctx *Context, node *shimast.Node) {
194
194
  ref := node.AsTypeReferenceNode()
@@ -198,12 +198,12 @@ func (noUnsafeFunctionType) Check(ctx *Context, node *shimast.Node) {
198
198
  ctx.Report(node, "The Function type is unsafe. Use a specific function type instead.")
199
199
  }
200
200
 
201
- // no-wrapper-object-types: prefer primitive type keywords over boxed object
201
+ // noWrapperObjectTypes: prefer primitive type keywords over boxed object
202
202
  // type names such as `String` and `Boolean`.
203
203
  // typescript-eslint recommended: https://typescript-eslint.io/rules/no-wrapper-object-types/
204
204
  type noWrapperObjectTypes struct{}
205
205
 
206
- func (noWrapperObjectTypes) Name() string { return "no-wrapper-object-types" }
206
+ func (noWrapperObjectTypes) Name() string { return "typescript/no-wrapper-object-types" }
207
207
  func (noWrapperObjectTypes) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindTypeReference} }
208
208
  func (noWrapperObjectTypes) Check(ctx *Context, node *shimast.Node) {
209
209
  ref := node.AsTypeReferenceNode()
@@ -301,31 +301,11 @@ func wrapperPrimitive(name string) (string, bool) {
301
301
  return "", false
302
302
  }
303
303
 
304
- // no-useless-constructor: an empty constructor with no parameters is noise.
305
- // typescript-eslint strict: https://typescript-eslint.io/rules/no-useless-constructor/
306
- type noUselessConstructor struct{}
307
-
308
- func (noUselessConstructor) Name() string { return "no-useless-constructor" }
309
- func (noUselessConstructor) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindConstructor} }
310
- func (noUselessConstructor) Check(ctx *Context, node *shimast.Node) {
311
- ctor := node.AsConstructorDeclaration()
312
- if ctor == nil || ctor.Body == nil {
313
- return
314
- }
315
- if len(node.Parameters()) != 0 {
316
- return
317
- }
318
- body := ctor.Body.AsBlock()
319
- if body == nil || body.Statements == nil || len(body.Statements.Nodes) == 0 {
320
- ctx.Report(node, "Useless empty constructor.")
321
- }
322
- }
323
-
324
- // prefer-literal-enum-member: computed enum members are harder to inspect.
304
+ // preferLiteralEnumMember: computed enum members are harder to inspect.
325
305
  // typescript-eslint strict: https://typescript-eslint.io/rules/prefer-literal-enum-member/
326
306
  type preferLiteralEnumMember struct{}
327
307
 
328
- func (preferLiteralEnumMember) Name() string { return "prefer-literal-enum-member" }
308
+ func (preferLiteralEnumMember) Name() string { return "typescript/prefer-literal-enum-member" }
329
309
  func (preferLiteralEnumMember) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindEnumMember} }
330
310
  func (preferLiteralEnumMember) Check(ctx *Context, node *shimast.Node) {
331
311
  member := node.AsEnumMember()
@@ -335,11 +315,11 @@ func (preferLiteralEnumMember) Check(ctx *Context, node *shimast.Node) {
335
315
  ctx.Report(member.Initializer, "Enum member initializer should be a literal value.")
336
316
  }
337
317
 
338
- // consistent-type-assertions: prefer `value as Type` over `<Type>value`.
318
+ // consistentTypeAssertions: prefer `value as Type` over `<Type>value`.
339
319
  // typescript-eslint stylistic: https://typescript-eslint.io/rules/consistent-type-assertions/
340
320
  type consistentTypeAssertions struct{}
341
321
 
342
- func (consistentTypeAssertions) Name() string { return "consistent-type-assertions" }
322
+ func (consistentTypeAssertions) Name() string { return "typescript/consistent-type-assertions" }
343
323
  func (consistentTypeAssertions) Visits() []shimast.Kind {
344
324
  return []shimast.Kind{shimast.KindTypeAssertionExpression}
345
325
  }
@@ -347,12 +327,12 @@ func (consistentTypeAssertions) Check(ctx *Context, node *shimast.Node) {
347
327
  ctx.Report(node, "Use `as` type assertions instead of angle-bracket assertions.")
348
328
  }
349
329
 
350
- // consistent-type-definitions: prefer interfaces for object-shaped public
330
+ // consistentTypeDefinitions: prefer interfaces for object-shaped public
351
331
  // contracts. This mirrors typescript-eslint's default option.
352
332
  // typescript-eslint stylistic: https://typescript-eslint.io/rules/consistent-type-definitions/
353
333
  type consistentTypeDefinitions struct{}
354
334
 
355
- func (consistentTypeDefinitions) Name() string { return "consistent-type-definitions" }
335
+ func (consistentTypeDefinitions) Name() string { return "typescript/consistent-type-definitions" }
356
336
  func (consistentTypeDefinitions) Visits() []shimast.Kind {
357
337
  return []shimast.Kind{shimast.KindTypeAliasDeclaration}
358
338
  }
@@ -364,7 +344,7 @@ func (consistentTypeDefinitions) Check(ctx *Context, node *shimast.Node) {
364
344
  ctx.Report(node, "Use an interface instead of a type literal alias.")
365
345
  }
366
346
 
367
- // dot-notation: `obj["prop"]` should be `obj.prop` when the key is a valid
347
+ // dotNotation: `obj["prop"]` should be `obj.prop` when the key is a valid
368
348
  // identifier.
369
349
  // ESLint canonical: https://eslint.org/docs/latest/rules/dot-notation
370
350
  type dotNotation struct{}
@@ -436,7 +416,7 @@ func isReservedWord(value string) bool {
436
416
 
437
417
  // isSimpleIdentifierName reports whether value is a valid bare identifier
438
418
  // (ASCII letters, digits, underscore, dollar sign; digits not first). Used
439
- // by dot-notation to decide whether bracket access can become dot access.
419
+ // by dotNotation to decide whether bracket access can become dot access.
440
420
  func isSimpleIdentifierName(value string) bool {
441
421
  if value == "" {
442
422
  return false
@@ -453,12 +433,12 @@ func isSimpleIdentifierName(value string) bool {
453
433
  return true
454
434
  }
455
435
 
456
- // no-unsafe-declaration-merging: class/interface merging hides runtime vs type
436
+ // noUnsafeDeclarationMerging: class/interface merging hides runtime vs type
457
437
  // surface differences.
458
438
  // typescript-eslint recommended: https://typescript-eslint.io/rules/no-unsafe-declaration-merging/
459
439
  type noUnsafeDeclarationMerging struct{}
460
440
 
461
- func (noUnsafeDeclarationMerging) Name() string { return "no-unsafe-declaration-merging" }
441
+ func (noUnsafeDeclarationMerging) Name() string { return "typescript/no-unsafe-declaration-merging" }
462
442
  func (noUnsafeDeclarationMerging) Visits() []shimast.Kind {
463
443
  return []shimast.Kind{shimast.KindSourceFile}
464
444
  }
@@ -500,7 +480,6 @@ func init() {
500
480
  Register(noUnsafeDeclarationMerging{})
501
481
  Register(noUnsafeFunctionType{})
502
482
  Register(noWrapperObjectTypes{})
503
- Register(noUselessConstructor{})
504
483
  Register(preferLiteralEnumMember{})
505
484
  Register(consistentTypeAssertions{})
506
485
  Register(consistentTypeDefinitions{})
@@ -0,0 +1,87 @@
1
+ // groupedAccessorPairs: a `get` and `set` accessor that share the same
2
+ // property name should be declared next to each other in the class
3
+ // body. When the pair is split apart by unrelated members, a reader
4
+ // scanning the class has to chase the read and write halves separately
5
+ // — and patches to one half are easy to make without noticing the
6
+ // other.
7
+ //
8
+ // AST-only: walk every class declaration/expression, group members by
9
+ // (name, static-ness), and for any group that contains both a getter
10
+ // and a setter check that their member indices are adjacent. The
11
+ // second-encountered half is the one reported, because the first half
12
+ // reads correctly until the reader hits the second declaration.
13
+ // https://eslint.org/docs/latest/rules/grouped-accessor-pairs
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ type groupedAccessorPairs struct{}
19
+
20
+ func (groupedAccessorPairs) Name() string { return "grouped-accessor-pairs" }
21
+ func (groupedAccessorPairs) Visits() []shimast.Kind {
22
+ return []shimast.Kind{shimast.KindClassDeclaration, shimast.KindClassExpression}
23
+ }
24
+ func (groupedAccessorPairs) Check(ctx *Context, node *shimast.Node) {
25
+ members := classMembers(node)
26
+ if len(members) < 2 {
27
+ return
28
+ }
29
+ type slot struct {
30
+ name string
31
+ static bool
32
+ }
33
+ type entry struct {
34
+ index int
35
+ kind shimast.Kind
36
+ node *shimast.Node
37
+ }
38
+ groups := map[slot][]entry{}
39
+ for i, member := range members {
40
+ if member == nil {
41
+ continue
42
+ }
43
+ if member.Kind != shimast.KindGetAccessor && member.Kind != shimast.KindSetAccessor {
44
+ continue
45
+ }
46
+ name := classMemberName(member)
47
+ if name == "" {
48
+ continue
49
+ }
50
+ key := slot{name: name, static: hasModifier(member, shimast.KindStaticKeyword)}
51
+ groups[key] = append(groups[key], entry{index: i, kind: member.Kind, node: member})
52
+ }
53
+ for _, entries := range groups {
54
+ if len(entries) < 2 {
55
+ continue
56
+ }
57
+ // Find a getter/setter pair within the group.
58
+ var get, set *entry
59
+ for i := range entries {
60
+ e := &entries[i]
61
+ if e.kind == shimast.KindGetAccessor && get == nil {
62
+ get = e
63
+ } else if e.kind == shimast.KindSetAccessor && set == nil {
64
+ set = e
65
+ }
66
+ }
67
+ if get == nil || set == nil {
68
+ continue
69
+ }
70
+ // Adjacent indices in the members list satisfy the rule.
71
+ diff := get.index - set.index
72
+ if diff == 1 || diff == -1 {
73
+ continue
74
+ }
75
+ // Report on whichever half appears later — the earlier one
76
+ // reads fine in isolation; the later one is the surprise.
77
+ later := get
78
+ if set.index > get.index {
79
+ later = set
80
+ }
81
+ ctx.Report(later.node, "Accessor pair should be grouped.")
82
+ }
83
+ }
84
+
85
+ func init() {
86
+ Register(groupedAccessorPairs{})
87
+ }
@@ -0,0 +1,198 @@
1
+ // guardForIn: `for (key in obj)` walks the prototype chain and yields
2
+ // every enumerable name, inherited or own. Most authors only ever care
3
+ // about own keys, so an unguarded body silently leaks work onto
4
+ // prototype-chain entries someone else attached. The canonical guard is
5
+ // `if (Object.hasOwn(obj, key))` or the older
6
+ // `Object.prototype.hasOwnProperty.call(obj, key)`; an inverted-guard
7
+ // `continue` (`if (!Object.hasOwn(...)) continue;`) is the equivalent
8
+ // early-skip shape.
9
+ //
10
+ // Conservative baseline: the rule only inspects the FIRST executable
11
+ // statement of the loop body. The body either opens with a guard
12
+ // covering everything that follows, or it does not — anything more
13
+ // nuanced is the developer's responsibility. The guard expression must
14
+ // reference the loop's own key binding; a hard-coded call on an
15
+ // unrelated identifier is not a real guard.
16
+ // https://eslint.org/docs/latest/rules/guard-for-in
17
+ package linthost
18
+
19
+ import (
20
+ shimast "github.com/microsoft/typescript-go/shim/ast"
21
+ )
22
+
23
+ type guardForIn struct{}
24
+
25
+ func (guardForIn) Name() string { return "guard-for-in" }
26
+ func (guardForIn) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindForInStatement} }
27
+ func (guardForIn) Check(ctx *Context, node *shimast.Node) {
28
+ stmt := node.AsForInOrOfStatement()
29
+ if stmt == nil || stmt.Statement == nil {
30
+ return
31
+ }
32
+ first := firstBodyStatement(stmt.Statement)
33
+ if first == nil {
34
+ return
35
+ }
36
+ key := forInKeyName(stmt.Initializer)
37
+ if isHasOwnGuard(first, key) {
38
+ return
39
+ }
40
+ ctx.Report(node, "The body of a `for...in` should be wrapped in an `if (Object.hasOwn(...))` statement to filter unwanted properties from the prototype.")
41
+ }
42
+
43
+ // firstBodyStatement returns the first executable statement inside a
44
+ // loop body. A block body unwraps to its first statement; a bare
45
+ // non-block body is itself the only statement. Returns nil for an
46
+ // empty block — an empty body cannot leak inherited keys.
47
+ func firstBodyStatement(body *shimast.Node) *shimast.Node {
48
+ if body == nil {
49
+ return nil
50
+ }
51
+ if body.Kind != shimast.KindBlock {
52
+ return body
53
+ }
54
+ block := body.AsBlock()
55
+ if block == nil || block.Statements == nil {
56
+ return nil
57
+ }
58
+ for _, s := range block.Statements.Nodes {
59
+ if s != nil {
60
+ return s
61
+ }
62
+ }
63
+ return nil
64
+ }
65
+
66
+ // forInKeyName extracts the identifier text of the loop key from a
67
+ // `for (… in obj)` initializer. The initializer is either a
68
+ // VariableDeclarationList with one declaration (`for (const key in …)`)
69
+ // or a bare Identifier (`for (key in …)`). Destructuring patterns and
70
+ // other shapes return "" so the rule skips its key-identity check.
71
+ func forInKeyName(init *shimast.Node) string {
72
+ if init == nil {
73
+ return ""
74
+ }
75
+ if name := identifierText(init); name != "" {
76
+ return name
77
+ }
78
+ if init.Kind != shimast.KindVariableDeclarationList {
79
+ return ""
80
+ }
81
+ list := init.AsVariableDeclarationList()
82
+ if list == nil || list.Declarations == nil || len(list.Declarations.Nodes) != 1 {
83
+ return ""
84
+ }
85
+ decl := list.Declarations.Nodes[0]
86
+ if decl == nil {
87
+ return ""
88
+ }
89
+ v := decl.AsVariableDeclaration()
90
+ if v == nil {
91
+ return ""
92
+ }
93
+ return identifierText(v.Name())
94
+ }
95
+
96
+ // isHasOwnGuard reports whether `stmt` is the canonical own-key guard
97
+ // that should open a `for...in` body. Two shapes count:
98
+ //
99
+ // 1. `if (<has-own>(obj, key)) { … }` — positive guard wrapping the
100
+ // real body. The else branch (if any) is allowed because the
101
+ // developer has explicitly handled the inherited-key case.
102
+ // 2. `if (!<has-own>(obj, key)) continue;` — inverted-guard early
103
+ // skip. The then branch must be a single `continue` (with or
104
+ // without a block wrapper) so the rest of the loop body only runs
105
+ // for own keys.
106
+ //
107
+ // `<has-own>` is either `Object.hasOwn(obj, key)` or
108
+ // `Object.prototype.hasOwnProperty.call(obj, key)`. The second
109
+ // argument must match `key` when one was extracted from the
110
+ // initializer; otherwise any second argument is accepted (the rule
111
+ // has no reliable handle on the key name).
112
+ func isHasOwnGuard(stmt *shimast.Node, key string) bool {
113
+ if stmt == nil || stmt.Kind != shimast.KindIfStatement {
114
+ return false
115
+ }
116
+ ifStmt := stmt.AsIfStatement()
117
+ if ifStmt == nil || ifStmt.Expression == nil {
118
+ return false
119
+ }
120
+ cond := stripParens(ifStmt.Expression)
121
+ if cond == nil {
122
+ return false
123
+ }
124
+ if isHasOwnCall(cond, key) {
125
+ return true
126
+ }
127
+ if cond.Kind != shimast.KindPrefixUnaryExpression {
128
+ return false
129
+ }
130
+ pre := cond.AsPrefixUnaryExpression()
131
+ if pre == nil || pre.Operator != shimast.KindExclamationToken {
132
+ return false
133
+ }
134
+ if !isHasOwnCall(stripParens(pre.Operand), key) {
135
+ return false
136
+ }
137
+ // Negated guard: require the then branch to be a single `continue`
138
+ // so the rest of the loop runs only for own keys.
139
+ return isLoneContinue(ifStmt.ThenStatement)
140
+ }
141
+
142
+ // isHasOwnCall reports whether `node` is `Object.hasOwn(obj, key)` or
143
+ // `Object.prototype.hasOwnProperty.call(obj, key)`. The second
144
+ // argument must match `key` when one is supplied.
145
+ func isHasOwnCall(node *shimast.Node, key string) bool {
146
+ if node == nil || node.Kind != shimast.KindCallExpression {
147
+ return false
148
+ }
149
+ call := node.AsCallExpression()
150
+ if call == nil || call.Expression == nil || call.Arguments == nil {
151
+ return false
152
+ }
153
+ args := call.Arguments.Nodes
154
+ if len(args) < 2 {
155
+ return false
156
+ }
157
+ callee := stripParens(call.Expression)
158
+ switch {
159
+ case isMatchingPropertyAccess(callee, "Object", "hasOwn"):
160
+ // `Object.hasOwn(obj, key)` — both arguments belong to the
161
+ // caller; the key check is the second argument.
162
+ case isMatchingPropertyAccess(callee, "Object", "prototype", "hasOwnProperty", "call"):
163
+ // `Object.prototype.hasOwnProperty.call(obj, key)` — same
164
+ // argument layout because `.call(obj, key)` passes the
165
+ // receiver explicitly.
166
+ default:
167
+ return false
168
+ }
169
+ if key == "" {
170
+ return true
171
+ }
172
+ return identifierText(stripParens(args[1])) == key
173
+ }
174
+
175
+ // isLoneContinue reports whether `stmt` is a bare `continue;` (or a
176
+ // block containing exactly one `continue;`). Used to validate the
177
+ // then-branch of the negated-guard shape.
178
+ func isLoneContinue(stmt *shimast.Node) bool {
179
+ if stmt == nil {
180
+ return false
181
+ }
182
+ if stmt.Kind == shimast.KindContinueStatement {
183
+ return true
184
+ }
185
+ if stmt.Kind != shimast.KindBlock {
186
+ return false
187
+ }
188
+ block := stmt.AsBlock()
189
+ if block == nil || block.Statements == nil || len(block.Statements.Nodes) != 1 {
190
+ return false
191
+ }
192
+ return block.Statements.Nodes[0] != nil &&
193
+ block.Statements.Nodes[0].Kind == shimast.KindContinueStatement
194
+ }
195
+
196
+ func init() {
197
+ Register(guardForIn{})
198
+ }
@@ -0,0 +1,77 @@
1
+ // idLength reports declaration names shorter than the default minimum
2
+ // of two characters. Single-letter bindings (`a`, `x`, `t`) are
3
+ // notoriously hard to grep, fold poorly into call-site documentation,
4
+ // and frequently collide with the convention of using single letters
5
+ // only for true free variables.
6
+ // https://eslint.org/docs/latest/rules/id-length
7
+ //
8
+ // Conservative baseline: only the four declaration kinds the ESLint
9
+ // rule documents as in-scope are inspected — variable, function,
10
+ // class, and parameter declarations. Each name is read through the
11
+ // shared `identifierText` helper so destructuring patterns and
12
+ // computed property names contribute zero findings.
13
+ package linthost
14
+
15
+ import (
16
+ "strconv"
17
+
18
+ shimast "github.com/microsoft/typescript-go/shim/ast"
19
+ )
20
+
21
+ // idLengthMinimum is the default minimum identifier length. ESLint
22
+ // uses 2; mirroring it keeps the rule's default behavior aligned with
23
+ // upstream and lets the existing fixture annotations remain stable.
24
+ const idLengthMinimum = 2
25
+
26
+ type idLength struct{}
27
+
28
+ func (idLength) Name() string { return "id-length" }
29
+ func (idLength) Visits() []shimast.Kind {
30
+ return []shimast.Kind{
31
+ shimast.KindVariableDeclaration,
32
+ shimast.KindParameter,
33
+ shimast.KindFunctionDeclaration,
34
+ shimast.KindClassDeclaration,
35
+ }
36
+ }
37
+ func (idLength) Check(ctx *Context, node *shimast.Node) {
38
+ var nameNode *shimast.Node
39
+ switch node.Kind {
40
+ case shimast.KindVariableDeclaration:
41
+ decl := node.AsVariableDeclaration()
42
+ if decl == nil {
43
+ return
44
+ }
45
+ nameNode = decl.Name()
46
+ case shimast.KindParameter:
47
+ decl := node.AsParameterDeclaration()
48
+ if decl == nil {
49
+ return
50
+ }
51
+ nameNode = decl.Name()
52
+ case shimast.KindFunctionDeclaration:
53
+ decl := node.AsFunctionDeclaration()
54
+ if decl == nil {
55
+ return
56
+ }
57
+ nameNode = decl.Name()
58
+ case shimast.KindClassDeclaration:
59
+ decl := node.AsClassDeclaration()
60
+ if decl == nil {
61
+ return
62
+ }
63
+ nameNode = decl.Name()
64
+ }
65
+ name := identifierText(nameNode)
66
+ if name == "" {
67
+ return
68
+ }
69
+ if len([]rune(name)) >= idLengthMinimum {
70
+ return
71
+ }
72
+ ctx.Report(nameNode, "Identifier name '"+name+"' is too short (< "+strconv.Itoa(idLengthMinimum)+").")
73
+ }
74
+
75
+ func init() {
76
+ Register(idLength{})
77
+ }
@@ -5,14 +5,14 @@ import (
5
5
  shimscanner "github.com/microsoft/typescript-go/shim/scanner"
6
6
  )
7
7
 
8
- // no-import-type-side-effects: an import whose every named specifier
8
+ // noImportTypeSideEffects: an import whose every named specifier
9
9
  // uses the inline `type` modifier is morally a type-only import; hoist
10
10
  // the `type` to the import clause to make that intent explicit and let
11
11
  // `verbatimModuleSyntax` elide the import entirely. typescript-eslint
12
12
  // stylistic: https://typescript-eslint.io/rules/no-import-type-side-effects/
13
13
  type noImportTypeSideEffects struct{}
14
14
 
15
- func (noImportTypeSideEffects) Name() string { return "no-import-type-side-effects" }
15
+ func (noImportTypeSideEffects) Name() string { return "typescript/no-import-type-side-effects" }
16
16
  func (noImportTypeSideEffects) Visits() []shimast.Kind {
17
17
  return []shimast.Kind{shimast.KindImportDeclaration}
18
18
  }
@@ -94,6 +94,74 @@ func (noImportTypeSideEffects) Check(ctx *Context, node *shimast.Node) {
94
94
  ctx.ReportFix(node, message, edits...)
95
95
  }
96
96
 
97
+ // noUselessEmptyExport: `export {}` is only useful as a module marker.
98
+ // Once a file or namespace block already contains another import/export,
99
+ // the empty export does not change module-ness and can be removed.
100
+ type noUselessEmptyExport struct{}
101
+
102
+ func (noUselessEmptyExport) Name() string { return "typescript/no-useless-empty-export" }
103
+ func (noUselessEmptyExport) Visits() []shimast.Kind {
104
+ return []shimast.Kind{shimast.KindSourceFile, shimast.KindModuleBlock}
105
+ }
106
+ func (noUselessEmptyExport) Check(ctx *Context, node *shimast.Node) {
107
+ if ctx.File != nil && ctx.File.IsDeclarationFile {
108
+ return
109
+ }
110
+ statements := node.Statements()
111
+ if len(statements) == 0 {
112
+ return
113
+ }
114
+ emptyExports := []*shimast.Node{}
115
+ foundOtherModuleSyntax := false
116
+ for _, stmt := range statements {
117
+ if stmt == nil {
118
+ continue
119
+ }
120
+ if isEmptyExportDeclaration(stmt) {
121
+ emptyExports = append(emptyExports, stmt)
122
+ continue
123
+ }
124
+ if isModuleSyntaxStatement(stmt) {
125
+ foundOtherModuleSyntax = true
126
+ }
127
+ }
128
+ if !foundOtherModuleSyntax {
129
+ return
130
+ }
131
+ for _, stmt := range emptyExports {
132
+ ctx.Report(stmt, "Empty export does not change module-ness here.")
133
+ }
134
+ }
135
+
136
+ func isEmptyExportDeclaration(node *shimast.Node) bool {
137
+ if node == nil || node.Kind != shimast.KindExportDeclaration {
138
+ return false
139
+ }
140
+ decl := node.AsExportDeclaration()
141
+ if decl == nil || decl.ExportClause == nil || decl.ModuleSpecifier != nil {
142
+ return false
143
+ }
144
+ if decl.ExportClause.Kind != shimast.KindNamedExports {
145
+ return false
146
+ }
147
+ named := decl.ExportClause.AsNamedExports()
148
+ return named != nil && (named.Elements == nil || len(named.Elements.Nodes) == 0)
149
+ }
150
+
151
+ func isModuleSyntaxStatement(node *shimast.Node) bool {
152
+ if node == nil {
153
+ return false
154
+ }
155
+ switch node.Kind {
156
+ case shimast.KindImportDeclaration, shimast.KindImportEqualsDeclaration, shimast.KindExportAssignment:
157
+ return true
158
+ case shimast.KindExportDeclaration:
159
+ return !isEmptyExportDeclaration(node)
160
+ }
161
+ return hasModifier(node, shimast.KindExportKeyword)
162
+ }
163
+
97
164
  func init() {
98
165
  Register(noImportTypeSideEffects{})
166
+ Register(noUselessEmptyExport{})
99
167
  }