@ttsc/lint 0.13.0 → 0.14.0-dev.20260528

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (467) hide show
  1. package/README.md +948 -69
  2. package/lib/defaultFormat.d.ts +9 -6
  3. package/lib/defaultFormat.js +9 -6
  4. package/lib/defaultFormat.js.map +1 -1
  5. package/lib/index.d.ts +46 -0
  6. package/lib/index.js +60 -37
  7. package/lib/index.js.map +1 -1
  8. package/lib/structures/ITtscLintConfig.d.ts +12 -6
  9. package/lib/structures/{ITtscLintFormatConfig.d.ts → ITtscLintFormat.d.ts} +2 -2
  10. package/lib/structures/{TtscLintRuleMap.js → ITtscLintFormat.js} +1 -1
  11. package/lib/structures/ITtscLintFormat.js.map +1 -0
  12. package/lib/structures/TtscLintRuleSetting.d.ts +49 -0
  13. package/lib/structures/{TtscLintRuleOptions.js → TtscLintRuleSetting.js} +1 -1
  14. package/lib/structures/TtscLintRuleSetting.js.map +1 -0
  15. package/lib/structures/index.d.ts +3 -4
  16. package/lib/structures/index.js +3 -4
  17. package/lib/structures/index.js.map +1 -1
  18. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +104 -0
  19. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +14 -0
  20. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
  21. package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +79 -0
  22. package/lib/structures/rules/ITtscLintBoundariesRules.js +3 -0
  23. package/lib/structures/rules/ITtscLintBoundariesRules.js.map +1 -0
  24. package/lib/structures/rules/ITtscLintContributorRules.d.ts +17 -0
  25. package/lib/structures/rules/ITtscLintContributorRules.js +3 -0
  26. package/lib/structures/rules/ITtscLintContributorRules.js.map +1 -0
  27. package/lib/structures/rules/ITtscLintCoreRules.d.ts +1257 -0
  28. package/lib/structures/{ITtscLintFormatConfig.js → rules/ITtscLintCoreRules.js} +1 -1
  29. package/lib/structures/rules/ITtscLintCoreRules.js.map +1 -0
  30. package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +17 -0
  31. package/lib/structures/rules/ITtscLintCypressRuleOptions.js +10 -0
  32. package/lib/structures/rules/ITtscLintCypressRuleOptions.js.map +1 -0
  33. package/lib/structures/rules/ITtscLintCypressRules.d.ts +129 -0
  34. package/lib/structures/rules/ITtscLintCypressRules.js +3 -0
  35. package/lib/structures/rules/ITtscLintCypressRules.js.map +1 -0
  36. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +157 -0
  37. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +13 -0
  38. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js.map +1 -0
  39. package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +167 -0
  40. package/lib/structures/rules/ITtscLintFunctionalRules.js +3 -0
  41. package/lib/structures/rules/ITtscLintFunctionalRules.js.map +1 -0
  42. package/lib/structures/rules/ITtscLintJestRules.d.ts +201 -0
  43. package/lib/structures/rules/ITtscLintJestRules.js +3 -0
  44. package/lib/structures/rules/ITtscLintJestRules.js.map +1 -0
  45. package/lib/structures/rules/ITtscLintJsdocRules.d.ts +140 -0
  46. package/lib/structures/rules/ITtscLintJsdocRules.js +3 -0
  47. package/lib/structures/rules/ITtscLintJsdocRules.js.map +1 -0
  48. package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +302 -0
  49. package/lib/structures/rules/ITtscLintJsxA11yRules.js +3 -0
  50. package/lib/structures/rules/ITtscLintJsxA11yRules.js.map +1 -0
  51. package/lib/structures/rules/ITtscLintNextjsRules.d.ts +185 -0
  52. package/lib/structures/rules/ITtscLintNextjsRules.js +3 -0
  53. package/lib/structures/rules/ITtscLintNextjsRules.js.map +1 -0
  54. package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +330 -0
  55. package/lib/structures/rules/ITtscLintPlaywrightRules.js +3 -0
  56. package/lib/structures/rules/ITtscLintPlaywrightRules.js.map +1 -0
  57. package/lib/structures/rules/ITtscLintPromiseRules.d.ts +188 -0
  58. package/lib/structures/rules/ITtscLintPromiseRules.js +3 -0
  59. package/lib/structures/rules/ITtscLintPromiseRules.js.map +1 -0
  60. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +18 -0
  61. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js +8 -0
  62. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js.map +1 -0
  63. package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +51 -0
  64. package/lib/structures/rules/ITtscLintReactPerfRules.js +3 -0
  65. package/lib/structures/rules/ITtscLintReactPerfRules.js.map +1 -0
  66. package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +39 -0
  67. package/lib/structures/rules/ITtscLintReactRuleOptions.js +12 -0
  68. package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
  69. package/lib/structures/rules/ITtscLintReactRules.d.ts +289 -0
  70. package/lib/structures/rules/ITtscLintReactRules.js +3 -0
  71. package/lib/structures/rules/ITtscLintReactRules.js.map +1 -0
  72. package/lib/structures/rules/ITtscLintRegexpRules.d.ts +190 -0
  73. package/lib/structures/rules/ITtscLintRegexpRules.js +3 -0
  74. package/lib/structures/rules/ITtscLintRegexpRules.js.map +1 -0
  75. package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +66 -0
  76. package/lib/structures/rules/ITtscLintRuleOptionsMap.js +3 -0
  77. package/lib/structures/rules/ITtscLintRuleOptionsMap.js.map +1 -0
  78. package/lib/structures/rules/ITtscLintRules.d.ts +55 -0
  79. package/lib/structures/{TtscLintRule.js → rules/ITtscLintRules.js} +1 -1
  80. package/lib/structures/rules/ITtscLintRules.js.map +1 -0
  81. package/lib/structures/rules/ITtscLintSecurityRules.d.ts +148 -0
  82. package/lib/structures/rules/ITtscLintSecurityRules.js +3 -0
  83. package/lib/structures/rules/ITtscLintSecurityRules.js.map +1 -0
  84. package/lib/structures/rules/ITtscLintSolidRules.d.ts +181 -0
  85. package/lib/structures/rules/ITtscLintSolidRules.js +3 -0
  86. package/lib/structures/rules/ITtscLintSolidRules.js.map +1 -0
  87. package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +21 -0
  88. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js +9 -0
  89. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js.map +1 -0
  90. package/lib/structures/rules/ITtscLintStorybookRules.d.ts +174 -0
  91. package/lib/structures/rules/ITtscLintStorybookRules.js +3 -0
  92. package/lib/structures/rules/ITtscLintStorybookRules.js.map +1 -0
  93. package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +94 -0
  94. package/lib/structures/rules/ITtscLintTanstackQueryRules.js +3 -0
  95. package/lib/structures/rules/ITtscLintTanstackQueryRules.js.map +1 -0
  96. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +22 -0
  97. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js +10 -0
  98. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js.map +1 -0
  99. package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +310 -0
  100. package/lib/structures/rules/ITtscLintTestingLibraryRules.js +3 -0
  101. package/lib/structures/rules/ITtscLintTestingLibraryRules.js.map +1 -0
  102. package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +1132 -0
  103. package/lib/structures/rules/ITtscLintTypeScriptRules.js +3 -0
  104. package/lib/structures/rules/ITtscLintTypeScriptRules.js.map +1 -0
  105. package/lib/structures/rules/ITtscLintUnicornRules.d.ts +997 -0
  106. package/lib/structures/rules/ITtscLintUnicornRules.js +3 -0
  107. package/lib/structures/rules/ITtscLintUnicornRules.js.map +1 -0
  108. package/lib/structures/rules/ITtscLintVitestRules.d.ts +141 -0
  109. package/lib/structures/rules/ITtscLintVitestRules.js +3 -0
  110. package/lib/structures/rules/ITtscLintVitestRules.js.map +1 -0
  111. package/lib/structures/rules/index.d.ts +31 -0
  112. package/lib/structures/rules/index.js +48 -0
  113. package/lib/structures/rules/index.js.map +1 -0
  114. package/linthost/ast_helpers.go +30 -5
  115. package/linthost/compile.go +33 -2
  116. package/linthost/config.go +48 -17
  117. package/linthost/config_format.go +9 -9
  118. package/linthost/directives.go +67 -25
  119. package/linthost/dispatch.go +14 -3
  120. package/linthost/engine.go +160 -40
  121. package/linthost/fix.go +2 -2
  122. package/linthost/flags_gen.go +17 -15
  123. package/linthost/host.go +40 -3
  124. package/linthost/lsp.go +747 -0
  125. package/linthost/print_dispatch.go +2 -2
  126. package/linthost/print_nodes_function.go +2 -2
  127. package/linthost/print_nodes_object.go +1 -1
  128. package/linthost/rule_names.go +14 -0
  129. package/linthost/rules_arrays.go +2 -2
  130. package/linthost/rules_boundaries.go +532 -0
  131. package/linthost/rules_camelcase.go +133 -0
  132. package/linthost/rules_complexity.go +94 -0
  133. package/linthost/rules_consistent_return.go +130 -0
  134. package/linthost/rules_console.go +1 -1
  135. package/linthost/rules_core_extra.go +739 -0
  136. package/linthost/rules_curly.go +70 -0
  137. package/linthost/rules_cypress.go +608 -0
  138. package/linthost/rules_debugger.go +2 -2
  139. package/linthost/rules_default_case.go +39 -0
  140. package/linthost/rules_default_case_last.go +46 -0
  141. package/linthost/rules_dupes.go +3 -3
  142. package/linthost/rules_empty.go +3 -3
  143. package/linthost/rules_escape.go +44 -24
  144. package/linthost/rules_eval.go +2 -2
  145. package/linthost/rules_finally.go +2 -2
  146. package/linthost/rules_format_jsdoc.go +1 -1
  147. package/linthost/rules_format_print_width.go +9 -9
  148. package/linthost/rules_format_quotes.go +1 -1
  149. package/linthost/rules_format_semi.go +1 -1
  150. package/linthost/rules_format_sort_imports.go +1 -1
  151. package/linthost/rules_format_trailing_comma.go +1 -1
  152. package/linthost/rules_functional.go +967 -0
  153. package/linthost/rules_gap.go +24 -45
  154. package/linthost/rules_grouped_accessor_pairs.go +87 -0
  155. package/linthost/rules_guard_for_in.go +198 -0
  156. package/linthost/rules_id_length.go +77 -0
  157. package/linthost/rules_imports.go +70 -2
  158. package/linthost/rules_init_declarations.go +53 -0
  159. package/linthost/rules_jest.go +618 -0
  160. package/linthost/rules_jsdoc.go +502 -0
  161. package/linthost/rules_jsx_a11y.go +1264 -0
  162. package/linthost/rules_logic.go +12 -12
  163. package/linthost/rules_loops.go +1 -1
  164. package/linthost/rules_max_classes_per_file.go +58 -0
  165. package/linthost/rules_max_depth.go +83 -0
  166. package/linthost/rules_max_lines.go +101 -0
  167. package/linthost/rules_max_lines_per_function.go +57 -0
  168. package/linthost/rules_max_nested_callbacks.go +61 -0
  169. package/linthost/rules_max_params.go +49 -0
  170. package/linthost/rules_max_statements.go +59 -0
  171. package/linthost/rules_misc.go +1 -1
  172. package/linthost/rules_nextjs.go +697 -0
  173. package/linthost/rules_no_else_return.go +75 -0
  174. package/linthost/rules_no_empty_named_blocks.go +91 -0
  175. package/linthost/rules_no_extend_native.go +51 -0
  176. package/linthost/rules_no_import_assign.go +140 -0
  177. package/linthost/rules_no_invalid_this.go +52 -0
  178. package/linthost/rules_no_loop_func.go +85 -0
  179. package/linthost/rules_no_magic_numbers.go +123 -0
  180. package/linthost/rules_no_mixed_operators.go +80 -0
  181. package/linthost/rules_no_param_reassign.go +98 -0
  182. package/linthost/rules_no_redeclare.go +270 -0
  183. package/linthost/rules_no_restricted_imports.go +105 -0
  184. package/linthost/rules_no_restricted_syntax.go +49 -0
  185. package/linthost/rules_no_shadow.go +147 -0
  186. package/linthost/rules_no_unreachable.go +77 -0
  187. package/linthost/rules_no_useless_assignment.go +120 -0
  188. package/linthost/rules_no_useless_constructor.go +245 -0
  189. package/linthost/rules_no_useless_return.go +51 -0
  190. package/linthost/rules_params.go +1 -1
  191. package/linthost/rules_playwright.go +788 -0
  192. package/linthost/rules_prefer_arrow_callback.go +124 -0
  193. package/linthost/rules_prefer_destructuring.go +98 -0
  194. package/linthost/rules_prefer_named_capture_group.go +129 -0
  195. package/linthost/rules_prefer_rest_params.go +94 -0
  196. package/linthost/rules_problems.go +41 -30
  197. package/linthost/rules_promise.go +1128 -73
  198. package/linthost/rules_protos.go +2 -2
  199. package/linthost/rules_react.go +773 -0
  200. package/linthost/rules_react_extras.go +227 -0
  201. package/linthost/rules_react_hooks.go +848 -0
  202. package/linthost/rules_react_perf.go +293 -0
  203. package/linthost/rules_react_refresh.go +583 -0
  204. package/linthost/rules_regexp.go +410 -0
  205. package/linthost/rules_security.go +830 -0
  206. package/linthost/rules_self.go +2 -2
  207. package/linthost/rules_solid.go +1073 -0
  208. package/linthost/rules_sort_imports.go +69 -0
  209. package/linthost/rules_sort_keys.go +134 -0
  210. package/linthost/rules_storybook.go +1176 -0
  211. package/linthost/rules_strings.go +4 -4
  212. package/linthost/rules_suggestions.go +38 -38
  213. package/linthost/rules_tanstack_query.go +844 -0
  214. package/linthost/rules_testing_library.go +1204 -0
  215. package/linthost/rules_throw.go +1 -1
  216. package/linthost/rules_ts.go +19 -19
  217. package/linthost/rules_ts_async.go +399 -0
  218. package/linthost/rules_ts_class_literal_property_style.go +115 -0
  219. package/linthost/rules_ts_consistent_type_exports.go +256 -0
  220. package/linthost/rules_ts_explicit_function_return_type.go +67 -0
  221. package/linthost/rules_ts_extra.go +155 -36
  222. package/linthost/rules_ts_no_base_to_string.go +218 -0
  223. package/linthost/rules_ts_no_confusing_void.go +72 -0
  224. package/linthost/rules_ts_no_deprecated.go +195 -0
  225. package/linthost/rules_ts_no_for_in_array.go +84 -0
  226. package/linthost/rules_ts_no_magic_numbers.go +124 -0
  227. package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
  228. package/linthost/rules_ts_no_misused_spread.go +104 -0
  229. package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
  230. package/linthost/rules_ts_no_restricted_types.go +62 -0
  231. package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
  232. package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
  233. package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
  234. package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
  235. package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
  236. package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
  237. package/linthost/rules_ts_no_unsafe_argument.go +82 -0
  238. package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
  239. package/linthost/rules_ts_no_unsafe_call.go +82 -0
  240. package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
  241. package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
  242. package/linthost/rules_ts_no_unsafe_return.go +126 -0
  243. package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
  244. package/linthost/rules_ts_no_useless_constructor.go +52 -0
  245. package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
  246. package/linthost/rules_ts_parameter_properties.go +38 -0
  247. package/linthost/rules_ts_prefer_find.go +178 -0
  248. package/linthost/rules_ts_prefer_includes.go +255 -0
  249. package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
  250. package/linthost/rules_ts_prefer_optional_chain.go +228 -0
  251. package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
  252. package/linthost/rules_ts_prefer_readonly.go +73 -0
  253. package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
  254. package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
  255. package/linthost/rules_ts_prefer_return_this_type.go +135 -0
  256. package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
  257. package/linthost/rules_ts_promise_function_async.go +77 -0
  258. package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
  259. package/linthost/rules_ts_require_array_sort_compare.go +96 -0
  260. package/linthost/rules_ts_restrict_plus_operands.go +127 -0
  261. package/linthost/rules_ts_restrict_template_expressions.go +95 -0
  262. package/linthost/rules_ts_simple.go +387 -0
  263. package/linthost/rules_ts_sort_type_constituents.go +144 -0
  264. package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
  265. package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
  266. package/linthost/rules_ts_unbound_method.go +126 -0
  267. package/linthost/rules_tsdoc.go +136 -0
  268. package/linthost/rules_unicorn_better_regex.go +27 -0
  269. package/linthost/rules_unicorn_catch_error_name.go +46 -0
  270. package/linthost/rules_unicorn_consistent_assert.go +47 -0
  271. package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
  272. package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
  273. package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
  274. package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
  275. package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
  276. package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
  277. package/linthost/rules_unicorn_custom_error_definition.go +138 -0
  278. package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
  279. package/linthost/rules_unicorn_error_message.go +64 -0
  280. package/linthost/rules_unicorn_escape_case.go +51 -0
  281. package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
  282. package/linthost/rules_unicorn_explicit_length_check.go +88 -0
  283. package/linthost/rules_unicorn_filename_case.go +29 -0
  284. package/linthost/rules_unicorn_import_style.go +28 -0
  285. package/linthost/rules_unicorn_isolated_functions.go +29 -0
  286. package/linthost/rules_unicorn_new_for_builtins.go +87 -0
  287. package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
  288. package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
  289. package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
  290. package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
  291. package/linthost/rules_unicorn_no_array_for_each.go +40 -0
  292. package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
  293. package/linthost/rules_unicorn_no_array_reduce.go +41 -0
  294. package/linthost/rules_unicorn_no_array_reverse.go +44 -0
  295. package/linthost/rules_unicorn_no_array_sort.go +43 -0
  296. package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
  297. package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
  298. package/linthost/rules_unicorn_no_console_spaces.go +61 -0
  299. package/linthost/rules_unicorn_no_document_cookie.go +41 -0
  300. package/linthost/rules_unicorn_no_empty_file.go +44 -0
  301. package/linthost/rules_unicorn_no_for_loop.go +102 -0
  302. package/linthost/rules_unicorn_no_hex_escape.go +42 -0
  303. package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
  304. package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
  305. package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
  306. package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
  307. package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
  308. package/linthost/rules_unicorn_no_lonely_if.go +44 -0
  309. package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
  310. package/linthost/rules_unicorn_no_named_default.go +54 -0
  311. package/linthost/rules_unicorn_no_negated_condition.go +85 -0
  312. package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
  313. package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
  314. package/linthost/rules_unicorn_no_new_array.go +30 -0
  315. package/linthost/rules_unicorn_no_new_buffer.go +31 -0
  316. package/linthost/rules_unicorn_no_null.go +24 -0
  317. package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
  318. package/linthost/rules_unicorn_no_process_exit.go +43 -0
  319. package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
  320. package/linthost/rules_unicorn_no_static_only_class.go +56 -0
  321. package/linthost/rules_unicorn_no_thenable.go +74 -0
  322. package/linthost/rules_unicorn_no_this_assignment.go +35 -0
  323. package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
  324. package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
  325. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
  326. package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
  327. package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
  328. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
  329. package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
  330. package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
  331. package/linthost/rules_unicorn_no_unused_properties.go +30 -0
  332. package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
  333. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
  334. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
  335. package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
  336. package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
  337. package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
  338. package/linthost/rules_unicorn_no_useless_spread.go +67 -0
  339. package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
  340. package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
  341. package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
  342. package/linthost/rules_unicorn_number_literal_case.go +69 -0
  343. package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
  344. package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
  345. package/linthost/rules_unicorn_prefer_array_find.go +51 -0
  346. package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
  347. package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
  348. package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
  349. package/linthost/rules_unicorn_prefer_array_some.go +67 -0
  350. package/linthost/rules_unicorn_prefer_at.go +77 -0
  351. package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
  352. package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
  353. package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
  354. package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
  355. package/linthost/rules_unicorn_prefer_code_point.go +49 -0
  356. package/linthost/rules_unicorn_prefer_date_now.go +78 -0
  357. package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
  358. package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
  359. package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
  360. package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
  361. package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
  362. package/linthost/rules_unicorn_prefer_event_target.go +36 -0
  363. package/linthost/rules_unicorn_prefer_export_from.go +129 -0
  364. package/linthost/rules_unicorn_prefer_global_this.go +127 -0
  365. package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
  366. package/linthost/rules_unicorn_prefer_includes.go +149 -0
  367. package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
  368. package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
  369. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
  370. package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
  371. package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
  372. package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
  373. package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
  374. package/linthost/rules_unicorn_prefer_module.go +50 -0
  375. package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
  376. package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
  377. package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
  378. package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
  379. package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
  380. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
  381. package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
  382. package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
  383. package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
  384. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
  385. package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
  386. package/linthost/rules_unicorn_prefer_set_has.go +42 -0
  387. package/linthost/rules_unicorn_prefer_set_size.go +48 -0
  388. package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
  389. package/linthost/rules_unicorn_prefer_single_call.go +96 -0
  390. package/linthost/rules_unicorn_prefer_spread.go +51 -0
  391. package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
  392. package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
  393. package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
  394. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
  395. package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
  396. package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
  397. package/linthost/rules_unicorn_prefer_switch.go +103 -0
  398. package/linthost/rules_unicorn_prefer_ternary.go +71 -0
  399. package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
  400. package/linthost/rules_unicorn_prefer_type_error.go +127 -0
  401. package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
  402. package/linthost/rules_unicorn_relative_url_style.go +49 -0
  403. package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
  404. package/linthost/rules_unicorn_require_module_attributes.go +54 -0
  405. package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
  406. package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
  407. package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
  408. package/linthost/rules_unicorn_string_content.go +27 -0
  409. package/linthost/rules_unicorn_switch_case_braces.go +42 -0
  410. package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
  411. package/linthost/rules_unicorn_template_indent.go +28 -0
  412. package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
  413. package/linthost/rules_unicorn_throw_new_error.go +61 -0
  414. package/linthost/rules_var.go +10 -4
  415. package/linthost/rules_vitest.go +568 -0
  416. package/package.json +3 -3
  417. package/plugin/main.go +49 -3
  418. package/rule/astutil/astutil.go +10 -3
  419. package/rule/rule.go +12 -10
  420. package/src/defaultFormat.ts +11 -8
  421. package/src/index.ts +65 -43
  422. package/src/structures/ITtscLintConfig.ts +12 -6
  423. package/src/structures/{ITtscLintFormatConfig.ts → ITtscLintFormat.ts} +2 -2
  424. package/src/structures/TtscLintRuleSetting.ts +55 -0
  425. package/src/structures/index.ts +3 -4
  426. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +128 -0
  427. package/src/structures/rules/ITtscLintBoundariesRules.ts +95 -0
  428. package/src/structures/rules/ITtscLintContributorRules.ts +21 -0
  429. package/src/structures/rules/ITtscLintCoreRules.ts +1406 -0
  430. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
  431. package/src/structures/rules/ITtscLintCypressRules.ts +145 -0
  432. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +213 -0
  433. package/src/structures/rules/ITtscLintFunctionalRules.ts +202 -0
  434. package/src/structures/rules/ITtscLintJestRules.ts +220 -0
  435. package/src/structures/rules/ITtscLintJsdocRules.ts +153 -0
  436. package/src/structures/rules/ITtscLintJsxA11yRules.ts +339 -0
  437. package/src/structures/rules/ITtscLintNextjsRules.ts +206 -0
  438. package/src/structures/rules/ITtscLintPlaywrightRules.ts +361 -0
  439. package/src/structures/rules/ITtscLintPromiseRules.ts +205 -0
  440. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
  441. package/src/structures/rules/ITtscLintReactPerfRules.ts +55 -0
  442. package/src/structures/rules/ITtscLintReactRuleOptions.ts +43 -0
  443. package/src/structures/rules/ITtscLintReactRules.ts +321 -0
  444. package/src/structures/rules/ITtscLintRegexpRules.ts +212 -0
  445. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +89 -0
  446. package/src/structures/rules/ITtscLintRules.ts +77 -0
  447. package/src/structures/rules/ITtscLintSecurityRules.ts +162 -0
  448. package/src/structures/rules/ITtscLintSolidRules.ts +202 -0
  449. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +23 -0
  450. package/src/structures/rules/ITtscLintStorybookRules.ts +193 -0
  451. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +102 -0
  452. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +24 -0
  453. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +342 -0
  454. package/src/structures/rules/ITtscLintTypeScriptRules.ts +1230 -0
  455. package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
  456. package/src/structures/rules/ITtscLintVitestRules.ts +154 -0
  457. package/src/structures/rules/index.ts +31 -0
  458. package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
  459. package/lib/structures/TtscLintRule.d.ts +0 -17
  460. package/lib/structures/TtscLintRule.js.map +0 -1
  461. package/lib/structures/TtscLintRuleMap.d.ts +0 -46
  462. package/lib/structures/TtscLintRuleMap.js.map +0 -1
  463. package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
  464. package/lib/structures/TtscLintRuleOptions.js.map +0 -1
  465. package/src/structures/TtscLintRule.ts +0 -160
  466. package/src/structures/TtscLintRuleMap.ts +0 -55
  467. package/src/structures/TtscLintRuleOptions.ts +0 -151
@@ -0,0 +1,113 @@
1
+ // AST-only baseline of typescript-eslint's `no-redundant-type-constituents`.
2
+ //
3
+ // The rule reports type union/intersection constituents that the type
4
+ // system would absorb — `string | any` collapses to `any`, `T & never`
5
+ // collapses to `never`, `T & unknown` collapses to `T`, and repeated
6
+ // constituents add nothing.
7
+ //
8
+ // Without the Checker the rule can only see what the type node declares,
9
+ // so the baseline covers the cases where one operand is the literal
10
+ // `any` / `unknown` / `never` keyword, plus duplicate operands matched
11
+ // by textual identity. Subset relations such as `string | "foo"` and
12
+ // generic alias resolution still need the type-aware path.
13
+ // https://typescript-eslint.io/rules/no-redundant-type-constituents/
14
+ package linthost
15
+
16
+ import (
17
+ "strings"
18
+
19
+ shimast "github.com/microsoft/typescript-go/shim/ast"
20
+ )
21
+
22
+ type noRedundantTypeConstituents struct{}
23
+
24
+ func (noRedundantTypeConstituents) Name() string {
25
+ return "typescript/no-redundant-type-constituents"
26
+ }
27
+ func (noRedundantTypeConstituents) Visits() []shimast.Kind {
28
+ return []shimast.Kind{shimast.KindUnionType, shimast.KindIntersectionType}
29
+ }
30
+ func (noRedundantTypeConstituents) Check(ctx *Context, node *shimast.Node) {
31
+ types := unionOrIntersectionTypes(node)
32
+ if len(types) < 2 {
33
+ return
34
+ }
35
+ isUnion := node.Kind == shimast.KindUnionType
36
+ hasAny := containsKeywordType(types, shimast.KindAnyKeyword)
37
+ hasUnknown := containsKeywordType(types, shimast.KindUnknownKeyword)
38
+ hasNever := containsKeywordType(types, shimast.KindNeverKeyword)
39
+ label := "intersection"
40
+ if isUnion {
41
+ label = "union"
42
+ }
43
+ seen := map[string]bool{}
44
+ for _, t := range types {
45
+ if t == nil {
46
+ continue
47
+ }
48
+ switch {
49
+ case isUnion && (hasAny || hasUnknown) && t.Kind != shimast.KindAnyKeyword && t.Kind != shimast.KindUnknownKeyword:
50
+ // `T | any` / `T | unknown` — every non-top constituent is
51
+ // absorbed. `any` takes precedence in the message because
52
+ // `any` also subsumes `unknown`.
53
+ absorbing := "unknown"
54
+ if hasAny {
55
+ absorbing = "any"
56
+ }
57
+ ctx.Report(t, "Constituent is overridden by `"+absorbing+"` in the surrounding union.")
58
+ case isUnion && hasNever && t.Kind == shimast.KindNeverKeyword:
59
+ ctx.Report(t, "`never` is absorbed by the surrounding union.")
60
+ case !isUnion && hasNever:
61
+ // `T & never` collapses to `never` for every constituent.
62
+ ctx.Report(t, "Intersection with `never` collapses to `never`.")
63
+ case !isUnion && hasUnknown && t.Kind == shimast.KindUnknownKeyword:
64
+ ctx.Report(t, "`unknown` is absorbed by the surrounding intersection.")
65
+ }
66
+ // Duplicate by textual identity — fire on the second occurrence
67
+ // so the first declaration stays unblamed.
68
+ key := strings.TrimSpace(nodeText(ctx.File, t))
69
+ if key == "" {
70
+ continue
71
+ }
72
+ if seen[key] {
73
+ ctx.Report(t, "Duplicate constituent in "+label+".")
74
+ continue
75
+ }
76
+ seen[key] = true
77
+ }
78
+ }
79
+
80
+ // unionOrIntersectionTypes returns the constituent type nodes of a union
81
+ // or intersection type node, or nil for other shapes.
82
+ func unionOrIntersectionTypes(node *shimast.Node) []*shimast.Node {
83
+ if node == nil {
84
+ return nil
85
+ }
86
+ switch node.Kind {
87
+ case shimast.KindUnionType:
88
+ if u := node.AsUnionTypeNode(); u != nil && u.Types != nil {
89
+ return u.Types.Nodes
90
+ }
91
+ case shimast.KindIntersectionType:
92
+ if i := node.AsIntersectionTypeNode(); i != nil && i.Types != nil {
93
+ return i.Types.Nodes
94
+ }
95
+ }
96
+ return nil
97
+ }
98
+
99
+ // containsKeywordType reports whether `types` contains a direct keyword
100
+ // type node of `kind` — `any`, `unknown`, or `never` in type position
101
+ // parse as bare keyword nodes rather than identifiers.
102
+ func containsKeywordType(types []*shimast.Node, kind shimast.Kind) bool {
103
+ for _, t := range types {
104
+ if t != nil && t.Kind == kind {
105
+ return true
106
+ }
107
+ }
108
+ return false
109
+ }
110
+
111
+ func init() {
112
+ Register(noRedundantTypeConstituents{})
113
+ }
@@ -0,0 +1,62 @@
1
+ // AST-only baseline of typescript-eslint's `no-restricted-types`.
2
+ //
3
+ // The upstream rule is fully configurable — users supply a map from
4
+ // banned type name to a custom message and (optionally) a rewrite hint.
5
+ // Without the rule-options plumbing, this baseline ships a fixed
6
+ // default set that covers the five built-in wrapper / global types
7
+ // that almost every team forbids: `Object`, `Function`, `Number`,
8
+ // `String`, and `Boolean`. The dedicated `typescript/no-unsafe-function-type`
9
+ // and `typescript/no-wrapper-object-types` rules also cover some of
10
+ // these, but `no-restricted-types` is the documented umbrella users
11
+ // reach for when they want a single "ban these names" knob.
12
+ //
13
+ // https://typescript-eslint.io/rules/no-restricted-types/
14
+ package linthost
15
+
16
+ import (
17
+ shimast "github.com/microsoft/typescript-go/shim/ast"
18
+ )
19
+
20
+ type noRestrictedTypes struct{}
21
+
22
+ // noRestrictedTypesDefault is the default set surfaced by the rule
23
+ // when no config is supplied. Each entry pairs the banned identifier
24
+ // with a short, actionable replacement hint.
25
+ var noRestrictedTypesDefault = map[string]string{
26
+ "Object": "Use `object` (any non-primitive) or a specific shape like `Record<string, unknown>` instead of `Object`.",
27
+ "Function": "Declare the specific call signature instead of the unsafe `Function` type.",
28
+ "Number": "Use the lowercase primitive `number` instead of the wrapper type `Number`.",
29
+ "String": "Use the lowercase primitive `string` instead of the wrapper type `String`.",
30
+ "Boolean": "Use the lowercase primitive `boolean` instead of the wrapper type `Boolean`.",
31
+ }
32
+
33
+ func (noRestrictedTypes) Name() string { return "typescript/no-restricted-types" }
34
+ func (noRestrictedTypes) Visits() []shimast.Kind {
35
+ return []shimast.Kind{shimast.KindTypeReference}
36
+ }
37
+ func (noRestrictedTypes) Check(ctx *Context, node *shimast.Node) {
38
+ ref := node.AsTypeReferenceNode()
39
+ if ref == nil || ref.TypeName == nil {
40
+ return
41
+ }
42
+ name := identifierText(ref.TypeName)
43
+ if name == "" {
44
+ return
45
+ }
46
+ message, banned := noRestrictedTypesDefault[name]
47
+ if !banned {
48
+ return
49
+ }
50
+ // Shadow guard: if the user has declared a same-named `type` /
51
+ // `interface` / `class` at file scope, their identifier is NOT the
52
+ // global wrapper. Re-use the wrapper-types helper so the two rules
53
+ // stay consistent about what counts as a shadow.
54
+ if fileShadowsWrapperName(ctx.File, name) {
55
+ return
56
+ }
57
+ ctx.Report(node, message)
58
+ }
59
+
60
+ func init() {
61
+ Register(noRestrictedTypes{})
62
+ }
@@ -0,0 +1,129 @@
1
+ // typescript/no-unnecessary-boolean-literal-compare: comparing a value
2
+ // already typed as `boolean` against `true` / `false` adds noise without
3
+ // changing the result — `x === true` evaluates to `x`, `x === false`
4
+ // evaluates to `!x`. The rule narrows to direct comparisons because once
5
+ // the operand carries `null` / `undefined` the literal compare actually
6
+ // strips nullability and is no longer redundant. typescript-eslint:
7
+ // https://typescript-eslint.io/rules/no-unnecessary-boolean-literal-compare/
8
+ //
9
+ // Type-aware. Without a Checker we cannot prove the non-literal side is
10
+ // pure boolean, so Context.Checker == nil short-circuits the rule the
11
+ // same way `no-misused-promises` and `strict-boolean-expressions` do.
12
+ package linthost
13
+
14
+ import (
15
+ shimast "github.com/microsoft/typescript-go/shim/ast"
16
+ shimchecker "github.com/microsoft/typescript-go/shim/checker"
17
+ )
18
+
19
+ type noUnnecessaryBooleanLiteralCompare struct{}
20
+
21
+ func (noUnnecessaryBooleanLiteralCompare) Name() string {
22
+ return "typescript/no-unnecessary-boolean-literal-compare"
23
+ }
24
+ func (noUnnecessaryBooleanLiteralCompare) NeedsTypeChecker() bool {
25
+ return true
26
+ }
27
+ func (noUnnecessaryBooleanLiteralCompare) Visits() []shimast.Kind {
28
+ return []shimast.Kind{shimast.KindBinaryExpression}
29
+ }
30
+ func (noUnnecessaryBooleanLiteralCompare) Check(ctx *Context, node *shimast.Node) {
31
+ if ctx.Checker == nil {
32
+ return
33
+ }
34
+ bin := node.AsBinaryExpression()
35
+ if bin == nil || bin.OperatorToken == nil || bin.Left == nil || bin.Right == nil {
36
+ return
37
+ }
38
+ // Only equality / inequality operators are subject to the rewrite —
39
+ // `<`, `>`, `&&`, etc. against `true` / `false` are not the same shape.
40
+ switch bin.OperatorToken.Kind {
41
+ case shimast.KindEqualsEqualsToken,
42
+ shimast.KindEqualsEqualsEqualsToken,
43
+ shimast.KindExclamationEqualsToken,
44
+ shimast.KindExclamationEqualsEqualsToken:
45
+ default:
46
+ return
47
+ }
48
+ left := stripParens(bin.Left)
49
+ right := stripParens(bin.Right)
50
+ if left == nil || right == nil {
51
+ return
52
+ }
53
+ // Identify which side is the literal and which side is the value.
54
+ // `true === x` and `x === true` are both reported.
55
+ var value *shimast.Node
56
+ switch {
57
+ case noUnnecessaryBooleanLiteralCompareIsBoolLiteral(left):
58
+ value = right
59
+ case noUnnecessaryBooleanLiteralCompareIsBoolLiteral(right):
60
+ value = left
61
+ default:
62
+ return
63
+ }
64
+ // Skip when both sides are literals — that's a different code smell
65
+ // (e.g. `true === false`) that other rules cover.
66
+ if noUnnecessaryBooleanLiteralCompareIsBoolLiteral(value) {
67
+ return
68
+ }
69
+ t := ctx.Checker.GetTypeAtLocation(value)
70
+ if t == nil {
71
+ return
72
+ }
73
+ // Only fire when the value side is pure boolean. A `boolean | null`
74
+ // operand uses the literal compare to strip nullability — leaving
75
+ // that intact is the explicit carve-out the rule documentation calls
76
+ // out, so we refuse to flag it.
77
+ if !noUnnecessaryBooleanLiteralCompareIsPureBoolean(t) {
78
+ return
79
+ }
80
+ ctx.Report(node, "This comparison against a boolean literal is unnecessary; use the value (or its negation) directly.")
81
+ }
82
+
83
+ // noUnnecessaryBooleanLiteralCompareIsBoolLiteral reports whether node is
84
+ // the literal `true` or `false` keyword.
85
+ func noUnnecessaryBooleanLiteralCompareIsBoolLiteral(node *shimast.Node) bool {
86
+ if node == nil {
87
+ return false
88
+ }
89
+ return node.Kind == shimast.KindTrueKeyword || node.Kind == shimast.KindFalseKeyword
90
+ }
91
+
92
+ // noUnnecessaryBooleanLiteralCompareIsPureBoolean reports whether t is a
93
+ // pure boolean type — `boolean`, `true`, `false`, or a union strictly of
94
+ // these. `boolean | null`, `boolean | undefined`, and `any` / `unknown`
95
+ // are explicitly excluded so the literal compare stays in place when it
96
+ // is also stripping nullability or escaping an opaque value.
97
+ func noUnnecessaryBooleanLiteralCompareIsPureBoolean(t *shimchecker.Type) bool {
98
+ if t == nil {
99
+ return false
100
+ }
101
+ flags := t.Flags()
102
+ if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
103
+ return false
104
+ }
105
+ if flags&shimchecker.TypeFlagsUnion != 0 {
106
+ parts := t.Types()
107
+ if len(parts) == 0 {
108
+ return false
109
+ }
110
+ for _, part := range parts {
111
+ if part == nil {
112
+ return false
113
+ }
114
+ pf := part.Flags()
115
+ if pf&(shimchecker.TypeFlagsNull|shimchecker.TypeFlagsUndefined) != 0 {
116
+ return false
117
+ }
118
+ if pf&shimchecker.TypeFlagsBooleanLike == 0 {
119
+ return false
120
+ }
121
+ }
122
+ return true
123
+ }
124
+ return flags&shimchecker.TypeFlagsBooleanLike != 0
125
+ }
126
+
127
+ func init() {
128
+ Register(noUnnecessaryBooleanLiteralCompare{})
129
+ }
@@ -0,0 +1,250 @@
1
+ // typescript/no-unnecessary-condition: a conditional whose test expression
2
+ // has a type that can only ever evaluate to one truthiness — `if ({})`,
3
+ // `if (null)`, `while ("")` — branches that never run (or always run) and
4
+ // almost always reflect a logic error. The runtime takes the static
5
+ // answer that the type system already had, so naming the constant intent
6
+ // explicitly (`if (true)`, deleting the dead arm, or widening the type)
7
+ // is the fix. typescript-eslint:
8
+ // https://typescript-eslint.io/rules/no-unnecessary-condition/
9
+ //
10
+ // Type-aware. Without a Checker the rule cannot tell `null` apart from
11
+ // `string | null`, so Context.Checker == nil short-circuits each Check to
12
+ // a no-op the way `strict-boolean-expressions` and `no-misused-promises`
13
+ // do.
14
+ package linthost
15
+
16
+ import (
17
+ "strings"
18
+
19
+ shimast "github.com/microsoft/typescript-go/shim/ast"
20
+ shimchecker "github.com/microsoft/typescript-go/shim/checker"
21
+ )
22
+
23
+ // truthState is the lattice value the rule tracks for each constituent of
24
+ // the test expression's static type.
25
+ //
26
+ // - truthStateUnknowable — `any` / `unknown` / `never`, or any other
27
+ // constituent we cannot prove either truthy or falsy. Treated as
28
+ // "abandon the analysis" — if any constituent is unknowable the
29
+ // overall result is unknowable and the rule does not fire.
30
+ // - truthStateAlwaysTruthy / truthStateAlwaysFalsy — a constituent
31
+ // whose runtime truthiness is fixed.
32
+ // - truthStateMixed — a constituent that could be either (plain
33
+ // `string`, plain `number`, plain `boolean`, enum, etc.). Reaching
34
+ // "mixed" disqualifies the whole expression from the rule.
35
+ type truthState int
36
+
37
+ const (
38
+ truthStateUnknowable truthState = iota
39
+ truthStateAlwaysTruthy
40
+ truthStateAlwaysFalsy
41
+ truthStateMixed
42
+ )
43
+
44
+ type noUnnecessaryCondition struct{}
45
+
46
+ func (noUnnecessaryCondition) Name() string { return "typescript/no-unnecessary-condition" }
47
+ func (noUnnecessaryCondition) NeedsTypeChecker() bool {
48
+ return true
49
+ }
50
+ func (noUnnecessaryCondition) Visits() []shimast.Kind {
51
+ return []shimast.Kind{
52
+ shimast.KindIfStatement,
53
+ shimast.KindWhileStatement,
54
+ shimast.KindDoStatement,
55
+ shimast.KindForStatement,
56
+ shimast.KindConditionalExpression,
57
+ shimast.KindBinaryExpression,
58
+ shimast.KindPrefixUnaryExpression,
59
+ }
60
+ }
61
+ func (noUnnecessaryCondition) Check(ctx *Context, node *shimast.Node) {
62
+ if ctx.Checker == nil {
63
+ return
64
+ }
65
+ switch node.Kind {
66
+ case shimast.KindIfStatement:
67
+ if stmt := node.AsIfStatement(); stmt != nil {
68
+ noUnnecessaryConditionReport(ctx, stmt.Expression)
69
+ }
70
+ case shimast.KindWhileStatement:
71
+ if stmt := node.AsWhileStatement(); stmt != nil {
72
+ noUnnecessaryConditionReport(ctx, stmt.Expression)
73
+ }
74
+ case shimast.KindDoStatement:
75
+ if stmt := node.AsDoStatement(); stmt != nil {
76
+ noUnnecessaryConditionReport(ctx, stmt.Expression)
77
+ }
78
+ case shimast.KindForStatement:
79
+ if stmt := node.AsForStatement(); stmt != nil {
80
+ noUnnecessaryConditionReport(ctx, stmt.Condition)
81
+ }
82
+ case shimast.KindConditionalExpression:
83
+ if expr := node.AsConditionalExpression(); expr != nil {
84
+ noUnnecessaryConditionReport(ctx, expr.Condition)
85
+ }
86
+ case shimast.KindPrefixUnaryExpression:
87
+ expr := node.AsPrefixUnaryExpression()
88
+ if expr != nil && expr.Operator == shimast.KindExclamationToken {
89
+ noUnnecessaryConditionReport(ctx, expr.Operand)
90
+ }
91
+ case shimast.KindBinaryExpression:
92
+ bin := node.AsBinaryExpression()
93
+ if bin == nil || bin.OperatorToken == nil {
94
+ return
95
+ }
96
+ // Only `&&` / `||` test their left operand for truthiness. `??`
97
+ // short-circuits on nullish, not on falsy, and is intentionally
98
+ // out of scope — its dedicated rule
99
+ // `no-unnecessary-nullish-coalescing` covers that pattern.
100
+ switch bin.OperatorToken.Kind {
101
+ case shimast.KindAmpersandAmpersandToken, shimast.KindBarBarToken:
102
+ noUnnecessaryConditionReport(ctx, bin.Left)
103
+ }
104
+ }
105
+ }
106
+
107
+ // noUnnecessaryConditionReport flags `expr` when its static type proves
108
+ // the runtime truthiness is fixed. The descent through `&&` / `||`
109
+ // mirrors `strict-boolean-expressions`: the outer BinaryExpression visit
110
+ // only checks Left, so the recursion here picks up Right too. Wrapping
111
+ // parens are skipped via stripParens.
112
+ func noUnnecessaryConditionReport(ctx *Context, expr *shimast.Node) {
113
+ if expr == nil {
114
+ return
115
+ }
116
+ expr = stripParens(expr)
117
+ if expr == nil {
118
+ return
119
+ }
120
+ if expr.Kind == shimast.KindBinaryExpression {
121
+ bin := expr.AsBinaryExpression()
122
+ if bin != nil && bin.OperatorToken != nil {
123
+ switch bin.OperatorToken.Kind {
124
+ case shimast.KindAmpersandAmpersandToken, shimast.KindBarBarToken:
125
+ noUnnecessaryConditionReport(ctx, bin.Left)
126
+ noUnnecessaryConditionReport(ctx, bin.Right)
127
+ return
128
+ }
129
+ }
130
+ }
131
+ t := ctx.Checker.GetTypeAtLocation(expr)
132
+ if t == nil {
133
+ return
134
+ }
135
+ switch noUnnecessaryConditionEvaluate(ctx.Checker, t) {
136
+ case truthStateAlwaysTruthy:
137
+ ctx.Report(expr, "Unnecessary conditional, value is always truthy.")
138
+ case truthStateAlwaysFalsy:
139
+ ctx.Report(expr, "Unnecessary conditional, value is always falsy.")
140
+ }
141
+ }
142
+
143
+ // noUnnecessaryConditionEvaluate folds a type into a single truthState by
144
+ // combining each constituent's state under union semantics: any
145
+ // unknowable constituent forces unknowable, otherwise the combined state
146
+ // is the unique truthy / falsy / mixed reading of every constituent.
147
+ // Intersections are not analyzed structurally — they bail to unknowable
148
+ // because the Checker may resolve them into shapes (e.g. branded
149
+ // primitives) the rule cannot reason about safely.
150
+ func noUnnecessaryConditionEvaluate(checker *shimchecker.Checker, t *shimchecker.Type) truthState {
151
+ if checker == nil || t == nil {
152
+ return truthStateUnknowable
153
+ }
154
+ flags := t.Flags()
155
+ if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
156
+ return truthStateUnknowable
157
+ }
158
+ if flags&shimchecker.TypeFlagsIntersection != 0 {
159
+ // Intersections such as `Foo & { brand: "x" }` carry semantics the
160
+ // rule cannot prove without a deeper Checker walk, so we keep the
161
+ // conservative bail.
162
+ return truthStateUnknowable
163
+ }
164
+ if flags&shimchecker.TypeFlagsUnion != 0 {
165
+ parts := t.Types()
166
+ if len(parts) == 0 {
167
+ return truthStateUnknowable
168
+ }
169
+ combined := truthState(-1)
170
+ for _, part := range parts {
171
+ if part == nil {
172
+ return truthStateUnknowable
173
+ }
174
+ state := noUnnecessaryConditionEvaluate(checker, part)
175
+ if state == truthStateUnknowable || state == truthStateMixed {
176
+ // A union with even one constituent we can't pin breaks the
177
+ // "always X" guarantee — bail.
178
+ return state
179
+ }
180
+ if combined == truthState(-1) {
181
+ combined = state
182
+ continue
183
+ }
184
+ if combined != state {
185
+ // `string | null` has both a falsy ("") and a always-falsy
186
+ // (null) outcome that disagree across constituents — fall
187
+ // back to mixed so the rule stays silent.
188
+ return truthStateMixed
189
+ }
190
+ }
191
+ if combined == truthState(-1) {
192
+ return truthStateUnknowable
193
+ }
194
+ return combined
195
+ }
196
+ // Atomic types.
197
+ if flags&(shimchecker.TypeFlagsNull|shimchecker.TypeFlagsUndefined|shimchecker.TypeFlagsVoid) != 0 {
198
+ return truthStateAlwaysFalsy
199
+ }
200
+ if flags&shimchecker.TypeFlagsBooleanLiteral != 0 {
201
+ text := checker.TypeToString(t)
202
+ if strings.TrimSpace(text) == "false" {
203
+ return truthStateAlwaysFalsy
204
+ }
205
+ if strings.TrimSpace(text) == "true" {
206
+ return truthStateAlwaysTruthy
207
+ }
208
+ return truthStateUnknowable
209
+ }
210
+ if flags&shimchecker.TypeFlagsStringLiteral != 0 {
211
+ text := strings.TrimSpace(checker.TypeToString(t))
212
+ if text == `""` || text == `''` {
213
+ return truthStateAlwaysFalsy
214
+ }
215
+ return truthStateAlwaysTruthy
216
+ }
217
+ if flags&shimchecker.TypeFlagsNumberLiteral != 0 {
218
+ text := strings.TrimSpace(checker.TypeToString(t))
219
+ // `0`, `0.0`, `-0` all stringify as `0`; everything else is truthy.
220
+ // `NaN` is not representable as a literal type, so it cannot reach
221
+ // this branch.
222
+ if text == "0" {
223
+ return truthStateAlwaysFalsy
224
+ }
225
+ return truthStateAlwaysTruthy
226
+ }
227
+ if flags&shimchecker.TypeFlagsBigIntLiteral != 0 {
228
+ text := strings.TrimSpace(checker.TypeToString(t))
229
+ if text == "0n" {
230
+ return truthStateAlwaysFalsy
231
+ }
232
+ return truthStateAlwaysTruthy
233
+ }
234
+ if flags&shimchecker.TypeFlagsObject != 0 {
235
+ // A non-nullable object value is always truthy. `{}`, arrays,
236
+ // class instances, functions, and structural records all share
237
+ // this contract; only `null` / `undefined` make an object position
238
+ // falsy and those flags route to the always-falsy branch above.
239
+ return truthStateAlwaysTruthy
240
+ }
241
+ // Plain `string` / `number` / `boolean` / `bigint` / enum / symbol /
242
+ // type parameter / index / template literal — every one of these can
243
+ // hold both truthy and falsy values (or escapes static reasoning), so
244
+ // the rule must stay silent.
245
+ return truthStateMixed
246
+ }
247
+
248
+ func init() {
249
+ Register(noUnnecessaryCondition{})
250
+ }
@@ -0,0 +1,118 @@
1
+ // typescript/no-unnecessary-qualifier: a qualified reference like
2
+ // `Foo.Bar` written inside `namespace Foo { ... }` (or `enum Foo { ...,
3
+ // X = Foo.Y, ... }`) names the same scope the reference is already in.
4
+ // The qualifier adds no information; dropping `Foo.` leaves the
5
+ // identical binding lookup. typescript-eslint:
6
+ // https://typescript-eslint.io/rules/no-unnecessary-qualifier/
7
+ package linthost
8
+
9
+ import (
10
+ shimast "github.com/microsoft/typescript-go/shim/ast"
11
+ )
12
+
13
+ // noUnnecessaryQualifier inspects every two-segment qualified reference
14
+ // whose head is a plain identifier — `QualifiedName` shows up in type
15
+ // position (`Foo.Bar` inside a type annotation) and
16
+ // `PropertyAccessExpression` shows up in value position. The check is
17
+ // AST-only: it walks the ancestor chain for an enclosing `namespace
18
+ // <head> { ... }` or `enum <head> { ... }` declaration and reports when
19
+ // one is found. The rule deliberately does not consult the Checker
20
+ // because the upstream rule operates on lexical scope identity, which
21
+ // the AST already encodes via declaration ancestry.
22
+ type noUnnecessaryQualifier struct{}
23
+
24
+ func (noUnnecessaryQualifier) Name() string {
25
+ return "typescript/no-unnecessary-qualifier"
26
+ }
27
+ func (noUnnecessaryQualifier) Visits() []shimast.Kind {
28
+ return []shimast.Kind{
29
+ shimast.KindQualifiedName,
30
+ shimast.KindPropertyAccessExpression,
31
+ }
32
+ }
33
+ func (noUnnecessaryQualifier) Check(ctx *Context, node *shimast.Node) {
34
+ head := noUnnecessaryQualifierHead(node)
35
+ if head == "" {
36
+ return
37
+ }
38
+ if !noUnnecessaryQualifierHasEnclosingScope(node, head) {
39
+ return
40
+ }
41
+ ctx.Report(node, "Qualifier `"+head+"` is the enclosing namespace or enum — drop the qualifier.")
42
+ }
43
+
44
+ // noUnnecessaryQualifierHead returns the LHS identifier text when the
45
+ // node is a two-segment qualified reference (`A.B`) whose head is a
46
+ // plain identifier. Returns "" for nested chains (`A.B.C`), computed
47
+ // accesses, or non-identifier heads — those shapes don't match the
48
+ // "qualifier names the enclosing scope" pattern.
49
+ func noUnnecessaryQualifierHead(node *shimast.Node) string {
50
+ if node == nil {
51
+ return ""
52
+ }
53
+ switch node.Kind {
54
+ case shimast.KindQualifiedName:
55
+ qn := node.AsQualifiedName()
56
+ if qn == nil || qn.Left == nil {
57
+ return ""
58
+ }
59
+ if qn.Left.Kind != shimast.KindIdentifier {
60
+ return ""
61
+ }
62
+ return identifierText(qn.Left)
63
+ case shimast.KindPropertyAccessExpression:
64
+ pa := node.AsPropertyAccessExpression()
65
+ if pa == nil || pa.Expression == nil || pa.Name() == nil {
66
+ return ""
67
+ }
68
+ // Optional chains (`Foo?.Bar`) aren't redundant in the same
69
+ // sense — the `?.` changes runtime behavior, so leave them be.
70
+ if pa.QuestionDotToken != nil {
71
+ return ""
72
+ }
73
+ if pa.Expression.Kind != shimast.KindIdentifier {
74
+ return ""
75
+ }
76
+ return identifierText(pa.Expression)
77
+ }
78
+ return ""
79
+ }
80
+
81
+ // noUnnecessaryQualifierHasEnclosingScope reports whether `node`
82
+ // appears inside a `namespace <head> { ... }` or `enum <head> { ... }`
83
+ // declaration body. The walk climbs `Parent` links until it finds a
84
+ // matching block or hits the SourceFile root.
85
+ func noUnnecessaryQualifierHasEnclosingScope(node *shimast.Node, head string) bool {
86
+ for cur := node.Parent; cur != nil; cur = cur.Parent {
87
+ switch cur.Kind {
88
+ case shimast.KindModuleDeclaration:
89
+ decl := cur.AsModuleDeclaration()
90
+ if decl == nil || decl.Name() == nil {
91
+ continue
92
+ }
93
+ // `declare module "fs"` carries a string-literal name and
94
+ // does not bind an identifier in the surrounding scope —
95
+ // skip those entirely. The rule only fires when the head
96
+ // matches the enclosing namespace's identifier name.
97
+ if decl.Name().Kind != shimast.KindIdentifier {
98
+ continue
99
+ }
100
+ if identifierText(decl.Name()) == head {
101
+ return true
102
+ }
103
+ case shimast.KindEnumDeclaration:
104
+ decl := cur.AsEnumDeclaration()
105
+ if decl == nil || decl.Name() == nil {
106
+ continue
107
+ }
108
+ if identifierText(decl.Name()) == head {
109
+ return true
110
+ }
111
+ }
112
+ }
113
+ return false
114
+ }
115
+
116
+ func init() {
117
+ Register(noUnnecessaryQualifier{})
118
+ }