@ttsc/lint 0.13.1 → 0.14.0-dev.20260528.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (464) 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 +35 -10
  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/config.go +48 -17
  116. package/linthost/config_format.go +9 -9
  117. package/linthost/directives.go +67 -25
  118. package/linthost/dispatch.go +14 -3
  119. package/linthost/engine.go +152 -31
  120. package/linthost/fix.go +2 -2
  121. package/linthost/lsp.go +747 -0
  122. package/linthost/print_dispatch.go +2 -2
  123. package/linthost/print_nodes_function.go +2 -2
  124. package/linthost/print_nodes_object.go +1 -1
  125. package/linthost/rule_names.go +14 -0
  126. package/linthost/rules_arrays.go +2 -2
  127. package/linthost/rules_boundaries.go +532 -0
  128. package/linthost/rules_camelcase.go +133 -0
  129. package/linthost/rules_complexity.go +94 -0
  130. package/linthost/rules_consistent_return.go +130 -0
  131. package/linthost/rules_console.go +1 -1
  132. package/linthost/rules_core_extra.go +739 -0
  133. package/linthost/rules_curly.go +70 -0
  134. package/linthost/rules_cypress.go +608 -0
  135. package/linthost/rules_debugger.go +2 -2
  136. package/linthost/rules_default_case.go +39 -0
  137. package/linthost/rules_default_case_last.go +46 -0
  138. package/linthost/rules_dupes.go +3 -3
  139. package/linthost/rules_empty.go +3 -3
  140. package/linthost/rules_escape.go +44 -24
  141. package/linthost/rules_eval.go +2 -2
  142. package/linthost/rules_finally.go +2 -2
  143. package/linthost/rules_format_jsdoc.go +1 -1
  144. package/linthost/rules_format_print_width.go +9 -9
  145. package/linthost/rules_format_quotes.go +1 -1
  146. package/linthost/rules_format_semi.go +1 -1
  147. package/linthost/rules_format_sort_imports.go +1 -1
  148. package/linthost/rules_format_trailing_comma.go +1 -1
  149. package/linthost/rules_functional.go +967 -0
  150. package/linthost/rules_gap.go +24 -45
  151. package/linthost/rules_grouped_accessor_pairs.go +87 -0
  152. package/linthost/rules_guard_for_in.go +198 -0
  153. package/linthost/rules_id_length.go +77 -0
  154. package/linthost/rules_imports.go +70 -2
  155. package/linthost/rules_init_declarations.go +53 -0
  156. package/linthost/rules_jest.go +618 -0
  157. package/linthost/rules_jsdoc.go +502 -0
  158. package/linthost/rules_jsx_a11y.go +1264 -0
  159. package/linthost/rules_logic.go +12 -12
  160. package/linthost/rules_loops.go +1 -1
  161. package/linthost/rules_max_classes_per_file.go +58 -0
  162. package/linthost/rules_max_depth.go +83 -0
  163. package/linthost/rules_max_lines.go +101 -0
  164. package/linthost/rules_max_lines_per_function.go +57 -0
  165. package/linthost/rules_max_nested_callbacks.go +61 -0
  166. package/linthost/rules_max_params.go +49 -0
  167. package/linthost/rules_max_statements.go +59 -0
  168. package/linthost/rules_misc.go +1 -1
  169. package/linthost/rules_nextjs.go +697 -0
  170. package/linthost/rules_no_else_return.go +75 -0
  171. package/linthost/rules_no_empty_named_blocks.go +91 -0
  172. package/linthost/rules_no_extend_native.go +51 -0
  173. package/linthost/rules_no_import_assign.go +140 -0
  174. package/linthost/rules_no_invalid_this.go +52 -0
  175. package/linthost/rules_no_loop_func.go +85 -0
  176. package/linthost/rules_no_magic_numbers.go +123 -0
  177. package/linthost/rules_no_mixed_operators.go +80 -0
  178. package/linthost/rules_no_param_reassign.go +98 -0
  179. package/linthost/rules_no_redeclare.go +270 -0
  180. package/linthost/rules_no_restricted_imports.go +105 -0
  181. package/linthost/rules_no_restricted_syntax.go +49 -0
  182. package/linthost/rules_no_shadow.go +147 -0
  183. package/linthost/rules_no_unreachable.go +77 -0
  184. package/linthost/rules_no_useless_assignment.go +120 -0
  185. package/linthost/rules_no_useless_constructor.go +245 -0
  186. package/linthost/rules_no_useless_return.go +51 -0
  187. package/linthost/rules_params.go +1 -1
  188. package/linthost/rules_playwright.go +788 -0
  189. package/linthost/rules_prefer_arrow_callback.go +124 -0
  190. package/linthost/rules_prefer_destructuring.go +98 -0
  191. package/linthost/rules_prefer_named_capture_group.go +129 -0
  192. package/linthost/rules_prefer_rest_params.go +94 -0
  193. package/linthost/rules_problems.go +41 -30
  194. package/linthost/rules_promise.go +1128 -73
  195. package/linthost/rules_protos.go +2 -2
  196. package/linthost/rules_react.go +773 -0
  197. package/linthost/rules_react_extras.go +227 -0
  198. package/linthost/rules_react_hooks.go +848 -0
  199. package/linthost/rules_react_perf.go +293 -0
  200. package/linthost/rules_react_refresh.go +583 -0
  201. package/linthost/rules_regexp.go +410 -0
  202. package/linthost/rules_security.go +830 -0
  203. package/linthost/rules_self.go +2 -2
  204. package/linthost/rules_solid.go +1073 -0
  205. package/linthost/rules_sort_imports.go +69 -0
  206. package/linthost/rules_sort_keys.go +134 -0
  207. package/linthost/rules_storybook.go +1176 -0
  208. package/linthost/rules_strings.go +4 -4
  209. package/linthost/rules_suggestions.go +38 -38
  210. package/linthost/rules_tanstack_query.go +844 -0
  211. package/linthost/rules_testing_library.go +1204 -0
  212. package/linthost/rules_throw.go +1 -1
  213. package/linthost/rules_ts.go +19 -19
  214. package/linthost/rules_ts_async.go +399 -0
  215. package/linthost/rules_ts_class_literal_property_style.go +115 -0
  216. package/linthost/rules_ts_consistent_type_exports.go +256 -0
  217. package/linthost/rules_ts_explicit_function_return_type.go +67 -0
  218. package/linthost/rules_ts_extra.go +155 -36
  219. package/linthost/rules_ts_no_base_to_string.go +218 -0
  220. package/linthost/rules_ts_no_confusing_void.go +72 -0
  221. package/linthost/rules_ts_no_deprecated.go +195 -0
  222. package/linthost/rules_ts_no_for_in_array.go +84 -0
  223. package/linthost/rules_ts_no_magic_numbers.go +124 -0
  224. package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
  225. package/linthost/rules_ts_no_misused_spread.go +104 -0
  226. package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
  227. package/linthost/rules_ts_no_restricted_types.go +62 -0
  228. package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
  229. package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
  230. package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
  231. package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
  232. package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
  233. package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
  234. package/linthost/rules_ts_no_unsafe_argument.go +82 -0
  235. package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
  236. package/linthost/rules_ts_no_unsafe_call.go +82 -0
  237. package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
  238. package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
  239. package/linthost/rules_ts_no_unsafe_return.go +126 -0
  240. package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
  241. package/linthost/rules_ts_no_useless_constructor.go +52 -0
  242. package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
  243. package/linthost/rules_ts_parameter_properties.go +38 -0
  244. package/linthost/rules_ts_prefer_find.go +178 -0
  245. package/linthost/rules_ts_prefer_includes.go +255 -0
  246. package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
  247. package/linthost/rules_ts_prefer_optional_chain.go +228 -0
  248. package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
  249. package/linthost/rules_ts_prefer_readonly.go +73 -0
  250. package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
  251. package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
  252. package/linthost/rules_ts_prefer_return_this_type.go +135 -0
  253. package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
  254. package/linthost/rules_ts_promise_function_async.go +77 -0
  255. package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
  256. package/linthost/rules_ts_require_array_sort_compare.go +96 -0
  257. package/linthost/rules_ts_restrict_plus_operands.go +127 -0
  258. package/linthost/rules_ts_restrict_template_expressions.go +95 -0
  259. package/linthost/rules_ts_simple.go +387 -0
  260. package/linthost/rules_ts_sort_type_constituents.go +144 -0
  261. package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
  262. package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
  263. package/linthost/rules_ts_unbound_method.go +126 -0
  264. package/linthost/rules_tsdoc.go +136 -0
  265. package/linthost/rules_unicorn_better_regex.go +27 -0
  266. package/linthost/rules_unicorn_catch_error_name.go +46 -0
  267. package/linthost/rules_unicorn_consistent_assert.go +47 -0
  268. package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
  269. package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
  270. package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
  271. package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
  272. package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
  273. package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
  274. package/linthost/rules_unicorn_custom_error_definition.go +138 -0
  275. package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
  276. package/linthost/rules_unicorn_error_message.go +64 -0
  277. package/linthost/rules_unicorn_escape_case.go +51 -0
  278. package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
  279. package/linthost/rules_unicorn_explicit_length_check.go +88 -0
  280. package/linthost/rules_unicorn_filename_case.go +29 -0
  281. package/linthost/rules_unicorn_import_style.go +28 -0
  282. package/linthost/rules_unicorn_isolated_functions.go +29 -0
  283. package/linthost/rules_unicorn_new_for_builtins.go +87 -0
  284. package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
  285. package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
  286. package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
  287. package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
  288. package/linthost/rules_unicorn_no_array_for_each.go +40 -0
  289. package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
  290. package/linthost/rules_unicorn_no_array_reduce.go +41 -0
  291. package/linthost/rules_unicorn_no_array_reverse.go +44 -0
  292. package/linthost/rules_unicorn_no_array_sort.go +43 -0
  293. package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
  294. package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
  295. package/linthost/rules_unicorn_no_console_spaces.go +61 -0
  296. package/linthost/rules_unicorn_no_document_cookie.go +41 -0
  297. package/linthost/rules_unicorn_no_empty_file.go +44 -0
  298. package/linthost/rules_unicorn_no_for_loop.go +102 -0
  299. package/linthost/rules_unicorn_no_hex_escape.go +42 -0
  300. package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
  301. package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
  302. package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
  303. package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
  304. package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
  305. package/linthost/rules_unicorn_no_lonely_if.go +44 -0
  306. package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
  307. package/linthost/rules_unicorn_no_named_default.go +54 -0
  308. package/linthost/rules_unicorn_no_negated_condition.go +85 -0
  309. package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
  310. package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
  311. package/linthost/rules_unicorn_no_new_array.go +30 -0
  312. package/linthost/rules_unicorn_no_new_buffer.go +31 -0
  313. package/linthost/rules_unicorn_no_null.go +24 -0
  314. package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
  315. package/linthost/rules_unicorn_no_process_exit.go +43 -0
  316. package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
  317. package/linthost/rules_unicorn_no_static_only_class.go +56 -0
  318. package/linthost/rules_unicorn_no_thenable.go +74 -0
  319. package/linthost/rules_unicorn_no_this_assignment.go +35 -0
  320. package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
  321. package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
  322. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
  323. package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
  324. package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
  325. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
  326. package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
  327. package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
  328. package/linthost/rules_unicorn_no_unused_properties.go +30 -0
  329. package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
  330. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
  331. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
  332. package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
  333. package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
  334. package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
  335. package/linthost/rules_unicorn_no_useless_spread.go +67 -0
  336. package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
  337. package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
  338. package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
  339. package/linthost/rules_unicorn_number_literal_case.go +69 -0
  340. package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
  341. package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
  342. package/linthost/rules_unicorn_prefer_array_find.go +51 -0
  343. package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
  344. package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
  345. package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
  346. package/linthost/rules_unicorn_prefer_array_some.go +67 -0
  347. package/linthost/rules_unicorn_prefer_at.go +77 -0
  348. package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
  349. package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
  350. package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
  351. package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
  352. package/linthost/rules_unicorn_prefer_code_point.go +49 -0
  353. package/linthost/rules_unicorn_prefer_date_now.go +78 -0
  354. package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
  355. package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
  356. package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
  357. package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
  358. package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
  359. package/linthost/rules_unicorn_prefer_event_target.go +36 -0
  360. package/linthost/rules_unicorn_prefer_export_from.go +129 -0
  361. package/linthost/rules_unicorn_prefer_global_this.go +127 -0
  362. package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
  363. package/linthost/rules_unicorn_prefer_includes.go +149 -0
  364. package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
  365. package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
  366. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
  367. package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
  368. package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
  369. package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
  370. package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
  371. package/linthost/rules_unicorn_prefer_module.go +50 -0
  372. package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
  373. package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
  374. package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
  375. package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
  376. package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
  377. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
  378. package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
  379. package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
  380. package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
  381. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
  382. package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
  383. package/linthost/rules_unicorn_prefer_set_has.go +42 -0
  384. package/linthost/rules_unicorn_prefer_set_size.go +48 -0
  385. package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
  386. package/linthost/rules_unicorn_prefer_single_call.go +96 -0
  387. package/linthost/rules_unicorn_prefer_spread.go +51 -0
  388. package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
  389. package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
  390. package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
  391. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
  392. package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
  393. package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
  394. package/linthost/rules_unicorn_prefer_switch.go +103 -0
  395. package/linthost/rules_unicorn_prefer_ternary.go +71 -0
  396. package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
  397. package/linthost/rules_unicorn_prefer_type_error.go +127 -0
  398. package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
  399. package/linthost/rules_unicorn_relative_url_style.go +49 -0
  400. package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
  401. package/linthost/rules_unicorn_require_module_attributes.go +54 -0
  402. package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
  403. package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
  404. package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
  405. package/linthost/rules_unicorn_string_content.go +27 -0
  406. package/linthost/rules_unicorn_switch_case_braces.go +42 -0
  407. package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
  408. package/linthost/rules_unicorn_template_indent.go +28 -0
  409. package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
  410. package/linthost/rules_unicorn_throw_new_error.go +61 -0
  411. package/linthost/rules_var.go +4 -4
  412. package/linthost/rules_vitest.go +568 -0
  413. package/package.json +3 -3
  414. package/plugin/main.go +49 -3
  415. package/rule/astutil/astutil.go +10 -3
  416. package/rule/rule.go +12 -10
  417. package/src/defaultFormat.ts +11 -8
  418. package/src/index.ts +40 -16
  419. package/src/structures/ITtscLintConfig.ts +12 -6
  420. package/src/structures/{ITtscLintFormatConfig.ts → ITtscLintFormat.ts} +2 -2
  421. package/src/structures/TtscLintRuleSetting.ts +55 -0
  422. package/src/structures/index.ts +3 -4
  423. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +128 -0
  424. package/src/structures/rules/ITtscLintBoundariesRules.ts +95 -0
  425. package/src/structures/rules/ITtscLintContributorRules.ts +21 -0
  426. package/src/structures/rules/ITtscLintCoreRules.ts +1406 -0
  427. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
  428. package/src/structures/rules/ITtscLintCypressRules.ts +145 -0
  429. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +213 -0
  430. package/src/structures/rules/ITtscLintFunctionalRules.ts +202 -0
  431. package/src/structures/rules/ITtscLintJestRules.ts +220 -0
  432. package/src/structures/rules/ITtscLintJsdocRules.ts +153 -0
  433. package/src/structures/rules/ITtscLintJsxA11yRules.ts +339 -0
  434. package/src/structures/rules/ITtscLintNextjsRules.ts +206 -0
  435. package/src/structures/rules/ITtscLintPlaywrightRules.ts +361 -0
  436. package/src/structures/rules/ITtscLintPromiseRules.ts +205 -0
  437. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
  438. package/src/structures/rules/ITtscLintReactPerfRules.ts +55 -0
  439. package/src/structures/rules/ITtscLintReactRuleOptions.ts +43 -0
  440. package/src/structures/rules/ITtscLintReactRules.ts +321 -0
  441. package/src/structures/rules/ITtscLintRegexpRules.ts +212 -0
  442. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +89 -0
  443. package/src/structures/rules/ITtscLintRules.ts +77 -0
  444. package/src/structures/rules/ITtscLintSecurityRules.ts +162 -0
  445. package/src/structures/rules/ITtscLintSolidRules.ts +202 -0
  446. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +23 -0
  447. package/src/structures/rules/ITtscLintStorybookRules.ts +193 -0
  448. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +102 -0
  449. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +24 -0
  450. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +342 -0
  451. package/src/structures/rules/ITtscLintTypeScriptRules.ts +1230 -0
  452. package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
  453. package/src/structures/rules/ITtscLintVitestRules.ts +154 -0
  454. package/src/structures/rules/index.ts +31 -0
  455. package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
  456. package/lib/structures/TtscLintRule.d.ts +0 -17
  457. package/lib/structures/TtscLintRule.js.map +0 -1
  458. package/lib/structures/TtscLintRuleMap.d.ts +0 -46
  459. package/lib/structures/TtscLintRuleMap.js.map +0 -1
  460. package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
  461. package/lib/structures/TtscLintRuleOptions.js.map +0 -1
  462. package/src/structures/TtscLintRule.ts +0 -160
  463. package/src/structures/TtscLintRuleMap.ts +0 -55
  464. package/src/structures/TtscLintRuleOptions.ts +0 -151
@@ -2,7 +2,7 @@ package linthost
2
2
 
3
3
  import shimast "github.com/microsoft/typescript-go/shim/ast"
4
4
 
5
- // no-throw-literal: throw should always pass an Error subclass.
5
+ // noThrowLiteral: throw should always pass an Error subclass.
6
6
  // https://eslint.org/docs/latest/rules/no-throw-literal
7
7
  type noThrowLiteral struct{}
8
8
 
@@ -6,20 +6,20 @@ package linthost
6
6
 
7
7
  import shimast "github.com/microsoft/typescript-go/shim/ast"
8
8
 
9
- // no-explicit-any: ban `: any` annotations. Loud equivalent of
9
+ // noExplicitAny: ban `: any` annotations. Loud equivalent of
10
10
  // `@typescript-eslint/no-explicit-any`.
11
11
  type noExplicitAny struct{}
12
12
 
13
- func (noExplicitAny) Name() string { return "no-explicit-any" }
13
+ func (noExplicitAny) Name() string { return "typescript/no-explicit-any" }
14
14
  func (noExplicitAny) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindAnyKeyword} }
15
15
  func (noExplicitAny) Check(ctx *Context, node *shimast.Node) {
16
16
  ctx.Report(node, "Unexpected any. Specify a different type.")
17
17
  }
18
18
 
19
- // no-non-null-assertion: ban the postfix `!` non-null assertion.
19
+ // noNonNullAssertion: ban the postfix `!` non-null assertion.
20
20
  type noNonNullAssertion struct{}
21
21
 
22
- func (noNonNullAssertion) Name() string { return "no-non-null-assertion" }
22
+ func (noNonNullAssertion) Name() string { return "typescript/no-non-null-assertion" }
23
23
  func (noNonNullAssertion) Visits() []shimast.Kind {
24
24
  return []shimast.Kind{shimast.KindNonNullExpression}
25
25
  }
@@ -27,11 +27,11 @@ func (noNonNullAssertion) Check(ctx *Context, node *shimast.Node) {
27
27
  ctx.Report(node, "Forbidden non-null assertion.")
28
28
  }
29
29
 
30
- // no-empty-interface: empty `interface { }` declarations are an alias
30
+ // noEmptyInterface: empty `interface { }` declarations are an alias
31
31
  // for the supertype with extra ceremony.
32
32
  type noEmptyInterface struct{}
33
33
 
34
- func (noEmptyInterface) Name() string { return "no-empty-interface" }
34
+ func (noEmptyInterface) Name() string { return "typescript/no-empty-interface" }
35
35
  func (noEmptyInterface) Visits() []shimast.Kind {
36
36
  return []shimast.Kind{shimast.KindInterfaceDeclaration}
37
37
  }
@@ -45,11 +45,11 @@ func (noEmptyInterface) Check(ctx *Context, node *shimast.Node) {
45
45
  }
46
46
  }
47
47
 
48
- // no-inferrable-types: `let x: number = 0` — the annotation is what TS
48
+ // noInferrableTypes: `let x: number = 0` — the annotation is what TS
49
49
  // would have inferred anyway.
50
50
  type noInferrableTypes struct{}
51
51
 
52
- func (noInferrableTypes) Name() string { return "no-inferrable-types" }
52
+ func (noInferrableTypes) Name() string { return "typescript/no-inferrable-types" }
53
53
  func (noInferrableTypes) Visits() []shimast.Kind {
54
54
  return []shimast.Kind{shimast.KindVariableDeclaration, shimast.KindParameter, shimast.KindPropertyDeclaration}
55
55
  }
@@ -126,11 +126,11 @@ func isUnaryNumeric(node *shimast.Node) bool {
126
126
  return false
127
127
  }
128
128
 
129
- // no-namespace: TypeScript-only `namespace`/`module` declarations. They
129
+ // noNamespace: TypeScript-only `namespace`/`module` declarations. They
130
130
  // exist for legacy reasons; modern TS uses ES modules.
131
131
  type noNamespace struct{}
132
132
 
133
- func (noNamespace) Name() string { return "no-namespace" }
133
+ func (noNamespace) Name() string { return "typescript/no-namespace" }
134
134
  func (noNamespace) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindModuleDeclaration} }
135
135
  func (noNamespace) Check(ctx *Context, node *shimast.Node) {
136
136
  decl := node.AsModuleDeclaration()
@@ -145,11 +145,11 @@ func (noNamespace) Check(ctx *Context, node *shimast.Node) {
145
145
  ctx.Report(node, "ES2015 module syntax is preferred over namespaces.")
146
146
  }
147
147
 
148
- // no-this-alias: `const self = this;` reassigns `this` to a local. Use
148
+ // noThisAlias: `const self = this;` reassigns `this` to a local. Use
149
149
  // arrow functions or `.bind(this)` instead.
150
150
  type noThisAlias struct{}
151
151
 
152
- func (noThisAlias) Name() string { return "no-this-alias" }
152
+ func (noThisAlias) Name() string { return "typescript/no-this-alias" }
153
153
  func (noThisAlias) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindVariableDeclaration} }
154
154
  func (noThisAlias) Check(ctx *Context, node *shimast.Node) {
155
155
  decl := node.AsVariableDeclaration()
@@ -161,10 +161,10 @@ func (noThisAlias) Check(ctx *Context, node *shimast.Node) {
161
161
  }
162
162
  }
163
163
 
164
- // prefer-as-const: `as 'foo'` / `as 1` should be `as const`.
164
+ // preferAsConst: `as 'foo'` / `as 1` should be `as const`.
165
165
  type preferAsConst struct{}
166
166
 
167
- func (preferAsConst) Name() string { return "prefer-as-const" }
167
+ func (preferAsConst) Name() string { return "typescript/prefer-as-const" }
168
168
  func (preferAsConst) Visits() []shimast.Kind {
169
169
  return []shimast.Kind{shimast.KindAsExpression, shimast.KindTypeAssertionExpression}
170
170
  }
@@ -213,7 +213,7 @@ func (preferAsConst) Check(ctx *Context, node *shimast.Node) {
213
213
  }
214
214
 
215
215
  // literalsMatchSourceText reports whether lhs and rhs are both literal
216
- // expressions whose source text is identical. Used by prefer-as-const to
216
+ // expressions whose source text is identical. Used by preferAsConst to
217
217
  // detect `x as "foo"` where "foo" matches x's literal value.
218
218
  func literalsMatchSourceText(file *shimast.SourceFile, lhs, rhs *shimast.Node) bool {
219
219
  if lhs == nil || rhs == nil {
@@ -225,11 +225,11 @@ func literalsMatchSourceText(file *shimast.SourceFile, lhs, rhs *shimast.Node) b
225
225
  return nodeText(file, lhs) == nodeText(file, rhs)
226
226
  }
227
227
 
228
- // no-require-imports: ban `require(...)` calls in TS source. Use
228
+ // noRequireImports: ban `require(...)` calls in TS source. Use
229
229
  // ES `import` instead.
230
230
  type noRequireImports struct{}
231
231
 
232
- func (noRequireImports) Name() string { return "no-require-imports" }
232
+ func (noRequireImports) Name() string { return "typescript/no-require-imports" }
233
233
  func (noRequireImports) Visits() []shimast.Kind {
234
234
  return []shimast.Kind{shimast.KindCallExpression, shimast.KindImportEqualsDeclaration}
235
235
  }
@@ -250,11 +250,11 @@ func (noRequireImports) Check(ctx *Context, node *shimast.Node) {
250
250
  }
251
251
  }
252
252
 
253
- // ban-ts-comment: `// @ts-ignore` / `// @ts-nocheck` / `// @ts-expect-error`
253
+ // banTsComment: `// @ts-ignore` / `// @ts-nocheck` / `// @ts-expect-error`
254
254
  // silence the type checker. Default mode flags every variant.
255
255
  type banTsComment struct{}
256
256
 
257
- func (banTsComment) Name() string { return "ban-ts-comment" }
257
+ func (banTsComment) Name() string { return "typescript/ban-ts-comment" }
258
258
  func (banTsComment) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindSourceFile} }
259
259
  func (banTsComment) Check(ctx *Context, node *shimast.Node) {
260
260
  if ctx.File == nil {
@@ -0,0 +1,399 @@
1
+ // TypeScript async/error-flow rules: type-aware ports of the
2
+ // typescript-eslint recommended-type-checked rules that round out the
3
+ // async story alongside `typescript/await-thenable`,
4
+ // `typescript/no-floating-promises`, and `typescript/return-await`
5
+ // already in rules_promise.go.
6
+ //
7
+ // Implemented here:
8
+ // - typescript/require-await
9
+ // (AST-only; async function with no `await` in its body)
10
+ // - typescript/no-misused-promises
11
+ // (type-aware; Promise in conditional / logical / forEach position)
12
+ // - typescript/use-unknown-in-catch-callback-variable
13
+ // (type-aware; `.catch(err)` / `.then(_, err)` must annotate `unknown`)
14
+ // - typescript/only-throw-error
15
+ // (type-aware; `throw` of a primitive value)
16
+ package linthost
17
+
18
+ import (
19
+ shimast "github.com/microsoft/typescript-go/shim/ast"
20
+ shimchecker "github.com/microsoft/typescript-go/shim/checker"
21
+ )
22
+
23
+ // requireAwait reports `async` function bodies that contain no `await`
24
+ // expression. The function still pays the microtask cost and signals
25
+ // async semantics to callers; the missing `await` is almost always a
26
+ // refactor artifact. typescript-eslint:
27
+ // https://typescript-eslint.io/rules/require-await/
28
+ //
29
+ // AST-only. The walker stops at nested function-like boundaries so an
30
+ // `await` inside an inner non-async closure does not count toward the
31
+ // outer function. Async generators are exempt — they satisfy the
32
+ // async-keyword contract through `yield`.
33
+ type requireAwait struct{}
34
+
35
+ func (requireAwait) Name() string { return "typescript/require-await" }
36
+ func (requireAwait) Visits() []shimast.Kind {
37
+ return []shimast.Kind{
38
+ shimast.KindFunctionDeclaration,
39
+ shimast.KindFunctionExpression,
40
+ shimast.KindArrowFunction,
41
+ shimast.KindMethodDeclaration,
42
+ }
43
+ }
44
+ func (requireAwait) Check(ctx *Context, node *shimast.Node) {
45
+ if !hasAsyncModifier(node) {
46
+ return
47
+ }
48
+ if requireAwaitIsAsyncGenerator(node) {
49
+ return
50
+ }
51
+ body := node.Body()
52
+ if body == nil {
53
+ return
54
+ }
55
+ if requireAwaitBodyHasAwait(body) {
56
+ return
57
+ }
58
+ startPos := keywordStart(ctx.File, node, "async")
59
+ if startPos < 0 {
60
+ ctx.Report(node, "Async function has no `await` expression.")
61
+ return
62
+ }
63
+ ctx.ReportRange(startPos, startPos+len("async"), "Async function has no `await` expression.")
64
+ }
65
+
66
+ // requireAwaitIsAsyncGenerator reports whether node is `async function*`,
67
+ // `async *method`, or the function-expression form thereof. Async
68
+ // generators are exempted by typescript-eslint: the generator's `yield`
69
+ // expressions express the suspend points and the rule would otherwise
70
+ // fire on every `async function*` that does not also `await`.
71
+ func requireAwaitIsAsyncGenerator(node *shimast.Node) bool {
72
+ switch node.Kind {
73
+ case shimast.KindFunctionDeclaration:
74
+ decl := node.AsFunctionDeclaration()
75
+ return decl != nil && decl.AsteriskToken != nil
76
+ case shimast.KindFunctionExpression:
77
+ expr := node.AsFunctionExpression()
78
+ return expr != nil && expr.AsteriskToken != nil
79
+ case shimast.KindMethodDeclaration:
80
+ decl := node.AsMethodDeclaration()
81
+ return decl != nil && decl.AsteriskToken != nil
82
+ }
83
+ return false
84
+ }
85
+
86
+ // requireAwaitBodyHasAwait reports whether body (or any descendant that
87
+ // is not itself a nested function-like scope) contains an `await`
88
+ // expression. The walker mirrors `walkFunctionBody` in rules_promise.go
89
+ // but bails out early once an `await` is found.
90
+ func requireAwaitBodyHasAwait(body *shimast.Node) bool {
91
+ found := false
92
+ var walk func(*shimast.Node)
93
+ walk = func(n *shimast.Node) {
94
+ if found || n == nil {
95
+ return
96
+ }
97
+ if n != body && isFunctionLikeKind(n) {
98
+ return
99
+ }
100
+ if n.Kind == shimast.KindAwaitExpression {
101
+ found = true
102
+ return
103
+ }
104
+ n.ForEachChild(func(child *shimast.Node) bool {
105
+ walk(child)
106
+ return false
107
+ })
108
+ }
109
+ walk(body)
110
+ return found
111
+ }
112
+
113
+ // noMisusedPromises reports Promises supplied where a boolean or a
114
+ // `void`-returning callback is expected. The Promise is truthy as a
115
+ // value, so the conditional silently passes; the discarded Promise then
116
+ // leaks any rejection. typescript-eslint:
117
+ // https://typescript-eslint.io/rules/no-misused-promises/
118
+ //
119
+ // Type-aware. Covers the three highest-signal positions:
120
+ // - conditional positions: `if (p)`, `while (p)`, `do … while (p)`,
121
+ // `for (; p; …)`, `p ? a : b`, `!p`;
122
+ // - short-circuit / nullish operators: `p && x`, `p || x`, `p ?? x`;
123
+ // - array iteration: `.forEach(async fn)` where the callback returns
124
+ // a Promise the iteration never observes.
125
+ //
126
+ // JSX event-handler positions and arbitrary user-defined
127
+ // void-callback contracts are deferred — they need a richer expected-
128
+ // type inspection than this baseline.
129
+ type noMisusedPromises struct{}
130
+
131
+ func (noMisusedPromises) Name() string { return "typescript/no-misused-promises" }
132
+ func (noMisusedPromises) NeedsTypeChecker() bool {
133
+ return true
134
+ }
135
+ func (noMisusedPromises) Visits() []shimast.Kind {
136
+ return []shimast.Kind{
137
+ shimast.KindIfStatement,
138
+ shimast.KindWhileStatement,
139
+ shimast.KindDoStatement,
140
+ shimast.KindForStatement,
141
+ shimast.KindConditionalExpression,
142
+ shimast.KindPrefixUnaryExpression,
143
+ shimast.KindBinaryExpression,
144
+ shimast.KindCallExpression,
145
+ }
146
+ }
147
+ func (noMisusedPromises) Check(ctx *Context, node *shimast.Node) {
148
+ if ctx.Checker == nil {
149
+ return
150
+ }
151
+ switch node.Kind {
152
+ case shimast.KindIfStatement:
153
+ if stmt := node.AsIfStatement(); stmt != nil {
154
+ noMisusedPromisesReportConditional(ctx, stmt.Expression)
155
+ }
156
+ case shimast.KindWhileStatement:
157
+ if stmt := node.AsWhileStatement(); stmt != nil {
158
+ noMisusedPromisesReportConditional(ctx, stmt.Expression)
159
+ }
160
+ case shimast.KindDoStatement:
161
+ if stmt := node.AsDoStatement(); stmt != nil {
162
+ noMisusedPromisesReportConditional(ctx, stmt.Expression)
163
+ }
164
+ case shimast.KindForStatement:
165
+ if stmt := node.AsForStatement(); stmt != nil {
166
+ noMisusedPromisesReportConditional(ctx, stmt.Condition)
167
+ }
168
+ case shimast.KindConditionalExpression:
169
+ if expr := node.AsConditionalExpression(); expr != nil {
170
+ noMisusedPromisesReportConditional(ctx, expr.Condition)
171
+ }
172
+ case shimast.KindPrefixUnaryExpression:
173
+ expr := node.AsPrefixUnaryExpression()
174
+ if expr != nil && expr.Operator == shimast.KindExclamationToken {
175
+ noMisusedPromisesReportConditional(ctx, expr.Operand)
176
+ }
177
+ case shimast.KindBinaryExpression:
178
+ bin := node.AsBinaryExpression()
179
+ if bin == nil || bin.OperatorToken == nil {
180
+ return
181
+ }
182
+ switch bin.OperatorToken.Kind {
183
+ case shimast.KindAmpersandAmpersandToken,
184
+ shimast.KindBarBarToken,
185
+ shimast.KindQuestionQuestionToken:
186
+ noMisusedPromisesReportConditional(ctx, bin.Left)
187
+ }
188
+ case shimast.KindCallExpression:
189
+ if call := node.AsCallExpression(); call != nil {
190
+ noMisusedPromisesCheckVoidCallback(ctx, call)
191
+ }
192
+ }
193
+ }
194
+
195
+ // noMisusedPromisesReportConditional reports expr if it carries a
196
+ // Promise type. `await x` and `void x` are author-acknowledged opt-outs
197
+ // and pass through. `any` / `unknown` / `never` are intentionally NOT
198
+ // flagged because they propagate from generic helpers and would
199
+ // produce overwhelming false-positive volume in real codebases.
200
+ func noMisusedPromisesReportConditional(ctx *Context, expr *shimast.Node) {
201
+ target := stripParens(expr)
202
+ if target == nil {
203
+ return
204
+ }
205
+ switch target.Kind {
206
+ case shimast.KindAwaitExpression, shimast.KindVoidExpression:
207
+ return
208
+ }
209
+ t := ctx.Checker.GetTypeAtLocation(target)
210
+ if t == nil || !isPromiseTypedExpression(ctx.Checker, t) {
211
+ return
212
+ }
213
+ ctx.Report(target, "Expected non-Promise value in a boolean conditional position; did you forget `await`?")
214
+ }
215
+
216
+ // noMisusedPromisesCheckVoidCallback fires when an async callback is
217
+ // passed to a method that expects a void-returning callback. The
218
+ // baseline targets the most common offender — `Array.prototype.forEach`
219
+ // — by name rather than by signature inspection. Restricting to
220
+ // `forEach` keeps the false-positive rate low; richer void-callback
221
+ // detection (e.g., JSX event handlers, user methods with `void` in
222
+ // their signature) is deferred.
223
+ func noMisusedPromisesCheckVoidCallback(ctx *Context, call *shimast.CallExpression) {
224
+ if call == nil || call.Arguments == nil || len(call.Arguments.Nodes) == 0 {
225
+ return
226
+ }
227
+ _, method, ok := promisePropertyAccessParts(call.Expression)
228
+ if !ok || method != "forEach" {
229
+ return
230
+ }
231
+ callback := stripParens(call.Arguments.Nodes[0])
232
+ if callback == nil || !isFunctionLikeKind(callback) {
233
+ return
234
+ }
235
+ if !hasAsyncModifier(callback) {
236
+ return
237
+ }
238
+ ctx.Report(callback, "Async callback passed to forEach — the returned Promise will be discarded; use `for ... of` instead.")
239
+ }
240
+
241
+ // useUnknownInCatchCallbackVariable requires the parameter of `.catch`
242
+ // and the second parameter of `.then` to be explicitly typed `unknown`.
243
+ // TypeScript 4.4+ types `try { } catch (e)` as `unknown` by default;
244
+ // promise chain callbacks still default to implicit `any`, so this rule
245
+ // closes that ergonomic gap. typescript-eslint:
246
+ // https://typescript-eslint.io/rules/use-unknown-in-catch-callback-variable/
247
+ //
248
+ // Type-aware: only fires when the receiver of `.catch` / `.then` is
249
+ // actually a Promise (rules out user-defined methods named `catch`).
250
+ // The annotation check is textual on the parameter's type node — the
251
+ // annotation must be exactly the token `unknown`.
252
+ type useUnknownInCatchCallbackVariable struct{}
253
+
254
+ func (useUnknownInCatchCallbackVariable) Name() string {
255
+ return "typescript/use-unknown-in-catch-callback-variable"
256
+ }
257
+ func (useUnknownInCatchCallbackVariable) NeedsTypeChecker() bool {
258
+ return true
259
+ }
260
+ func (useUnknownInCatchCallbackVariable) Visits() []shimast.Kind {
261
+ return []shimast.Kind{shimast.KindCallExpression}
262
+ }
263
+ func (useUnknownInCatchCallbackVariable) Check(ctx *Context, node *shimast.Node) {
264
+ if ctx.Checker == nil {
265
+ return
266
+ }
267
+ call := node.AsCallExpression()
268
+ if call == nil || call.Expression == nil || call.Arguments == nil {
269
+ return
270
+ }
271
+ receiver, method, ok := promisePropertyAccessParts(call.Expression)
272
+ if !ok || (method != "catch" && method != "then") {
273
+ return
274
+ }
275
+ args := call.Arguments.Nodes
276
+ var callback *shimast.Node
277
+ switch method {
278
+ case "catch":
279
+ if len(args) < 1 {
280
+ return
281
+ }
282
+ callback = stripParens(args[0])
283
+ case "then":
284
+ if len(args) < 2 {
285
+ return
286
+ }
287
+ callback = stripParens(args[1])
288
+ }
289
+ if callback == nil || !isFunctionLikeKind(callback) {
290
+ return
291
+ }
292
+ if receiver == nil {
293
+ return
294
+ }
295
+ t := ctx.Checker.GetTypeAtLocation(receiver)
296
+ if t == nil || !isPromiseTypedExpression(ctx.Checker, t) {
297
+ return
298
+ }
299
+ params := callback.Parameters()
300
+ if len(params) == 0 {
301
+ return
302
+ }
303
+ param := params[0].AsParameterDeclaration()
304
+ if param == nil {
305
+ return
306
+ }
307
+ if param.Type == nil {
308
+ ctx.Report(params[0], "Catch callback parameter should be explicitly typed `unknown`.")
309
+ return
310
+ }
311
+ annotationText := nodeText(ctx.File, param.Type)
312
+ if annotationText != "unknown" {
313
+ ctx.Report(param.Type, "Catch callback parameter must be typed `unknown`, not `"+annotationText+"`.")
314
+ }
315
+ }
316
+
317
+ // onlyThrowError reports `throw` of a value that is statically known
318
+ // to be a primitive (string / number / boolean / bigint / void /
319
+ // undefined / null). Throwing a non-Error loses the structured stack
320
+ // trace and breaks downstream `instanceof Error` checks.
321
+ // typescript-eslint:
322
+ // https://typescript-eslint.io/rules/only-throw-error/
323
+ //
324
+ // Type-aware. `any` / `unknown` / `never` pass through — they propagate
325
+ // from generic helpers and a strict rejection would explode at every
326
+ // re-throw of a caught `unknown`. Object types are conservatively
327
+ // allowed (a full base-type walk to confirm Error-derivation is
328
+ // deferred); the practical effect is that `throw "string"` and
329
+ // `throw 42` are caught but `throw { code: 1 }` slips through.
330
+ type onlyThrowError struct{}
331
+
332
+ func (onlyThrowError) Name() string { return "typescript/only-throw-error" }
333
+ func (onlyThrowError) NeedsTypeChecker() bool {
334
+ return true
335
+ }
336
+ func (onlyThrowError) Visits() []shimast.Kind {
337
+ return []shimast.Kind{shimast.KindThrowStatement}
338
+ }
339
+ func (onlyThrowError) Check(ctx *Context, node *shimast.Node) {
340
+ if ctx.Checker == nil {
341
+ return
342
+ }
343
+ stmt := node.AsThrowStatement()
344
+ if stmt == nil || stmt.Expression == nil {
345
+ return
346
+ }
347
+ expr := stripParens(stmt.Expression)
348
+ if expr == nil {
349
+ return
350
+ }
351
+ t := ctx.Checker.GetTypeAtLocation(expr)
352
+ if t == nil {
353
+ return
354
+ }
355
+ if onlyThrowErrorIsPrimitive(ctx.Checker, t) {
356
+ ctx.Report(node, "Throw an Error object instead of a non-Error value.")
357
+ }
358
+ }
359
+
360
+ // onlyThrowErrorIsPrimitive returns true when t is a primitive type
361
+ // (string / number / boolean / bigint / void / undefined / null).
362
+ // any / unknown / never escape the check on purpose. Union and
363
+ // intersection types recurse — `string | number` is a primitive
364
+ // throw even though it is a composite type.
365
+ func onlyThrowErrorIsPrimitive(checker *shimchecker.Checker, t *shimchecker.Type) bool {
366
+ if checker == nil || t == nil {
367
+ return false
368
+ }
369
+ flags := t.Flags()
370
+ if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
371
+ return false
372
+ }
373
+ if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
374
+ for _, part := range t.Types() {
375
+ if part == nil {
376
+ continue
377
+ }
378
+ if onlyThrowErrorIsPrimitive(checker, part) {
379
+ return true
380
+ }
381
+ }
382
+ return false
383
+ }
384
+ const primitiveMask = shimchecker.TypeFlagsStringLike |
385
+ shimchecker.TypeFlagsNumberLike |
386
+ shimchecker.TypeFlagsBigIntLike |
387
+ shimchecker.TypeFlagsBooleanLike |
388
+ shimchecker.TypeFlagsVoid |
389
+ shimchecker.TypeFlagsUndefined |
390
+ shimchecker.TypeFlagsNull
391
+ return flags&primitiveMask != 0
392
+ }
393
+
394
+ func init() {
395
+ Register(requireAwait{})
396
+ Register(noMisusedPromises{})
397
+ Register(useUnknownInCatchCallbackVariable{})
398
+ Register(onlyThrowError{})
399
+ }
@@ -0,0 +1,115 @@
1
+ // AST-only `typescript/class-literal-property-style` rule from
2
+ // typescript-eslint. Implemented here as a standalone file because the
3
+ // rule's literal-shape predicate and getter/setter pairing are
4
+ // self-contained and unrelated to the other class-shape rules already
5
+ // living in rules_ts_simple.go.
6
+ package linthost
7
+
8
+ import (
9
+ shimast "github.com/microsoft/typescript-go/shim/ast"
10
+ )
11
+
12
+ // classLiteralPropertyStyle reports `get foo() { return <literal>; }`
13
+ // accessors that have no companion setter — those should be expressed
14
+ // as a `readonly foo = <literal>;` field declaration. The getter form
15
+ // re-runs the body on every read and obscures the fact that the value
16
+ // is fixed; a readonly field is shorter, type-narrows to the literal
17
+ // type, and signals "this is a constant" at the call site.
18
+ // https://typescript-eslint.io/rules/class-literal-property-style/
19
+ //
20
+ // Default upstream config is `"fields"`, matching the wording above.
21
+ // The rule fires when:
22
+ // - the class member is a `get` accessor,
23
+ // - its body is a block containing a single `return <literal>;`,
24
+ // - the literal is a string, number, boolean, `null`, a template
25
+ // literal with no substitutions, or a unary-minus prefix on a
26
+ // numeric literal,
27
+ // - the class has no `set` accessor for the same member name.
28
+ type classLiteralPropertyStyle struct{}
29
+
30
+ func (classLiteralPropertyStyle) Name() string {
31
+ return "typescript/class-literal-property-style"
32
+ }
33
+ func (classLiteralPropertyStyle) Visits() []shimast.Kind {
34
+ return []shimast.Kind{shimast.KindGetAccessor}
35
+ }
36
+ func (classLiteralPropertyStyle) Check(ctx *Context, node *shimast.Node) {
37
+ parent := node.Parent
38
+ if parent == nil ||
39
+ (parent.Kind != shimast.KindClassDeclaration && parent.Kind != shimast.KindClassExpression) {
40
+ return
41
+ }
42
+ accessor := node.AsGetAccessorDeclaration()
43
+ if accessor == nil || accessor.Body == nil || accessor.Body.Kind != shimast.KindBlock {
44
+ return
45
+ }
46
+ statements := accessor.Body.Statements()
47
+ if len(statements) != 1 {
48
+ return
49
+ }
50
+ ret := statements[0]
51
+ if ret == nil || ret.Kind != shimast.KindReturnStatement {
52
+ return
53
+ }
54
+ retStmt := ret.AsReturnStatement()
55
+ if retStmt == nil || retStmt.Expression == nil {
56
+ return
57
+ }
58
+ if !isClassLiteralPropertyValue(retStmt.Expression) {
59
+ return
60
+ }
61
+ name := classMemberName(node)
62
+ if name == "" {
63
+ return
64
+ }
65
+ if classHasSetterFor(parent, name) {
66
+ return
67
+ }
68
+ ctx.Report(node, "Literal-returning getter `"+name+"` should be a `readonly` field instead.")
69
+ }
70
+
71
+ // isClassLiteralPropertyValue reports whether the expression is one of
72
+ // the literal shapes the rule accepts: a plain literal, a template
73
+ // literal without substitutions, or a unary-minus prefix on a numeric
74
+ // literal.
75
+ func isClassLiteralPropertyValue(expr *shimast.Node) bool {
76
+ if expr == nil {
77
+ return false
78
+ }
79
+ switch expr.Kind {
80
+ case shimast.KindStringLiteral,
81
+ shimast.KindNumericLiteral,
82
+ shimast.KindTrueKeyword,
83
+ shimast.KindFalseKeyword,
84
+ shimast.KindNullKeyword,
85
+ shimast.KindNoSubstitutionTemplateLiteral:
86
+ return true
87
+ case shimast.KindPrefixUnaryExpression:
88
+ prefix := expr.AsPrefixUnaryExpression()
89
+ if prefix == nil || prefix.Operator != shimast.KindMinusToken || prefix.Operand == nil {
90
+ return false
91
+ }
92
+ return prefix.Operand.Kind == shimast.KindNumericLiteral
93
+ }
94
+ return false
95
+ }
96
+
97
+ // classHasSetterFor reports whether the class contains a `set`
98
+ // accessor whose name matches `name`. A getter paired with a setter
99
+ // is left alone because the field form cannot reproduce the setter's
100
+ // side effects.
101
+ func classHasSetterFor(class *shimast.Node, name string) bool {
102
+ for _, member := range classMembers(class) {
103
+ if member == nil || member.Kind != shimast.KindSetAccessor {
104
+ continue
105
+ }
106
+ if classMemberName(member) == name {
107
+ return true
108
+ }
109
+ }
110
+ return false
111
+ }
112
+
113
+ func init() {
114
+ Register(classLiteralPropertyStyle{})
115
+ }