@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
@@ -0,0 +1,102 @@
1
+ // typescript/no-unsafe-assignment: assigning an `any`-typed value into
2
+ // a concretely typed location erases the static guarantee the target
3
+ // declaration carries. `const num: number = anyValue;` compiles, but
4
+ // every later use of `num` operates on whatever `anyValue` actually
5
+ // holds at runtime. typescript-eslint:
6
+ // https://typescript-eslint.io/rules/no-unsafe-assignment/
7
+ //
8
+ // Type-aware. The rule visits two shapes:
9
+ //
10
+ // - `VariableDeclaration` — the initializer of `let x: T = ...` or
11
+ // `const x: T = ...`. Without a typed target the assignment is
12
+ // trivially safe (the local becomes `any` too), so the rule
13
+ // requires an explicit type annotation OR a target that resolves
14
+ // to a non-`any` type.
15
+ // - `BinaryExpression` with `=` operator — a plain reassignment like
16
+ // `x = anyValue`. The LHS already has a static type from its
17
+ // declaration; the rule fires when the RHS is `any` and the LHS is
18
+ // not.
19
+ //
20
+ // As with the rest of the unsafe-* family `unknown` is intentionally
21
+ // NOT flagged: it forces a narrowing assertion before the value can be
22
+ // stored in a typed slot, which is the explicit ergonomic the upstream
23
+ // rule pushes toward.
24
+ package linthost
25
+
26
+ import (
27
+ shimast "github.com/microsoft/typescript-go/shim/ast"
28
+ )
29
+
30
+ type noUnsafeAssignment struct{}
31
+
32
+ func (noUnsafeAssignment) Name() string { return "typescript/no-unsafe-assignment" }
33
+ func (noUnsafeAssignment) NeedsTypeChecker() bool {
34
+ return true
35
+ }
36
+ func (noUnsafeAssignment) Visits() []shimast.Kind {
37
+ return []shimast.Kind{
38
+ shimast.KindVariableDeclaration,
39
+ shimast.KindBinaryExpression,
40
+ }
41
+ }
42
+ func (noUnsafeAssignment) Check(ctx *Context, node *shimast.Node) {
43
+ if ctx.Checker == nil {
44
+ return
45
+ }
46
+ switch node.Kind {
47
+ case shimast.KindVariableDeclaration:
48
+ decl := node.AsVariableDeclaration()
49
+ if decl == nil || decl.Initializer == nil {
50
+ return
51
+ }
52
+ // Only flag when the target has an explicit type annotation —
53
+ // `const x = anyValue;` widens `x` to `any` too, which is the
54
+ // `no-explicit-any` family's concern, not this rule's.
55
+ if decl.Type == nil {
56
+ return
57
+ }
58
+ rhs := stripParens(decl.Initializer)
59
+ if rhs == nil {
60
+ return
61
+ }
62
+ rhsType := ctx.Checker.GetTypeAtLocation(rhs)
63
+ if !typeIsUnsafeAny(rhsType) {
64
+ return
65
+ }
66
+ lhsType := ctx.Checker.GetTypeFromTypeNode(decl.Type)
67
+ if typeIsUnsafeAny(lhsType) {
68
+ return
69
+ }
70
+ ctx.Report(node, noUnsafeAssignmentMessage)
71
+ case shimast.KindBinaryExpression:
72
+ bin := node.AsBinaryExpression()
73
+ if bin == nil || bin.OperatorToken == nil {
74
+ return
75
+ }
76
+ if bin.OperatorToken.Kind != shimast.KindEqualsToken {
77
+ return
78
+ }
79
+ if bin.Left == nil || bin.Right == nil {
80
+ return
81
+ }
82
+ rhs := stripParens(bin.Right)
83
+ if rhs == nil {
84
+ return
85
+ }
86
+ rhsType := ctx.Checker.GetTypeAtLocation(rhs)
87
+ if !typeIsUnsafeAny(rhsType) {
88
+ return
89
+ }
90
+ lhsType := ctx.Checker.GetTypeAtLocation(bin.Left)
91
+ if typeIsUnsafeAny(lhsType) {
92
+ return
93
+ }
94
+ ctx.Report(node, noUnsafeAssignmentMessage)
95
+ }
96
+ }
97
+
98
+ const noUnsafeAssignmentMessage = "Unsafe assignment of a value typed as `any` to a typed target. Narrow the value before storing it."
99
+
100
+ func init() {
101
+ Register(noUnsafeAssignment{})
102
+ }
@@ -0,0 +1,82 @@
1
+ // typescript/no-unsafe-call: invoking a value whose static type is
2
+ // `any` discards every signature check the type system would otherwise
3
+ // perform. The runtime call still happens, but the parameter list is
4
+ // unchecked, the return type is `any`, and any downstream use of the
5
+ // result silently spreads the `any` further. typescript-eslint:
6
+ // https://typescript-eslint.io/rules/no-unsafe-call/
7
+ //
8
+ // Type-aware. The rule visits the three syntactic invocation shapes —
9
+ // `f(...)`, `new F(...)`, and the tagged-template form `f` + ``"x"`` —
10
+ // and reports when the callee resolves to a type whose flags include
11
+ // `TypeFlagsAny`. `unknown` is intentionally not flagged: it requires a
12
+ // narrowing assertion before the call, which is the explicit ergonomics
13
+ // the upstream rule pushes toward. `never` is also skipped — a never
14
+ // callee means the code is unreachable, which is a different rule's
15
+ // concern.
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
+ type noUnsafeCall struct{}
24
+
25
+ func (noUnsafeCall) Name() string { return "typescript/no-unsafe-call" }
26
+ func (noUnsafeCall) NeedsTypeChecker() bool {
27
+ return true
28
+ }
29
+ func (noUnsafeCall) Visits() []shimast.Kind {
30
+ return []shimast.Kind{
31
+ shimast.KindCallExpression,
32
+ shimast.KindNewExpression,
33
+ shimast.KindTaggedTemplateExpression,
34
+ }
35
+ }
36
+ func (noUnsafeCall) Check(ctx *Context, node *shimast.Node) {
37
+ if ctx.Checker == nil {
38
+ return
39
+ }
40
+ var callee *shimast.Node
41
+ switch node.Kind {
42
+ case shimast.KindCallExpression:
43
+ if call := node.AsCallExpression(); call != nil {
44
+ callee = call.Expression
45
+ }
46
+ case shimast.KindNewExpression:
47
+ if ne := node.AsNewExpression(); ne != nil {
48
+ callee = ne.Expression
49
+ }
50
+ case shimast.KindTaggedTemplateExpression:
51
+ if tag := node.AsTaggedTemplateExpression(); tag != nil {
52
+ callee = tag.Tag
53
+ }
54
+ }
55
+ if callee == nil {
56
+ return
57
+ }
58
+ t := ctx.Checker.GetTypeAtLocation(callee)
59
+ if !typeIsUnsafeAny(t) {
60
+ return
61
+ }
62
+ ctx.Report(callee, noUnsafeCallMessage)
63
+ }
64
+
65
+ const noUnsafeCallMessage = "Unsafe call of a value typed as `any`. Narrow the callee to a concrete signature before invoking it."
66
+
67
+ // typeIsUnsafeAny reports whether `t` carries the `any` flag — the only
68
+ // shape these unsafe-* rules flag. `unknown` is intentionally NOT
69
+ // included: it forces a narrowing assertion at the use site, which is
70
+ // the safer ergonomic the upstream rules push toward. Returns false on
71
+ // nil so an absent type silently bypasses the rule rather than firing
72
+ // on every unanalysable expression.
73
+ func typeIsUnsafeAny(t *shimchecker.Type) bool {
74
+ if t == nil {
75
+ return false
76
+ }
77
+ return t.Flags()&shimchecker.TypeFlagsAny != 0
78
+ }
79
+
80
+ func init() {
81
+ Register(noUnsafeCall{})
82
+ }
@@ -0,0 +1,235 @@
1
+ // typescript/no-unsafe-enum-comparison: `===` / `!==` (and the `==` /
2
+ // `!=` cousins) silently accept any value that shares the widened
3
+ // primitive of an enum member. A string enum value compared with a raw
4
+ // string literal therefore matches whichever string happens to land in
5
+ // the other operand, even when the literal is not declared on the enum
6
+ // at all. The fix is to compare against one of the enum's own members
7
+ // so a typo surfaces at compile time.
8
+ // typescript-eslint:
9
+ // https://typescript-eslint.io/rules/no-unsafe-enum-comparison/
10
+ //
11
+ // Type-aware. Without a Checker we cannot tell an enum-typed value
12
+ // apart from a plain `string` / `number`, so Context.Checker == nil
13
+ // short-circuits the visit the same way every other type-aware rule
14
+ // in this package does.
15
+ //
16
+ // The matching algorithm mirrors typescript-eslint:
17
+ //
18
+ // - one side must carry an enum type (TypeFlagsEnumLike — covers
19
+ // both the enum union and its literal members);
20
+ // - the other side must be the widened primitive (string-/number-/
21
+ // bigint-like) WITHOUT carrying the same enum;
22
+ // - `any`, `unknown`, `never`, and identical enums on both sides
23
+ // pass through.
24
+ package linthost
25
+
26
+ import (
27
+ shimast "github.com/microsoft/typescript-go/shim/ast"
28
+ shimchecker "github.com/microsoft/typescript-go/shim/checker"
29
+ )
30
+
31
+ type noUnsafeEnumComparison struct{}
32
+
33
+ func (noUnsafeEnumComparison) Name() string { return "typescript/no-unsafe-enum-comparison" }
34
+ func (noUnsafeEnumComparison) NeedsTypeChecker() bool {
35
+ return true
36
+ }
37
+ func (noUnsafeEnumComparison) Visits() []shimast.Kind {
38
+ return []shimast.Kind{shimast.KindBinaryExpression}
39
+ }
40
+ func (noUnsafeEnumComparison) Check(ctx *Context, node *shimast.Node) {
41
+ if ctx.Checker == nil {
42
+ return
43
+ }
44
+ bin := node.AsBinaryExpression()
45
+ if bin == nil || bin.OperatorToken == nil || bin.Left == nil || bin.Right == nil {
46
+ return
47
+ }
48
+ switch bin.OperatorToken.Kind {
49
+ case shimast.KindEqualsEqualsToken,
50
+ shimast.KindEqualsEqualsEqualsToken,
51
+ shimast.KindExclamationEqualsToken,
52
+ shimast.KindExclamationEqualsEqualsToken:
53
+ default:
54
+ return
55
+ }
56
+ left := ctx.Checker.GetTypeAtLocation(bin.Left)
57
+ right := ctx.Checker.GetTypeAtLocation(bin.Right)
58
+ if left == nil || right == nil {
59
+ return
60
+ }
61
+ if noUnsafeEnumComparisonMismatch(left, right) || noUnsafeEnumComparisonMismatch(right, left) {
62
+ ctx.Report(node, "Unsafe comparison between an enum-typed value and a plain primitive of the same widened type. Compare against one of the enum's own members so a typo surfaces at compile time.")
63
+ }
64
+ }
65
+
66
+ // noUnsafeEnumComparisonMismatch reports whether `enumSide` carries an
67
+ // enum type and `otherSide` is the widened primitive without naming the
68
+ // same enum. Both arms walk union constituents — a `Color | undefined`
69
+ // still counts as the enum side, and the comparison `color === "red"`
70
+ // is still unsafe even when `color` carries an extra nullish branch.
71
+ func noUnsafeEnumComparisonMismatch(enumSide, otherSide *shimchecker.Type) bool {
72
+ if !noUnsafeEnumComparisonHasEnum(enumSide) {
73
+ return false
74
+ }
75
+ // `any` / `unknown` / `never` on the other side silently propagate
76
+ // from generic helpers — flagging them would explode false positives
77
+ // the same way `restrict-template-expressions` mitigates with its
78
+ // `allowAny` default.
79
+ if noUnsafeEnumComparisonIsLoose(otherSide) {
80
+ return false
81
+ }
82
+ // If the other side is provably the same enum (or one of its
83
+ // members), the comparison is the safe shape the rule recommends.
84
+ if noUnsafeEnumComparisonSharesEnum(enumSide, otherSide) {
85
+ return false
86
+ }
87
+ // The mismatch only fires when the non-enum side is the widened
88
+ // primitive that the enum widens to. A `Color === Status.Active`
89
+ // comparison (two unrelated enums of the same widened number) also
90
+ // trips this branch via the other call ordering.
91
+ if !noUnsafeEnumComparisonIsBareLiteralLike(otherSide) && !noUnsafeEnumComparisonHasEnum(otherSide) {
92
+ return false
93
+ }
94
+ return true
95
+ }
96
+
97
+ // noUnsafeEnumComparisonHasEnum reports whether t (or any constituent of
98
+ // a union) carries an enum-like flag. `TypeFlagsEnumLike` covers both
99
+ // the enum union type produced by `enum E { ... }` and the canonical
100
+ // `TypeFlagsEnumLiteral`-tagged literal types for each member.
101
+ func noUnsafeEnumComparisonHasEnum(t *shimchecker.Type) bool {
102
+ if t == nil {
103
+ return false
104
+ }
105
+ flags := t.Flags()
106
+ if flags&shimchecker.TypeFlagsEnumLike != 0 {
107
+ return true
108
+ }
109
+ if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
110
+ for _, part := range t.Types() {
111
+ if noUnsafeEnumComparisonHasEnum(part) {
112
+ return true
113
+ }
114
+ }
115
+ }
116
+ return false
117
+ }
118
+
119
+ // noUnsafeEnumComparisonIsLoose reports whether t propagates from a
120
+ // generic helper without naming a concrete type — `any` / `unknown` /
121
+ // `never`. The upstream rule keeps these silent so type-erasure paths
122
+ // (`JSON.parse`, untyped APIs) don't light up everywhere.
123
+ func noUnsafeEnumComparisonIsLoose(t *shimchecker.Type) bool {
124
+ if t == nil {
125
+ return true
126
+ }
127
+ return t.Flags()&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0
128
+ }
129
+
130
+ // noUnsafeEnumComparisonSharesEnum reports whether both sides refer to
131
+ // the same enum declaration. The Checker canonicalizes enum literal
132
+ // types per member, so identity follows the type's name symbol (or the
133
+ // enum union's symbol) up the parent chain to the EnumDeclaration node
134
+ // — comparing those addresses tells us whether `Color.Red` and
135
+ // `Color.Blue` come from the same enum.
136
+ func noUnsafeEnumComparisonSharesEnum(a, b *shimchecker.Type) bool {
137
+ aDecl := noUnsafeEnumComparisonEnumDeclaration(a)
138
+ bDecl := noUnsafeEnumComparisonEnumDeclaration(b)
139
+ if aDecl == nil || bDecl == nil {
140
+ return false
141
+ }
142
+ return aDecl == bDecl
143
+ }
144
+
145
+ // noUnsafeEnumComparisonEnumDeclaration returns the EnumDeclaration
146
+ // node that t (or any constituent of a union) belongs to, or nil when
147
+ // t is not an enum-flavored type. Both the enum union type and each
148
+ // enum-literal member carry the enum's symbol via Type.Symbol; the
149
+ // symbol's parent declaration is the EnumDeclaration we identify by.
150
+ func noUnsafeEnumComparisonEnumDeclaration(t *shimchecker.Type) *shimast.Node {
151
+ if t == nil {
152
+ return nil
153
+ }
154
+ flags := t.Flags()
155
+ if flags&shimchecker.TypeFlagsEnumLike != 0 {
156
+ sym := t.Symbol()
157
+ if sym == nil {
158
+ return nil
159
+ }
160
+ for _, decl := range sym.Declarations {
161
+ if decl == nil {
162
+ continue
163
+ }
164
+ if decl.Kind == shimast.KindEnumDeclaration {
165
+ return decl
166
+ }
167
+ // Enum member literal types carry the member symbol; walk
168
+ // one level up to land on the surrounding EnumDeclaration.
169
+ if decl.Parent != nil && decl.Parent.Kind == shimast.KindEnumDeclaration {
170
+ return decl.Parent
171
+ }
172
+ }
173
+ return nil
174
+ }
175
+ if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
176
+ var seen *shimast.Node
177
+ for _, part := range t.Types() {
178
+ decl := noUnsafeEnumComparisonEnumDeclaration(part)
179
+ if decl == nil {
180
+ continue
181
+ }
182
+ if seen == nil {
183
+ seen = decl
184
+ continue
185
+ }
186
+ if seen != decl {
187
+ return nil
188
+ }
189
+ }
190
+ return seen
191
+ }
192
+ return nil
193
+ }
194
+
195
+ // noUnsafeEnumComparisonIsBareLiteralLike reports whether t is a plain
196
+ // primitive or primitive literal — the widened side of an enum
197
+ // comparison. Unions are considered bare when every constituent is.
198
+ // Pure `null` / `undefined` operands are exempt because they don't
199
+ // share an enum's primitive widening — `color === null` is a real
200
+ // nullability check, not a same-primitive mistake.
201
+ func noUnsafeEnumComparisonIsBareLiteralLike(t *shimchecker.Type) bool {
202
+ if t == nil {
203
+ return false
204
+ }
205
+ flags := t.Flags()
206
+ if flags&shimchecker.TypeFlagsEnumLike != 0 {
207
+ return false
208
+ }
209
+ const primitiveMask = shimchecker.TypeFlagsStringLike |
210
+ shimchecker.TypeFlagsNumberLike |
211
+ shimchecker.TypeFlagsBigIntLike
212
+ if flags&primitiveMask != 0 {
213
+ return true
214
+ }
215
+ if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
216
+ anyMatch := false
217
+ for _, part := range t.Types() {
218
+ if part == nil {
219
+ continue
220
+ }
221
+ if noUnsafeEnumComparisonHasEnum(part) {
222
+ return false
223
+ }
224
+ if noUnsafeEnumComparisonIsBareLiteralLike(part) {
225
+ anyMatch = true
226
+ }
227
+ }
228
+ return anyMatch
229
+ }
230
+ return false
231
+ }
232
+
233
+ func init() {
234
+ Register(noUnsafeEnumComparison{})
235
+ }
@@ -0,0 +1,58 @@
1
+ // typescript/no-unsafe-member-access: reading a property off a value
2
+ // whose static type is `any` silently yields another `any`, and the
3
+ // next operation on that result is unchecked too. `x.foo.bar.baz` is
4
+ // the cascade that lets a single `any` propagate through an entire
5
+ // expression tree. typescript-eslint:
6
+ // https://typescript-eslint.io/rules/no-unsafe-member-access/
7
+ //
8
+ // Type-aware. The rule visits dotted access (`x.foo`) and computed
9
+ // access (`x[k]`) and reports when the receiver resolves to `any`. As
10
+ // with the rest of the unsafe-* family `unknown` is intentionally NOT
11
+ // flagged: it forces a narrowing assertion before the access, which is
12
+ // the explicit ergonomic the upstream rule pushes toward.
13
+ package linthost
14
+
15
+ import (
16
+ shimast "github.com/microsoft/typescript-go/shim/ast"
17
+ )
18
+
19
+ type noUnsafeMemberAccess struct{}
20
+
21
+ func (noUnsafeMemberAccess) Name() string { return "typescript/no-unsafe-member-access" }
22
+ func (noUnsafeMemberAccess) NeedsTypeChecker() bool {
23
+ return true
24
+ }
25
+ func (noUnsafeMemberAccess) Visits() []shimast.Kind {
26
+ return []shimast.Kind{
27
+ shimast.KindPropertyAccessExpression,
28
+ shimast.KindElementAccessExpression,
29
+ }
30
+ }
31
+ func (noUnsafeMemberAccess) Check(ctx *Context, node *shimast.Node) {
32
+ if ctx.Checker == nil {
33
+ return
34
+ }
35
+ var receiver *shimast.Node
36
+ switch node.Kind {
37
+ case shimast.KindPropertyAccessExpression:
38
+ if access := node.AsPropertyAccessExpression(); access != nil {
39
+ receiver = access.Expression
40
+ }
41
+ case shimast.KindElementAccessExpression:
42
+ if access := node.AsElementAccessExpression(); access != nil {
43
+ receiver = access.Expression
44
+ }
45
+ }
46
+ if receiver == nil {
47
+ return
48
+ }
49
+ t := ctx.Checker.GetTypeAtLocation(receiver)
50
+ if !typeIsUnsafeAny(t) {
51
+ return
52
+ }
53
+ ctx.Report(node, "Unsafe member access on a value typed as `any`. Narrow the receiver to a concrete type before reading a property.")
54
+ }
55
+
56
+ func init() {
57
+ Register(noUnsafeMemberAccess{})
58
+ }
@@ -0,0 +1,126 @@
1
+ // typescript/no-unsafe-return: a `return X;` whose expression carries
2
+ // the `any` type from a function whose declared return shape is
3
+ // concrete leaks `any` past the type boundary. Callers see the declared
4
+ // shape, lose every downstream type check on the value, and the bug
5
+ // that introduced the `any` migrates to whichever site reads the result.
6
+ // typescript-eslint:
7
+ // https://typescript-eslint.io/rules/no-unsafe-return/
8
+ //
9
+ // Type-aware. Without a Checker we cannot tell `any` apart from a
10
+ // concrete shape, so Context.Checker == nil short-circuits the visit
11
+ // the same way `no-floating-promises` and `restrict-plus-operands` do.
12
+ //
13
+ // The rule walks each `return` to its enclosing function-like
14
+ // declaration, asks the Checker for that function's signature, and
15
+ // compares the declared return type against the expression type:
16
+ //
17
+ // - the expression must be `any`-typed (raw `any`, not `unknown`);
18
+ // - the declared return type must be concrete — `any`, `unknown`, and
19
+ // `void` are deliberately exempt because they advertise the same
20
+ // looseness at the boundary and a strict rejection would explode
21
+ // on every generic helper that propagates `unknown`.
22
+ package linthost
23
+
24
+ import (
25
+ shimast "github.com/microsoft/typescript-go/shim/ast"
26
+ shimchecker "github.com/microsoft/typescript-go/shim/checker"
27
+ )
28
+
29
+ type noUnsafeReturn struct{}
30
+
31
+ func (noUnsafeReturn) Name() string { return "typescript/no-unsafe-return" }
32
+ func (noUnsafeReturn) NeedsTypeChecker() bool {
33
+ return true
34
+ }
35
+ func (noUnsafeReturn) Visits() []shimast.Kind {
36
+ return []shimast.Kind{shimast.KindReturnStatement}
37
+ }
38
+ func (noUnsafeReturn) Check(ctx *Context, node *shimast.Node) {
39
+ if ctx.Checker == nil {
40
+ return
41
+ }
42
+ ret := node.AsReturnStatement()
43
+ if ret == nil || ret.Expression == nil {
44
+ return
45
+ }
46
+ fn := noUnsafeReturnEnclosingFunction(node)
47
+ if fn == nil {
48
+ return
49
+ }
50
+ sig := ctx.Checker.GetSignatureFromDeclaration(fn)
51
+ if sig == nil {
52
+ return
53
+ }
54
+ declared := ctx.Checker.GetReturnTypeOfSignature(sig)
55
+ if declared == nil {
56
+ return
57
+ }
58
+ if !noUnsafeReturnIsConcrete(declared) {
59
+ return
60
+ }
61
+ exprType := ctx.Checker.GetTypeAtLocation(ret.Expression)
62
+ if exprType == nil {
63
+ return
64
+ }
65
+ if !noUnsafeReturnIsAny(exprType) {
66
+ return
67
+ }
68
+ ctx.Report(ret.Expression, "Unsafe return of `any` value from function with a concrete declared return type. The `any` leaks past the type boundary and disables downstream type checks.")
69
+ }
70
+
71
+ // noUnsafeReturnEnclosingFunction walks up the parent chain to the
72
+ // nearest function-like declaration that owns this `return`. Nested
73
+ // functions establish their own return scope, so the walk stops at the
74
+ // first function-like ancestor — mirroring the `consistent-return`
75
+ // scope rule already established in this package.
76
+ func noUnsafeReturnEnclosingFunction(node *shimast.Node) *shimast.Node {
77
+ for cur := node.Parent; cur != nil; cur = cur.Parent {
78
+ if isFunctionLikeKind(cur) {
79
+ return cur
80
+ }
81
+ }
82
+ return nil
83
+ }
84
+
85
+ // noUnsafeReturnIsConcrete reports whether the declared return type is
86
+ // strict enough to be worth protecting. `any`, `unknown`, and `void`
87
+ // are the three shapes that explicitly advertise looseness — the
88
+ // upstream rule exempts them so generic helpers that propagate
89
+ // `unknown` and side-effect functions that return `void` do not light
90
+ // up everywhere. Unions are concrete only when every constituent is.
91
+ func noUnsafeReturnIsConcrete(t *shimchecker.Type) bool {
92
+ if t == nil {
93
+ return false
94
+ }
95
+ flags := t.Flags()
96
+ if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsVoid) != 0 {
97
+ return false
98
+ }
99
+ if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
100
+ for _, part := range t.Types() {
101
+ if part == nil {
102
+ continue
103
+ }
104
+ if !noUnsafeReturnIsConcrete(part) {
105
+ return false
106
+ }
107
+ }
108
+ return true
109
+ }
110
+ return true
111
+ }
112
+
113
+ // noUnsafeReturnIsAny reports whether t is the raw `any` type. The
114
+ // upstream rule treats `unknown` as a safe escape hatch — values
115
+ // returned as `unknown` cannot be used without further narrowing, so
116
+ // they don't leak silently — and only flags the lossy `any` case.
117
+ func noUnsafeReturnIsAny(t *shimchecker.Type) bool {
118
+ if t == nil {
119
+ return false
120
+ }
121
+ return t.Flags()&shimchecker.TypeFlagsAny != 0
122
+ }
123
+
124
+ func init() {
125
+ Register(noUnsafeReturn{})
126
+ }
@@ -0,0 +1,81 @@
1
+ // typescript/no-unsafe-unary-minus: the unary `-` operator coerces its
2
+ // operand via `Number()` at runtime, so strings, booleans, and plain
3
+ // objects silently produce `NaN`, `0`, `-1`, or `-NaN` instead of a
4
+ // negated number. The rule restricts the operator to operands whose
5
+ // static type is number-like or bigint-like — the two shapes where the
6
+ // negation is a real arithmetic operation rather than a hidden
7
+ // coercion. typescript-eslint:
8
+ // https://typescript-eslint.io/rules/no-unsafe-unary-minus/
9
+ //
10
+ // Type-aware. Without a Checker the rule cannot tell `-x` on a number
11
+ // apart from `-x` on a string, so Context.Checker == nil short-circuits
12
+ // the visit the same way every other type-aware rule in this package
13
+ // does. `any` / `unknown` / `never` pass through to match the upstream
14
+ // `allowAny`-style defaults that keep generic helpers quiet.
15
+ package linthost
16
+
17
+ import (
18
+ shimast "github.com/microsoft/typescript-go/shim/ast"
19
+ shimchecker "github.com/microsoft/typescript-go/shim/checker"
20
+ )
21
+
22
+ type noUnsafeUnaryMinus struct{}
23
+
24
+ func (noUnsafeUnaryMinus) Name() string { return "typescript/no-unsafe-unary-minus" }
25
+ func (noUnsafeUnaryMinus) NeedsTypeChecker() bool {
26
+ return true
27
+ }
28
+ func (noUnsafeUnaryMinus) Visits() []shimast.Kind {
29
+ return []shimast.Kind{shimast.KindPrefixUnaryExpression}
30
+ }
31
+ func (noUnsafeUnaryMinus) Check(ctx *Context, node *shimast.Node) {
32
+ if ctx.Checker == nil {
33
+ return
34
+ }
35
+ expr := node.AsPrefixUnaryExpression()
36
+ if expr == nil || expr.Operator != shimast.KindMinusToken || expr.Operand == nil {
37
+ return
38
+ }
39
+ t := ctx.Checker.GetTypeAtLocation(expr.Operand)
40
+ if t == nil {
41
+ return
42
+ }
43
+ if noUnsafeUnaryMinusIsNumeric(t) {
44
+ return
45
+ }
46
+ ctx.Report(node, "Unary `-` requires a number-like or bigint-like operand. Other shapes are silently coerced via `Number(x)` and almost always indicate a bug.")
47
+ }
48
+
49
+ // noUnsafeUnaryMinusIsNumeric reports whether t is provably number-like
50
+ // or bigint-like. `any` / `unknown` / `never` are treated as numeric to
51
+ // keep the rule silent on generic helpers and untyped boundaries —
52
+ // matching the upstream `allowAny` posture. Unions and intersections
53
+ // must have every constituent numeric for the whole type to count.
54
+ func noUnsafeUnaryMinusIsNumeric(t *shimchecker.Type) bool {
55
+ if t == nil {
56
+ return true
57
+ }
58
+ flags := t.Flags()
59
+ if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
60
+ return true
61
+ }
62
+ if flags&(shimchecker.TypeFlagsNumberLike|shimchecker.TypeFlagsBigIntLike) != 0 {
63
+ return true
64
+ }
65
+ if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
66
+ for _, part := range t.Types() {
67
+ if part == nil {
68
+ continue
69
+ }
70
+ if !noUnsafeUnaryMinusIsNumeric(part) {
71
+ return false
72
+ }
73
+ }
74
+ return true
75
+ }
76
+ return false
77
+ }
78
+
79
+ func init() {
80
+ Register(noUnsafeUnaryMinus{})
81
+ }