@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
@@ -0,0 +1,147 @@
1
+ // noShadow reports a binding declaration whose name matches a binding
2
+ // already in scope at an outer level. The inner declaration silently
3
+ // obscures the outer reference — readers expect `outer` inside the body
4
+ // to mean the outer binding, but it now resolves to the inner one. The
5
+ // pattern is almost always an accidental rebind during refactoring.
6
+ // https://eslint.org/docs/latest/rules/no-shadow
7
+ //
8
+ // Conservative scope tracking: walk the file once with an explicit
9
+ // stack of scope frames. A frame is pushed on every function-like
10
+ // node (which contributes its parameter names) and on every Block /
11
+ // CatchClause (which contributes its block-scoped `let`, `const`,
12
+ // `class`, and `function` declarations). `var` bindings are recorded
13
+ // on the nearest enclosing function frame instead — they hoist past
14
+ // inner block boundaries.
15
+ //
16
+ // Only plain identifier bindings are tracked. Destructuring patterns
17
+ // (`const { a } = …`, `function f({ x }) {}`) are skipped because the
18
+ // rule cannot reason about pattern equality without a real binder, and
19
+ // the AST-only baseline prefers false negatives to false positives.
20
+ package linthost
21
+
22
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
23
+
24
+ type noShadow struct{}
25
+
26
+ func (noShadow) Name() string { return "no-shadow" }
27
+ func (noShadow) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindSourceFile} }
28
+ func (noShadow) Check(ctx *Context, node *shimast.Node) {
29
+ if node == nil {
30
+ return
31
+ }
32
+ // Each frame records the names declared at that lexical level.
33
+ // `isFunction` marks frames that absorb hoisted `var` bindings.
34
+ type frame struct {
35
+ names map[string]bool
36
+ isFunction bool
37
+ }
38
+ stack := []*frame{{names: map[string]bool{}, isFunction: true}}
39
+
40
+ outerHas := func(name string) bool {
41
+ for i := len(stack) - 2; i >= 0; i-- {
42
+ if stack[i].names[name] {
43
+ return true
44
+ }
45
+ }
46
+ return false
47
+ }
48
+
49
+ declare := func(name string, declNode *shimast.Node, hoist bool) {
50
+ if name == "" {
51
+ return
52
+ }
53
+ target := stack[len(stack)-1]
54
+ if hoist {
55
+ for i := len(stack) - 1; i >= 0; i-- {
56
+ if stack[i].isFunction {
57
+ target = stack[i]
58
+ break
59
+ }
60
+ }
61
+ }
62
+ if outerHas(name) {
63
+ ctx.Report(declNode, "'"+name+"' is already declared in the upper scope.")
64
+ }
65
+ target.names[name] = true
66
+ }
67
+
68
+ var walk func(n *shimast.Node)
69
+ walk = func(n *shimast.Node) {
70
+ if n == nil {
71
+ return
72
+ }
73
+ // Bind a function declaration's name in the enclosing scope
74
+ // before descending into its body. `var`-style hoisting takes
75
+ // the name to the nearest function frame.
76
+ if n.Kind == shimast.KindFunctionDeclaration {
77
+ if decl := n.AsFunctionDeclaration(); decl != nil && decl.Body != nil {
78
+ if name := identifierText(decl.Name()); name != "" {
79
+ declare(name, n, true)
80
+ }
81
+ }
82
+ }
83
+ // Push a frame for every scope-introducing node. Function-like
84
+ // frames also receive their parameter names before descending.
85
+ if isFunctionLikeKind(n) {
86
+ stack = append(stack, &frame{names: map[string]bool{}, isFunction: true})
87
+ for _, name := range parameterBindingNames(n) {
88
+ declare(name, n, false)
89
+ }
90
+ n.ForEachChild(func(child *shimast.Node) bool {
91
+ walk(child)
92
+ return false
93
+ })
94
+ stack = stack[:len(stack)-1]
95
+ return
96
+ }
97
+ switch n.Kind {
98
+ case shimast.KindBlock, shimast.KindCatchClause:
99
+ // Function bodies are blocks too, but the function frame
100
+ // pushed above already represents that scope — skip the
101
+ // extra frame so a parameter and a body-level `let` of the
102
+ // same name still register as a redeclare, not a shadow.
103
+ if n.Kind == shimast.KindBlock && n.Parent != nil && isFunctionLikeKind(n.Parent) {
104
+ n.ForEachChild(func(child *shimast.Node) bool {
105
+ walk(child)
106
+ return false
107
+ })
108
+ return
109
+ }
110
+ stack = append(stack, &frame{names: map[string]bool{}})
111
+ if catch := n.AsCatchClause(); catch != nil && catch.VariableDeclaration != nil {
112
+ if name := identifierText(catch.VariableDeclaration.Name()); name != "" {
113
+ declare(name, catch.VariableDeclaration, false)
114
+ }
115
+ }
116
+ n.ForEachChild(func(child *shimast.Node) bool {
117
+ walk(child)
118
+ return false
119
+ })
120
+ stack = stack[:len(stack)-1]
121
+ return
122
+ case shimast.KindVariableStatement:
123
+ vs := n.AsVariableStatement()
124
+ if vs != nil && vs.DeclarationList != nil {
125
+ hoist := shimast.IsVar(vs.DeclarationList)
126
+ for _, name := range variableStatementBindingNames(n) {
127
+ declare(name, n, hoist)
128
+ }
129
+ }
130
+ case shimast.KindClassDeclaration:
131
+ if decl := n.AsClassDeclaration(); decl != nil {
132
+ if name := identifierText(decl.Name()); name != "" {
133
+ declare(name, n, false)
134
+ }
135
+ }
136
+ }
137
+ n.ForEachChild(func(child *shimast.Node) bool {
138
+ walk(child)
139
+ return false
140
+ })
141
+ }
142
+ walk(node)
143
+ }
144
+
145
+ func init() {
146
+ Register(noShadow{})
147
+ }
@@ -0,0 +1,77 @@
1
+ // noUnreachable reports statements that follow an unconditional control-
2
+ // flow terminator inside the same statement list. After `return`, `throw`,
3
+ // `break`, or `continue` the surrounding block exits, so any later
4
+ // statement in the list is dead code — almost always a leftover from
5
+ // refactoring.
6
+ //
7
+ // Conservative baseline: only the immediate statement list of a Block,
8
+ // SourceFile, or ModuleBlock is inspected; nested conditionals and loops
9
+ // are left to a real control-flow pass. Hoistable function declarations
10
+ // following the terminator are exempt because they are hoisted above the
11
+ // unreachable point and remain callable from earlier statements.
12
+ // https://eslint.org/docs/latest/rules/no-unreachable
13
+ package linthost
14
+
15
+ import (
16
+ shimast "github.com/microsoft/typescript-go/shim/ast"
17
+ )
18
+
19
+ type noUnreachable struct{}
20
+
21
+ func (noUnreachable) Name() string { return "no-unreachable" }
22
+ func (noUnreachable) Visits() []shimast.Kind {
23
+ return []shimast.Kind{
24
+ shimast.KindBlock,
25
+ shimast.KindSourceFile,
26
+ shimast.KindModuleBlock,
27
+ }
28
+ }
29
+ func (noUnreachable) Check(ctx *Context, node *shimast.Node) {
30
+ stmts := node.Statements()
31
+ if len(stmts) < 2 {
32
+ return
33
+ }
34
+ terminated := false
35
+ for _, stmt := range stmts {
36
+ if stmt == nil {
37
+ continue
38
+ }
39
+ if terminated && !isHoistableDeclaration(stmt) {
40
+ ctx.Report(stmt, "Unreachable code.")
41
+ continue
42
+ }
43
+ if isControlFlowTerminator(stmt) {
44
+ terminated = true
45
+ }
46
+ }
47
+ }
48
+
49
+ // isControlFlowTerminator reports whether `stmt` is one of the four
50
+ // statement kinds that unconditionally leave the surrounding block:
51
+ // `return`, `throw`, `break`, `continue`.
52
+ func isControlFlowTerminator(stmt *shimast.Node) bool {
53
+ if stmt == nil {
54
+ return false
55
+ }
56
+ switch stmt.Kind {
57
+ case shimast.KindReturnStatement,
58
+ shimast.KindThrowStatement,
59
+ shimast.KindBreakStatement,
60
+ shimast.KindContinueStatement:
61
+ return true
62
+ }
63
+ return false
64
+ }
65
+
66
+ // isHoistableDeclaration reports whether `stmt` is a declaration whose
67
+ // binding survives even when it textually follows a terminator. Function
68
+ // declarations hoist to the top of their containing scope, so a
69
+ // `function f() {…}` after a `return` is still callable from earlier
70
+ // statements and is not dead code in the ESLint sense.
71
+ func isHoistableDeclaration(stmt *shimast.Node) bool {
72
+ return stmt != nil && stmt.Kind == shimast.KindFunctionDeclaration
73
+ }
74
+
75
+ func init() {
76
+ Register(noUnreachable{})
77
+ }
@@ -0,0 +1,120 @@
1
+ // noUselessAssignment reports an assignment whose value is immediately
2
+ // overwritten by the very next statement without an intervening read of
3
+ // the same identifier. `x = 1; x = 2;` writes the first value just to
4
+ // discard it — almost always a leftover from refactoring.
5
+ // https://eslint.org/docs/latest/rules/no-useless-assignment
6
+ //
7
+ // Conservative baseline: only the syntactically adjacent
8
+ // ExpressionStatement / ExpressionStatement pair is inspected, and only
9
+ // when both left-hand sides are bare identifiers with the same name. A
10
+ // real dead-store analysis would track reads across branches and inside
11
+ // the right-hand expression; the simpler textual match catches the
12
+ // common copy-paste case without needing full control-flow.
13
+ package linthost
14
+
15
+ import (
16
+ shimast "github.com/microsoft/typescript-go/shim/ast"
17
+ )
18
+
19
+ type noUselessAssignment struct{}
20
+
21
+ func (noUselessAssignment) Name() string { return "no-useless-assignment" }
22
+ func (noUselessAssignment) Visits() []shimast.Kind {
23
+ return []shimast.Kind{shimast.KindBlock}
24
+ }
25
+ func (noUselessAssignment) Check(ctx *Context, node *shimast.Node) {
26
+ block := node.AsBlock()
27
+ if block == nil || block.Statements == nil {
28
+ return
29
+ }
30
+ stmts := block.Statements.Nodes
31
+ if len(stmts) < 2 {
32
+ return
33
+ }
34
+ for i := 0; i+1 < len(stmts); i++ {
35
+ firstName, firstAssign := plainAssignmentTarget(stmts[i])
36
+ if firstName == "" {
37
+ continue
38
+ }
39
+ secondName, _ := plainAssignmentTarget(stmts[i+1])
40
+ if secondName != firstName {
41
+ continue
42
+ }
43
+ // If the second statement's RHS reads the first target, the
44
+ // first write is load-bearing — skip.
45
+ if assignmentRhsReadsIdent(stmts[i+1], firstName) {
46
+ continue
47
+ }
48
+ ctx.Report(firstAssign, "Assignment to `"+firstName+"` is immediately overwritten without being read.")
49
+ }
50
+ }
51
+
52
+ // plainAssignmentTarget returns the identifier name on the left-hand
53
+ // side of `stmt` when it is an `ExpressionStatement` wrapping a plain
54
+ // `<ident> = <expr>` assignment. Anything else (compound assignment,
55
+ // destructuring target, property access, non-statement) returns "".
56
+ func plainAssignmentTarget(stmt *shimast.Node) (string, *shimast.Node) {
57
+ if stmt == nil || stmt.Kind != shimast.KindExpressionStatement {
58
+ return "", nil
59
+ }
60
+ expr := stmt.AsExpressionStatement()
61
+ if expr == nil || expr.Expression == nil {
62
+ return "", nil
63
+ }
64
+ inner := stripParens(expr.Expression)
65
+ if inner == nil || inner.Kind != shimast.KindBinaryExpression {
66
+ return "", nil
67
+ }
68
+ bin := inner.AsBinaryExpression()
69
+ if bin == nil || bin.OperatorToken == nil || bin.OperatorToken.Kind != shimast.KindEqualsToken {
70
+ return "", nil
71
+ }
72
+ name := identifierText(stripParens(bin.Left))
73
+ if name == "" {
74
+ return "", nil
75
+ }
76
+ return name, stmt
77
+ }
78
+
79
+ // assignmentRhsReadsIdent reports whether the second statement's
80
+ // assignment right-hand side references the same identifier name. A
81
+ // `x = x + 1` style update reads the previous value, so the prior
82
+ // assignment is not actually dead.
83
+ func assignmentRhsReadsIdent(stmt *shimast.Node, name string) bool {
84
+ if stmt == nil || stmt.Kind != shimast.KindExpressionStatement {
85
+ return false
86
+ }
87
+ expr := stmt.AsExpressionStatement()
88
+ if expr == nil || expr.Expression == nil {
89
+ return false
90
+ }
91
+ inner := stripParens(expr.Expression)
92
+ if inner == nil || inner.Kind != shimast.KindBinaryExpression {
93
+ return false
94
+ }
95
+ bin := inner.AsBinaryExpression()
96
+ if bin == nil || bin.Right == nil {
97
+ return false
98
+ }
99
+ found := false
100
+ var walk func(n *shimast.Node)
101
+ walk = func(n *shimast.Node) {
102
+ if found || n == nil {
103
+ return
104
+ }
105
+ if n.Kind == shimast.KindIdentifier && identifierText(n) == name {
106
+ found = true
107
+ return
108
+ }
109
+ n.ForEachChild(func(child *shimast.Node) bool {
110
+ walk(child)
111
+ return false
112
+ })
113
+ }
114
+ walk(bin.Right)
115
+ return found
116
+ }
117
+
118
+ func init() {
119
+ Register(noUselessAssignment{})
120
+ }
@@ -0,0 +1,245 @@
1
+ // noUselessConstructor: report class constructors that contribute
2
+ // nothing beyond what the engine would synthesize on its own. Two
3
+ // shapes fire:
4
+ //
5
+ // - Empty body, no parameters, no accessibility/decorator modifiers.
6
+ // The engine generates an identical implicit constructor when the
7
+ // class declares none, so the explicit declaration is pure noise.
8
+ //
9
+ // - Derived constructor that does nothing but forward to `super(...args)`
10
+ // unchanged. The default constructor of a subclass already forwards
11
+ // every argument to `super`, so an explicit `constructor(...args) {
12
+ // super(...args); }` is redundant. The forwarded parameter list and
13
+ // the `super` call's argument list must be identical rest-spreads of
14
+ // the same name — modifying, reordering, or filtering the arguments
15
+ // means the constructor still has a purpose and is left alone.
16
+ //
17
+ // Constructors that carry parameter properties (`constructor(private x:
18
+ // number)`) or accessibility / decorator modifiers are skipped: removing
19
+ // them would change the class shape or its observable metadata, so they
20
+ // are never "useless" by this rule's standard.
21
+ // https://typescript-eslint.io/rules/no-useless-constructor/
22
+ package linthost
23
+
24
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
25
+
26
+ type noUselessConstructor struct{}
27
+
28
+ func (noUselessConstructor) Name() string { return "no-useless-constructor" }
29
+ func (noUselessConstructor) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindConstructor} }
30
+ func (noUselessConstructor) Check(ctx *Context, node *shimast.Node) {
31
+ ctor := node.AsConstructorDeclaration()
32
+ if ctor == nil || ctor.Body == nil {
33
+ return
34
+ }
35
+ // Accessibility modifiers (`private`/`protected`) on the constructor
36
+ // itself are load-bearing: they restrict who can `new` the class.
37
+ // Removing the constructor would silently widen visibility.
38
+ if node.ModifierFlags()&(shimast.ModifierFlagsPrivate|shimast.ModifierFlagsProtected) != 0 {
39
+ return
40
+ }
41
+ if hasParameterProperty(node) {
42
+ return
43
+ }
44
+ body := ctor.Body.AsBlock()
45
+ if body == nil || body.Statements == nil {
46
+ return
47
+ }
48
+ params := node.Parameters()
49
+
50
+ // Shape 1: empty body, no parameters. The implicit constructor that
51
+ // the engine generates when no constructor is written is identical,
52
+ // so the explicit declaration is noise.
53
+ if len(params) == 0 && len(body.Statements.Nodes) == 0 {
54
+ ctx.Report(node, "Useless empty constructor.")
55
+ return
56
+ }
57
+
58
+ // Shape 2: derived class constructor that only forwards arguments to
59
+ // `super(...args)` without modification. The synthetic default
60
+ // constructor of a subclass behaves identically, so the explicit
61
+ // declaration is noise. Only fires when the class extends another.
62
+ parent := node.Parent
63
+ if parent == nil || !classExtendsAnother(parent) {
64
+ return
65
+ }
66
+ if len(body.Statements.Nodes) != 1 {
67
+ return
68
+ }
69
+ if !isPlainSuperForwarder(params, body.Statements.Nodes[0]) {
70
+ return
71
+ }
72
+ ctx.Report(node, "Useless constructor: forwards arguments to `super` unchanged.")
73
+ }
74
+
75
+ // hasParameterProperty reports whether any constructor parameter carries
76
+ // a TypeScript parameter-property modifier (`public`, `private`,
77
+ // `protected`, or `readonly`). Such a parameter declares an instance
78
+ // field, so the constructor is doing real work even if its body is
79
+ // empty — removing it would drop the field.
80
+ func hasParameterProperty(node *shimast.Node) bool {
81
+ for _, p := range node.Parameters() {
82
+ if p == nil {
83
+ continue
84
+ }
85
+ if p.ModifierFlags()&(shimast.ModifierFlagsPrivate|shimast.ModifierFlagsProtected|shimast.ModifierFlagsReadonly) != 0 {
86
+ return true
87
+ }
88
+ // `public` is not represented by any of the above flags but does
89
+ // still create a parameter property. Inspect the raw modifier
90
+ // list for a PublicKeyword.
91
+ decl := p.AsParameterDeclaration()
92
+ if decl == nil {
93
+ continue
94
+ }
95
+ if hasPublicModifier(decl.Modifiers()) {
96
+ return true
97
+ }
98
+ }
99
+ return false
100
+ }
101
+
102
+ // hasPublicModifier reports whether `mods` includes a `public` keyword.
103
+ // `public` is a parameter-property qualifier that does not set any of
104
+ // the Private/Protected/Readonly modifier flags, so we walk the raw
105
+ // modifier list to detect it.
106
+ func hasPublicModifier(mods *shimast.ModifierList) bool {
107
+ if mods == nil {
108
+ return false
109
+ }
110
+ for _, m := range mods.Nodes {
111
+ if m != nil && m.Kind == shimast.KindPublicKeyword {
112
+ return true
113
+ }
114
+ }
115
+ return false
116
+ }
117
+
118
+ // isPlainSuperForwarder reports whether `stmt` is exactly
119
+ // `super(...name);` (an expression statement wrapping a CallExpression
120
+ // whose callee is the `super` keyword and whose only argument is a
121
+ // SpreadElement over an identifier) AND the constructor parameter list
122
+ // is exactly `(...name)` over the same identifier. Type annotations on
123
+ // the rest parameter are allowed — `(...args: unknown[])` still
124
+ // forwards unchanged.
125
+ func isPlainSuperForwarder(params []*shimast.Node, stmt *shimast.Node) bool {
126
+ if stmt == nil || stmt.Kind != shimast.KindExpressionStatement {
127
+ return false
128
+ }
129
+ exprStmt := stmt.AsExpressionStatement()
130
+ if exprStmt == nil || exprStmt.Expression == nil {
131
+ return false
132
+ }
133
+ expr := stripParens(exprStmt.Expression)
134
+ if expr == nil || expr.Kind != shimast.KindCallExpression {
135
+ return false
136
+ }
137
+ call := expr.AsCallExpression()
138
+ if call == nil || call.Expression == nil || call.Expression.Kind != shimast.KindSuperKeyword {
139
+ return false
140
+ }
141
+ if call.Arguments == nil {
142
+ return false
143
+ }
144
+ args := call.Arguments.Nodes
145
+ // `super()` — zero arguments — only matches when the constructor
146
+ // also declares zero parameters. ESLint flags this shape too: the
147
+ // synthetic default constructor of a derived class would call
148
+ // `super(...args)`, which for a zero-arg case is the same thing.
149
+ if len(args) == 0 {
150
+ return len(params) == 0
151
+ }
152
+ if len(args) != len(params) {
153
+ return false
154
+ }
155
+ // All arguments must be `...name` spreading the identically named
156
+ // rest parameter. ESLint also accepts the positional `super(a, b)`
157
+ // over `(a, b)` shape — match that too: every parameter must be a
158
+ // plain identifier (or rest), and the argument must spread/use the
159
+ // same identifier in the same position.
160
+ for i, arg := range args {
161
+ paramName, paramRest, ok := plainParamIdentifier(params[i])
162
+ if !ok {
163
+ return false
164
+ }
165
+ argName, argSpread, ok := plainArgIdentifier(arg)
166
+ if !ok {
167
+ return false
168
+ }
169
+ if paramName != argName {
170
+ return false
171
+ }
172
+ if paramRest != argSpread {
173
+ return false
174
+ }
175
+ }
176
+ return true
177
+ }
178
+
179
+ // plainParamIdentifier extracts the identifier name of a parameter that
180
+ // is a plain `name` or `...name`. Returns `(name, isRest, true)` on
181
+ // match, or zero values + false when the parameter is a destructuring
182
+ // pattern, has a default value, has an accessibility modifier, has a
183
+ // `?` token (optional), or otherwise carries observable behavior.
184
+ // Type annotations are intentionally ignored — they do not change the
185
+ // runtime forwarding behavior.
186
+ func plainParamIdentifier(param *shimast.Node) (string, bool, bool) {
187
+ if param == nil {
188
+ return "", false, false
189
+ }
190
+ decl := param.AsParameterDeclaration()
191
+ if decl == nil {
192
+ return "", false, false
193
+ }
194
+ if decl.Initializer != nil || decl.QuestionToken != nil {
195
+ return "", false, false
196
+ }
197
+ // Accessibility modifier on the parameter would already have been
198
+ // caught by hasParameterProperty above, but guard locally too.
199
+ if param.ModifierFlags()&(shimast.ModifierFlagsPrivate|shimast.ModifierFlagsProtected|shimast.ModifierFlagsReadonly) != 0 {
200
+ return "", false, false
201
+ }
202
+ if hasPublicModifier(decl.Modifiers()) {
203
+ return "", false, false
204
+ }
205
+ name := identifierText(decl.Name())
206
+ if name == "" {
207
+ return "", false, false
208
+ }
209
+ return name, decl.DotDotDotToken != nil, true
210
+ }
211
+
212
+ // plainArgIdentifier extracts the identifier name of a call argument
213
+ // that is a plain `name` or `...name`. Returns `(name, isSpread, true)`
214
+ // on match. Anything else — a literal, property access, expression —
215
+ // is treated as observable work and disqualifies the forwarder.
216
+ func plainArgIdentifier(arg *shimast.Node) (string, bool, bool) {
217
+ if arg == nil {
218
+ return "", false, false
219
+ }
220
+ stripped := stripParens(arg)
221
+ if stripped == nil {
222
+ return "", false, false
223
+ }
224
+ if stripped.Kind == shimast.KindSpreadElement {
225
+ spread := stripped.AsSpreadElement()
226
+ if spread == nil {
227
+ return "", false, false
228
+ }
229
+ inner := stripParens(spread.Expression)
230
+ name := identifierText(inner)
231
+ if name == "" {
232
+ return "", false, false
233
+ }
234
+ return name, true, true
235
+ }
236
+ name := identifierText(stripped)
237
+ if name == "" {
238
+ return "", false, false
239
+ }
240
+ return name, false, true
241
+ }
242
+
243
+ func init() {
244
+ Register(noUselessConstructor{})
245
+ }
@@ -0,0 +1,51 @@
1
+ // noUselessReturn reports a bare `return;` whose only effect is to end a
2
+ // function body that would have returned anyway. `function f() { … ;
3
+ // return; }` is identical to `function f() { … ; }`: the trailing
4
+ // statement adds no behavior, only noise. The conservative baseline only
5
+ // fires at the very last statement of a block that is itself the
6
+ // immediate body of a function-like — any earlier `return;` inside a
7
+ // loop, branch, or inner block may still be load-bearing.
8
+ // https://eslint.org/docs/latest/rules/no-useless-return
9
+ package linthost
10
+
11
+ import (
12
+ shimast "github.com/microsoft/typescript-go/shim/ast"
13
+ )
14
+
15
+ type noUselessReturn struct{}
16
+
17
+ func (noUselessReturn) Name() string { return "no-useless-return" }
18
+ func (noUselessReturn) Visits() []shimast.Kind {
19
+ return []shimast.Kind{shimast.KindReturnStatement}
20
+ }
21
+ func (noUselessReturn) Check(ctx *Context, node *shimast.Node) {
22
+ ret := node.AsReturnStatement()
23
+ if ret == nil || ret.Expression != nil {
24
+ // `return X;` is never useless: it carries a value.
25
+ return
26
+ }
27
+ parent := node.Parent
28
+ if parent == nil || parent.Kind != shimast.KindBlock {
29
+ return
30
+ }
31
+ block := parent.AsBlock()
32
+ if block == nil || block.Statements == nil {
33
+ return
34
+ }
35
+ stmts := block.Statements.Nodes
36
+ if len(stmts) == 0 || stmts[len(stmts)-1] != node {
37
+ // Only the last statement of the block is provably useless;
38
+ // any earlier `return;` may guard the statements that follow.
39
+ return
40
+ }
41
+ if !isFunctionLikeKind(parent.Parent) {
42
+ // The block must be the immediate body of a function-like so
43
+ // the function's natural completion is what would run next.
44
+ return
45
+ }
46
+ ctx.Report(node, "Unnecessary return statement.")
47
+ }
48
+
49
+ func init() {
50
+ Register(noUselessReturn{})
51
+ }
@@ -2,7 +2,7 @@ package linthost
2
2
 
3
3
  import shimast "github.com/microsoft/typescript-go/shim/ast"
4
4
 
5
- // default-param-last: forbid parameters with default initializers that
5
+ // defaultParamLast: forbid parameters with default initializers that
6
6
  // precede non-default parameters. The combination forces every caller
7
7
  // to spell out `undefined` for the defaulted parameter — which defeats
8
8
  // the purpose of the default. ESLint canonical: