@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,80 @@
1
+ // noMixedOperators flags expressions that mix operators from different
2
+ // precedence families without explicit parentheses around the inner
3
+ // expression. The classic gotcha is `a && b || c` — readers expect
4
+ // left-to-right grouping, but `&&` binds tighter than `||`, so the
5
+ // parse tree is actually `(a && b) || c`. Wrapping the inner
6
+ // sub-expression in parens removes the ambiguity for both the parser
7
+ // and the reader.
8
+ //
9
+ // The conservative baseline fires only on the highest-confusion mixes:
10
+ // logical mixed with a different logical, logical mixed with bitwise,
11
+ // and bitwise mixed with comparison. Same-operator chains (`a && b &&
12
+ // c`) and parenthesized inner children (`(a && b) || c`) never fire.
13
+ // https://eslint.org/docs/latest/rules/no-mixed-operators
14
+ package linthost
15
+
16
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
17
+
18
+ type noMixedOperators struct{}
19
+
20
+ const (
21
+ mixedGroupLogical = 1
22
+ mixedGroupBitwise = 2
23
+ mixedGroupComparison = 3
24
+ )
25
+
26
+ func (noMixedOperators) Name() string { return "no-mixed-operators" }
27
+ func (noMixedOperators) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindBinaryExpression} }
28
+ func (noMixedOperators) Check(ctx *Context, node *shimast.Node) {
29
+ expr := node.AsBinaryExpression()
30
+ if expr == nil || expr.OperatorToken == nil {
31
+ return
32
+ }
33
+ parent := noMixedOperatorsGroup(expr.OperatorToken.Kind)
34
+ if parent == 0 {
35
+ return
36
+ }
37
+ op := expr.OperatorToken.Kind
38
+ if noMixedOperatorsConflicts(parent, op, expr.Left) ||
39
+ noMixedOperatorsConflicts(parent, op, expr.Right) {
40
+ ctx.Report(node, "Unexpected mix of different operators. Wrap the inner expression in parentheses to make the grouping explicit.")
41
+ }
42
+ }
43
+
44
+ // noMixedOperatorsConflicts returns true when `child` is an
45
+ // unparenthesized BinaryExpression whose operator group is confusing
46
+ // next to the parent group. Same operator never conflicts.
47
+ func noMixedOperatorsConflicts(parent int, parentOp shimast.Kind, child *shimast.Node) bool {
48
+ if child == nil || child.Kind != shimast.KindBinaryExpression {
49
+ return false
50
+ }
51
+ inner := child.AsBinaryExpression()
52
+ if inner == nil || inner.OperatorToken == nil || inner.OperatorToken.Kind == parentOp {
53
+ return false
54
+ }
55
+ g := noMixedOperatorsGroup(inner.OperatorToken.Kind)
56
+ if g == 0 {
57
+ return false
58
+ }
59
+ if parent == mixedGroupLogical {
60
+ return g == mixedGroupLogical || g == mixedGroupBitwise
61
+ }
62
+ return parent == mixedGroupBitwise && (g == mixedGroupLogical || g == mixedGroupComparison)
63
+ }
64
+
65
+ func noMixedOperatorsGroup(op shimast.Kind) int {
66
+ switch op {
67
+ case shimast.KindAmpersandAmpersandToken, shimast.KindBarBarToken, shimast.KindQuestionQuestionToken:
68
+ return mixedGroupLogical
69
+ case shimast.KindAmpersandToken, shimast.KindBarToken, shimast.KindCaretToken:
70
+ return mixedGroupBitwise
71
+ case shimast.KindEqualsEqualsToken, shimast.KindEqualsEqualsEqualsToken,
72
+ shimast.KindExclamationEqualsToken, shimast.KindExclamationEqualsEqualsToken,
73
+ shimast.KindLessThanToken, shimast.KindLessThanEqualsToken,
74
+ shimast.KindGreaterThanToken, shimast.KindGreaterThanEqualsToken:
75
+ return mixedGroupComparison
76
+ }
77
+ return 0
78
+ }
79
+
80
+ func init() { Register(noMixedOperators{}) }
@@ -0,0 +1,98 @@
1
+ // noParamReassign: reassigning a function parameter inside the body of
2
+ // the function it belongs to. Mutating the binding makes the declared
3
+ // name stop pointing at the caller's argument and is the usual ESLint
4
+ // baseline of `no-param-reassign` — without the `props: true` extension
5
+ // that would also flag `param.foo = …`.
6
+ //
7
+ // Conservative scope tracking: collect simple-identifier parameter
8
+ // names, walk the body until a nested function-like introduces a fresh
9
+ // scope, and flag `name = …` / `name op= …` / `++name` / `name--` at
10
+ // any depth in between. A local `const name = 1` that shadows a
11
+ // parameter name will produce a false positive in v1 — proper scope
12
+ // tracking needs the resolver, which the AST-only baseline avoids.
13
+ // Destructured parameter bindings are skipped for the same reason.
14
+ // https://eslint.org/docs/latest/rules/no-param-reassign
15
+ package linthost
16
+
17
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
18
+
19
+ type noParamReassign struct{}
20
+
21
+ func (noParamReassign) Name() string { return "no-param-reassign" }
22
+ func (noParamReassign) Visits() []shimast.Kind {
23
+ return []shimast.Kind{
24
+ shimast.KindFunctionDeclaration,
25
+ shimast.KindFunctionExpression,
26
+ shimast.KindArrowFunction,
27
+ shimast.KindMethodDeclaration,
28
+ shimast.KindConstructor,
29
+ shimast.KindGetAccessor,
30
+ shimast.KindSetAccessor,
31
+ }
32
+ }
33
+ func (noParamReassign) Check(ctx *Context, node *shimast.Node) {
34
+ body := node.Body()
35
+ if body == nil {
36
+ return
37
+ }
38
+ names := map[string]bool{}
39
+ for _, p := range node.Parameters() {
40
+ if decl := p.AsParameterDeclaration(); decl != nil {
41
+ if name := identifierText(decl.Name()); name != "" {
42
+ names[name] = true
43
+ }
44
+ }
45
+ }
46
+ if len(names) == 0 {
47
+ return
48
+ }
49
+ walkParamReassignBody(body, names, func(target *shimast.Node) {
50
+ ctx.Report(target, "Assignment to function parameter.")
51
+ })
52
+ }
53
+
54
+ // walkParamReassignBody visits every assignment-like write in `root`
55
+ // without crossing nested function-like scopes. The target identifier
56
+ // must be a bare name in `names` for `report` to fire.
57
+ func walkParamReassignBody(root *shimast.Node, names map[string]bool, report func(*shimast.Node)) {
58
+ if root == nil {
59
+ return
60
+ }
61
+ var walk func(*shimast.Node)
62
+ hits := func(operand *shimast.Node) bool {
63
+ name := identifierText(stripParens(operand))
64
+ return name != "" && names[name]
65
+ }
66
+ walk = func(node *shimast.Node) {
67
+ if node == nil || (node != root && isFunctionLikeKind(node)) {
68
+ return
69
+ }
70
+ switch node.Kind {
71
+ case shimast.KindBinaryExpression:
72
+ expr := node.AsBinaryExpression()
73
+ if expr != nil && expr.OperatorToken != nil &&
74
+ isAssignmentOperator(expr.OperatorToken.Kind) && hits(expr.Left) {
75
+ report(node)
76
+ }
77
+ case shimast.KindPrefixUnaryExpression:
78
+ pre := node.AsPrefixUnaryExpression()
79
+ if pre != nil && (pre.Operator == shimast.KindPlusPlusToken || pre.Operator == shimast.KindMinusMinusToken) && hits(pre.Operand) {
80
+ report(node)
81
+ }
82
+ case shimast.KindPostfixUnaryExpression:
83
+ post := node.AsPostfixUnaryExpression()
84
+ if post != nil && (post.Operator == shimast.KindPlusPlusToken || post.Operator == shimast.KindMinusMinusToken) && hits(post.Operand) {
85
+ report(node)
86
+ }
87
+ }
88
+ node.ForEachChild(func(child *shimast.Node) bool {
89
+ walk(child)
90
+ return false
91
+ })
92
+ }
93
+ walk(root)
94
+ }
95
+
96
+ func init() {
97
+ Register(noParamReassign{})
98
+ }
@@ -0,0 +1,270 @@
1
+ package linthost
2
+
3
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
4
+
5
+ // noRedeclare: reject declaring the same binding more than once in the
6
+ // same scope. The second declaration silently overwrites the first;
7
+ // shadowing the binding in a nested scope is left alone because the
8
+ // inner declaration introduces a fresh binding.
9
+ // https://eslint.org/docs/latest/rules/no-redeclare
10
+ //
11
+ // Each visited scope (source file, module block, or block) builds a
12
+ // `name -> first node` map by walking only the immediate statement
13
+ // list — nested blocks introduce their own scopes and are processed by
14
+ // a separate visit. The exception is `var`: it hoists to the nearest
15
+ // function-like container, so a function-scope visit also descends
16
+ // past inner blocks to pull every nested `var` into the function
17
+ // scope. Function overload signatures share the implementation's name
18
+ // by design and are skipped, mirroring ESLint's behavior.
19
+ type noRedeclare struct{}
20
+
21
+ func (noRedeclare) Name() string { return "no-redeclare" }
22
+ func (noRedeclare) Visits() []shimast.Kind {
23
+ return []shimast.Kind{shimast.KindSourceFile, shimast.KindModuleBlock, shimast.KindBlock}
24
+ }
25
+ func (noRedeclare) Check(ctx *Context, node *shimast.Node) {
26
+ statements := scopeStatements(node)
27
+ if statements == nil {
28
+ return
29
+ }
30
+ isFunctionScope := isFunctionScopeContainer(node)
31
+ seen := map[string]*shimast.Node{}
32
+
33
+ report := func(name string, declNode *shimast.Node) {
34
+ if prior, exists := seen[name]; exists {
35
+ _ = prior
36
+ ctx.Report(declNode, "'"+name+"' is already defined.")
37
+ return
38
+ }
39
+ seen[name] = declNode
40
+ }
41
+
42
+ // A function-body block inherits its parameters as the outermost
43
+ // bindings of the function scope. Pre-seed the seen map so a later
44
+ // `var` or function declaration with the same name reports.
45
+ if isFunctionScope && node.Kind == shimast.KindBlock && node.Parent != nil && isFunctionLikeKind(node.Parent) {
46
+ for _, name := range parameterBindingNames(node.Parent) {
47
+ if name != "" {
48
+ seen[name] = node.Parent
49
+ }
50
+ }
51
+ }
52
+
53
+ // Pass 1: block-scoped declarations from the immediate statement
54
+ // list. `var` statements only contribute here in function-scope
55
+ // containers — inside a plain block they belong to the enclosing
56
+ // function scope and are reported there instead.
57
+ for _, stmt := range statements {
58
+ if stmt == nil {
59
+ continue
60
+ }
61
+ if stmt.Kind == shimast.KindVariableStatement && !isFunctionScope {
62
+ vs := stmt.AsVariableStatement()
63
+ if vs != nil && vs.DeclarationList != nil && shimast.IsVar(vs.DeclarationList) {
64
+ continue
65
+ }
66
+ }
67
+ for _, name := range immediateDeclarationNames(stmt) {
68
+ if name != "" {
69
+ report(name, stmt)
70
+ }
71
+ }
72
+ }
73
+
74
+ // Pass 2: var hoisting. Function scopes (source file, module block,
75
+ // function body) also collect every `var` declared in nested blocks
76
+ // up to the next function-like boundary. Top-level `var` statements
77
+ // are already reported in Pass 1, so this pass descends into each
78
+ // statement's children rather than visiting the statement itself.
79
+ if isFunctionScope {
80
+ for _, stmt := range statements {
81
+ if stmt == nil || stmt.Kind == shimast.KindVariableStatement {
82
+ continue
83
+ }
84
+ collectHoistedVarsInto(stmt, func(name string, declNode *shimast.Node) {
85
+ if name != "" {
86
+ report(name, declNode)
87
+ }
88
+ })
89
+ }
90
+ }
91
+ }
92
+
93
+ // scopeStatements returns the direct statement list of a scope-defining
94
+ // container (source file, module block, or block). Returns nil for any
95
+ // other node kind so the caller can bail without further checks.
96
+ func scopeStatements(node *shimast.Node) []*shimast.Node {
97
+ switch node.Kind {
98
+ case shimast.KindSourceFile:
99
+ file := node.AsSourceFile()
100
+ if file != nil && file.Statements != nil {
101
+ return file.Statements.Nodes
102
+ }
103
+ case shimast.KindModuleBlock:
104
+ mb := node.AsModuleBlock()
105
+ if mb != nil && mb.Statements != nil {
106
+ return mb.Statements.Nodes
107
+ }
108
+ case shimast.KindBlock:
109
+ block := node.AsBlock()
110
+ if block != nil && block.Statements != nil {
111
+ return block.Statements.Nodes
112
+ }
113
+ }
114
+ return nil
115
+ }
116
+
117
+ // isFunctionScopeContainer reports whether node is a scope into which
118
+ // `var` declarations hoist: the source file, a module block, or a
119
+ // block that forms the body of a function-like declaration.
120
+ func isFunctionScopeContainer(node *shimast.Node) bool {
121
+ switch node.Kind {
122
+ case shimast.KindSourceFile, shimast.KindModuleBlock:
123
+ return true
124
+ case shimast.KindBlock:
125
+ return node.Parent != nil && isFunctionLikeKind(node.Parent)
126
+ }
127
+ return false
128
+ }
129
+
130
+ // immediateDeclarationNames returns every binding name introduced by a
131
+ // single top-level statement of a scope. Variable statements contribute
132
+ // their identifier names regardless of `var`/`let`/`const` keyword;
133
+ // function and class declarations contribute their own name. Overload
134
+ // signatures (`function f(): void;` with no body) are skipped because
135
+ // they intentionally repeat the implementation's name. Ambient
136
+ // declarations (`declare var x: …`, `declare function f(): …`) are
137
+ // also skipped — TypeScript merges them with concrete declarations of
138
+ // the same name by design.
139
+ func immediateDeclarationNames(stmt *shimast.Node) []string {
140
+ if stmt == nil {
141
+ return nil
142
+ }
143
+ if stmt.ModifierFlags()&shimast.ModifierFlagsAmbient != 0 {
144
+ return nil
145
+ }
146
+ switch stmt.Kind {
147
+ case shimast.KindVariableStatement:
148
+ return variableStatementBindingNames(stmt)
149
+ case shimast.KindFunctionDeclaration:
150
+ decl := stmt.AsFunctionDeclaration()
151
+ if decl == nil || decl.Body == nil {
152
+ return nil
153
+ }
154
+ if name := identifierText(decl.Name()); name != "" {
155
+ return []string{name}
156
+ }
157
+ case shimast.KindClassDeclaration:
158
+ decl := stmt.AsClassDeclaration()
159
+ if decl == nil {
160
+ return nil
161
+ }
162
+ if name := identifierText(decl.Name()); name != "" {
163
+ return []string{name}
164
+ }
165
+ }
166
+ return nil
167
+ }
168
+
169
+ // variableStatementBindingNames returns the identifier name of every
170
+ // declaration in a `var`/`let`/`const` statement. Destructuring
171
+ // patterns (`const { a } = obj`) are skipped — the rule cannot reason
172
+ // about pattern equality without scope resolution, so the conservative
173
+ // baseline only handles plain identifier bindings.
174
+ func variableStatementBindingNames(stmt *shimast.Node) []string {
175
+ vs := stmt.AsVariableStatement()
176
+ if vs == nil || vs.DeclarationList == nil {
177
+ return nil
178
+ }
179
+ list := vs.DeclarationList.AsVariableDeclarationList()
180
+ if list == nil || list.Declarations == nil {
181
+ return nil
182
+ }
183
+ var names []string
184
+ for _, decl := range list.Declarations.Nodes {
185
+ if decl == nil {
186
+ continue
187
+ }
188
+ v := decl.AsVariableDeclaration()
189
+ if v == nil {
190
+ continue
191
+ }
192
+ if name := identifierText(v.Name()); name != "" {
193
+ names = append(names, name)
194
+ }
195
+ }
196
+ return names
197
+ }
198
+
199
+ // parameterBindingNames returns the identifier name of every plain
200
+ // parameter on a function-like node. Destructured parameters are
201
+ // skipped for the same reason as variableStatementBindingNames.
202
+ func parameterBindingNames(fn *shimast.Node) []string {
203
+ params := fn.Parameters()
204
+ if len(params) == 0 {
205
+ return nil
206
+ }
207
+ var names []string
208
+ for _, param := range params {
209
+ if param == nil {
210
+ continue
211
+ }
212
+ decl := param.AsParameterDeclaration()
213
+ if decl == nil {
214
+ continue
215
+ }
216
+ if name := identifierText(decl.Name()); name != "" {
217
+ names = append(names, name)
218
+ }
219
+ }
220
+ return names
221
+ }
222
+
223
+ // collectHoistedVarsInto walks every descendant of node up to (but
224
+ // not into) a nested function-like boundary, invoking yield for each
225
+ // `var` binding it discovers. Both `var` statements and `for (var i …)`
226
+ // declaration lists contribute; the former carries a VariableStatement
227
+ // kind so the surrounding statement reports, the latter carries a bare
228
+ // VariableDeclarationList so each individual VariableDeclaration node
229
+ // reports. Plain identifier bindings only — destructuring patterns are
230
+ // skipped to keep the rule reliable.
231
+ func collectHoistedVarsInto(node *shimast.Node, yield func(string, *shimast.Node)) {
232
+ if node == nil || isFunctionLikeKind(node) {
233
+ return
234
+ }
235
+ if node.Kind == shimast.KindVariableStatement {
236
+ vs := node.AsVariableStatement()
237
+ if vs != nil && vs.DeclarationList != nil && shimast.IsVar(vs.DeclarationList) {
238
+ for _, name := range variableStatementBindingNames(node) {
239
+ yield(name, node)
240
+ }
241
+ }
242
+ return
243
+ }
244
+ if node.Kind == shimast.KindVariableDeclarationList {
245
+ list := node.AsVariableDeclarationList()
246
+ if list != nil && shimast.IsVar(node) && list.Declarations != nil {
247
+ for _, decl := range list.Declarations.Nodes {
248
+ if decl == nil {
249
+ continue
250
+ }
251
+ v := decl.AsVariableDeclaration()
252
+ if v == nil {
253
+ continue
254
+ }
255
+ if name := identifierText(v.Name()); name != "" {
256
+ yield(name, decl)
257
+ }
258
+ }
259
+ }
260
+ return
261
+ }
262
+ node.ForEachChild(func(child *shimast.Node) bool {
263
+ collectHoistedVarsInto(child, yield)
264
+ return false
265
+ })
266
+ }
267
+
268
+ func init() {
269
+ Register(noRedeclare{})
270
+ }
@@ -0,0 +1,105 @@
1
+ // noRestrictedImports reports an `import` (or `export … from`) whose
2
+ // module specifier matches a project-configured deny list. The rule is
3
+ // the policy hammer for forcing a module boundary: a package that has
4
+ // been renamed, a workspace internal that should not leak, or a heavy
5
+ // dependency that the project wants to discourage all share the same
6
+ // shape — flag the import at its source so the offending line is the
7
+ // one the developer fixes.
8
+ //
9
+ // Configuration shape: a `paths` array of bare module specifiers to
10
+ // flag, exact-match only. An empty (or missing) list is a no-op — the
11
+ // rule contributes no findings until the project lists something to
12
+ // restrict. The native engine's RuleConfig path does not carry options
13
+ // to the rule, so the Go unit test exercises the rule via a hard-coded
14
+ // default deny list (`lodash`, `underscore`) that fires whenever the
15
+ // rule is enabled with no options blob.
16
+ // https://eslint.org/docs/latest/rules/no-restricted-imports
17
+ package linthost
18
+
19
+ import (
20
+ "encoding/json"
21
+
22
+ shimast "github.com/microsoft/typescript-go/shim/ast"
23
+ )
24
+
25
+ type noRestrictedImports struct{}
26
+
27
+ // noRestrictedImportsOptions decodes the `paths` array from a user
28
+ // `[severity, options]` tuple. Anything else on the blob is ignored so
29
+ // future ESLint-compatible keys (e.g. `patterns`) can be layered in
30
+ // without changing existing configs.
31
+ type noRestrictedImportsOptions struct {
32
+ Paths []string `json:"paths"`
33
+ }
34
+
35
+ // hardCodedRestrictedImports is the default deny list used when the
36
+ // rule is enabled without an options blob. The Go-side test harness
37
+ // exercises the rule through `RuleConfig` (severity-only, no options),
38
+ // so the rule needs a deterministic non-empty default to be testable
39
+ // at the AST layer at all. The choice mirrors a common "don't lean on
40
+ // utility-belt libraries" lint setup in real projects.
41
+ var hardCodedRestrictedImports = []string{"lodash", "underscore"}
42
+
43
+ func (noRestrictedImports) Name() string { return "no-restricted-imports" }
44
+ func (noRestrictedImports) Visits() []shimast.Kind {
45
+ return []shimast.Kind{
46
+ shimast.KindImportDeclaration,
47
+ shimast.KindExportDeclaration,
48
+ }
49
+ }
50
+ func (noRestrictedImports) Check(ctx *Context, node *shimast.Node) {
51
+ specifierNode := moduleSpecifierOf(node)
52
+ if specifierNode == nil {
53
+ return
54
+ }
55
+ specifier := stringLiteralText(specifierNode)
56
+ if specifier == "" {
57
+ return
58
+ }
59
+ denied := resolveNoRestrictedImportsPaths(ctx)
60
+ for _, target := range denied {
61
+ if specifier == target {
62
+ ctx.Report(specifierNode, "'"+specifier+"' import is restricted from being used.")
63
+ return
64
+ }
65
+ }
66
+ }
67
+
68
+ // moduleSpecifierOf returns the `from "…"` string-literal node of the
69
+ // import / re-export declaration. `export { x }` (no `from`) and
70
+ // every other shape returns nil so the caller short-circuits.
71
+ func moduleSpecifierOf(node *shimast.Node) *shimast.Node {
72
+ if node == nil {
73
+ return nil
74
+ }
75
+ switch node.Kind {
76
+ case shimast.KindImportDeclaration:
77
+ if imp := node.AsImportDeclaration(); imp != nil {
78
+ return imp.ModuleSpecifier
79
+ }
80
+ case shimast.KindExportDeclaration:
81
+ if exp := node.AsExportDeclaration(); exp != nil {
82
+ return exp.ModuleSpecifier
83
+ }
84
+ }
85
+ return nil
86
+ }
87
+
88
+ // resolveNoRestrictedImportsPaths returns the active deny list for the
89
+ // firing context. A `paths` array on the user's options blob wins; an
90
+ // empty / missing blob falls back to `hardCodedRestrictedImports` so
91
+ // the AST-layer test fires deterministically.
92
+ func resolveNoRestrictedImportsPaths(ctx *Context) []string {
93
+ if ctx == nil || len(ctx.Options) == 0 {
94
+ return hardCodedRestrictedImports
95
+ }
96
+ var opts noRestrictedImportsOptions
97
+ if err := json.Unmarshal(ctx.Options, &opts); err != nil || len(opts.Paths) == 0 {
98
+ return hardCodedRestrictedImports
99
+ }
100
+ return opts.Paths
101
+ }
102
+
103
+ func init() {
104
+ Register(noRestrictedImports{})
105
+ }
@@ -0,0 +1,49 @@
1
+ // noRestrictedSyntax: a project-level escape hatch that lets a team
2
+ // ban specific AST node kinds outright. Upstream ESLint accepts an
3
+ // arbitrary selector list and a per-entry message; without the
4
+ // rule-options plumbing, this baseline ships a fixed default set that
5
+ // covers the two syntactic constructs almost every modern TypeScript
6
+ // project forbids: `with` (replaced by destructuring / explicit access
7
+ // long ago) and labeled statements (used only to bridge complex
8
+ // nested loops, which are themselves better refactored). The full
9
+ // configurable surface is deferred — projects that need a custom
10
+ // denylist can stack additional rules until option decoding lands.
11
+ // https://eslint.org/docs/latest/rules/no-restricted-syntax
12
+ package linthost
13
+
14
+ import (
15
+ shimast "github.com/microsoft/typescript-go/shim/ast"
16
+ )
17
+
18
+ // noRestrictedSyntaxDefault is the built-in denylist surfaced when no
19
+ // config is supplied. Each entry pairs a banned node kind with the
20
+ // short, actionable message reported at the offending node.
21
+ var noRestrictedSyntaxDefault = map[shimast.Kind]string{
22
+ shimast.KindWithStatement: "`with` statements are restricted — use explicit property access instead.",
23
+ shimast.KindLabeledStatement: "Labeled statements are restricted — refactor the surrounding control flow instead.",
24
+ }
25
+
26
+ type noRestrictedSyntax struct{}
27
+
28
+ func (noRestrictedSyntax) Name() string { return "no-restricted-syntax" }
29
+ func (noRestrictedSyntax) Visits() []shimast.Kind {
30
+ kinds := make([]shimast.Kind, 0, len(noRestrictedSyntaxDefault))
31
+ for kind := range noRestrictedSyntaxDefault {
32
+ kinds = append(kinds, kind)
33
+ }
34
+ return kinds
35
+ }
36
+ func (noRestrictedSyntax) Check(ctx *Context, node *shimast.Node) {
37
+ if node == nil {
38
+ return
39
+ }
40
+ message, banned := noRestrictedSyntaxDefault[node.Kind]
41
+ if !banned {
42
+ return
43
+ }
44
+ ctx.Report(node, message)
45
+ }
46
+
47
+ func init() {
48
+ Register(noRestrictedSyntax{})
49
+ }