@ttsc/lint 0.13.1 → 0.14.0-dev.20260528.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (464) hide show
  1. package/README.md +948 -69
  2. package/lib/defaultFormat.d.ts +9 -6
  3. package/lib/defaultFormat.js +9 -6
  4. package/lib/defaultFormat.js.map +1 -1
  5. package/lib/index.d.ts +46 -0
  6. package/lib/index.js +35 -10
  7. package/lib/index.js.map +1 -1
  8. package/lib/structures/ITtscLintConfig.d.ts +12 -6
  9. package/lib/structures/{ITtscLintFormatConfig.d.ts → ITtscLintFormat.d.ts} +2 -2
  10. package/lib/structures/{TtscLintRuleMap.js → ITtscLintFormat.js} +1 -1
  11. package/lib/structures/ITtscLintFormat.js.map +1 -0
  12. package/lib/structures/TtscLintRuleSetting.d.ts +49 -0
  13. package/lib/structures/{TtscLintRuleOptions.js → TtscLintRuleSetting.js} +1 -1
  14. package/lib/structures/TtscLintRuleSetting.js.map +1 -0
  15. package/lib/structures/index.d.ts +3 -4
  16. package/lib/structures/index.js +3 -4
  17. package/lib/structures/index.js.map +1 -1
  18. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +104 -0
  19. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +14 -0
  20. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
  21. package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +79 -0
  22. package/lib/structures/rules/ITtscLintBoundariesRules.js +3 -0
  23. package/lib/structures/rules/ITtscLintBoundariesRules.js.map +1 -0
  24. package/lib/structures/rules/ITtscLintContributorRules.d.ts +17 -0
  25. package/lib/structures/rules/ITtscLintContributorRules.js +3 -0
  26. package/lib/structures/rules/ITtscLintContributorRules.js.map +1 -0
  27. package/lib/structures/rules/ITtscLintCoreRules.d.ts +1257 -0
  28. package/lib/structures/{ITtscLintFormatConfig.js → rules/ITtscLintCoreRules.js} +1 -1
  29. package/lib/structures/rules/ITtscLintCoreRules.js.map +1 -0
  30. package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +17 -0
  31. package/lib/structures/rules/ITtscLintCypressRuleOptions.js +10 -0
  32. package/lib/structures/rules/ITtscLintCypressRuleOptions.js.map +1 -0
  33. package/lib/structures/rules/ITtscLintCypressRules.d.ts +129 -0
  34. package/lib/structures/rules/ITtscLintCypressRules.js +3 -0
  35. package/lib/structures/rules/ITtscLintCypressRules.js.map +1 -0
  36. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +157 -0
  37. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +13 -0
  38. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js.map +1 -0
  39. package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +167 -0
  40. package/lib/structures/rules/ITtscLintFunctionalRules.js +3 -0
  41. package/lib/structures/rules/ITtscLintFunctionalRules.js.map +1 -0
  42. package/lib/structures/rules/ITtscLintJestRules.d.ts +201 -0
  43. package/lib/structures/rules/ITtscLintJestRules.js +3 -0
  44. package/lib/structures/rules/ITtscLintJestRules.js.map +1 -0
  45. package/lib/structures/rules/ITtscLintJsdocRules.d.ts +140 -0
  46. package/lib/structures/rules/ITtscLintJsdocRules.js +3 -0
  47. package/lib/structures/rules/ITtscLintJsdocRules.js.map +1 -0
  48. package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +302 -0
  49. package/lib/structures/rules/ITtscLintJsxA11yRules.js +3 -0
  50. package/lib/structures/rules/ITtscLintJsxA11yRules.js.map +1 -0
  51. package/lib/structures/rules/ITtscLintNextjsRules.d.ts +185 -0
  52. package/lib/structures/rules/ITtscLintNextjsRules.js +3 -0
  53. package/lib/structures/rules/ITtscLintNextjsRules.js.map +1 -0
  54. package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +330 -0
  55. package/lib/structures/rules/ITtscLintPlaywrightRules.js +3 -0
  56. package/lib/structures/rules/ITtscLintPlaywrightRules.js.map +1 -0
  57. package/lib/structures/rules/ITtscLintPromiseRules.d.ts +188 -0
  58. package/lib/structures/rules/ITtscLintPromiseRules.js +3 -0
  59. package/lib/structures/rules/ITtscLintPromiseRules.js.map +1 -0
  60. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +18 -0
  61. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js +8 -0
  62. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js.map +1 -0
  63. package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +51 -0
  64. package/lib/structures/rules/ITtscLintReactPerfRules.js +3 -0
  65. package/lib/structures/rules/ITtscLintReactPerfRules.js.map +1 -0
  66. package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +39 -0
  67. package/lib/structures/rules/ITtscLintReactRuleOptions.js +12 -0
  68. package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
  69. package/lib/structures/rules/ITtscLintReactRules.d.ts +289 -0
  70. package/lib/structures/rules/ITtscLintReactRules.js +3 -0
  71. package/lib/structures/rules/ITtscLintReactRules.js.map +1 -0
  72. package/lib/structures/rules/ITtscLintRegexpRules.d.ts +190 -0
  73. package/lib/structures/rules/ITtscLintRegexpRules.js +3 -0
  74. package/lib/structures/rules/ITtscLintRegexpRules.js.map +1 -0
  75. package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +66 -0
  76. package/lib/structures/rules/ITtscLintRuleOptionsMap.js +3 -0
  77. package/lib/structures/rules/ITtscLintRuleOptionsMap.js.map +1 -0
  78. package/lib/structures/rules/ITtscLintRules.d.ts +55 -0
  79. package/lib/structures/{TtscLintRule.js → rules/ITtscLintRules.js} +1 -1
  80. package/lib/structures/rules/ITtscLintRules.js.map +1 -0
  81. package/lib/structures/rules/ITtscLintSecurityRules.d.ts +148 -0
  82. package/lib/structures/rules/ITtscLintSecurityRules.js +3 -0
  83. package/lib/structures/rules/ITtscLintSecurityRules.js.map +1 -0
  84. package/lib/structures/rules/ITtscLintSolidRules.d.ts +181 -0
  85. package/lib/structures/rules/ITtscLintSolidRules.js +3 -0
  86. package/lib/structures/rules/ITtscLintSolidRules.js.map +1 -0
  87. package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +21 -0
  88. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js +9 -0
  89. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js.map +1 -0
  90. package/lib/structures/rules/ITtscLintStorybookRules.d.ts +174 -0
  91. package/lib/structures/rules/ITtscLintStorybookRules.js +3 -0
  92. package/lib/structures/rules/ITtscLintStorybookRules.js.map +1 -0
  93. package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +94 -0
  94. package/lib/structures/rules/ITtscLintTanstackQueryRules.js +3 -0
  95. package/lib/structures/rules/ITtscLintTanstackQueryRules.js.map +1 -0
  96. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +22 -0
  97. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js +10 -0
  98. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js.map +1 -0
  99. package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +310 -0
  100. package/lib/structures/rules/ITtscLintTestingLibraryRules.js +3 -0
  101. package/lib/structures/rules/ITtscLintTestingLibraryRules.js.map +1 -0
  102. package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +1132 -0
  103. package/lib/structures/rules/ITtscLintTypeScriptRules.js +3 -0
  104. package/lib/structures/rules/ITtscLintTypeScriptRules.js.map +1 -0
  105. package/lib/structures/rules/ITtscLintUnicornRules.d.ts +997 -0
  106. package/lib/structures/rules/ITtscLintUnicornRules.js +3 -0
  107. package/lib/structures/rules/ITtscLintUnicornRules.js.map +1 -0
  108. package/lib/structures/rules/ITtscLintVitestRules.d.ts +141 -0
  109. package/lib/structures/rules/ITtscLintVitestRules.js +3 -0
  110. package/lib/structures/rules/ITtscLintVitestRules.js.map +1 -0
  111. package/lib/structures/rules/index.d.ts +31 -0
  112. package/lib/structures/rules/index.js +48 -0
  113. package/lib/structures/rules/index.js.map +1 -0
  114. package/linthost/ast_helpers.go +30 -5
  115. package/linthost/config.go +48 -17
  116. package/linthost/config_format.go +9 -9
  117. package/linthost/directives.go +67 -25
  118. package/linthost/dispatch.go +14 -3
  119. package/linthost/engine.go +152 -31
  120. package/linthost/fix.go +2 -2
  121. package/linthost/lsp.go +747 -0
  122. package/linthost/print_dispatch.go +2 -2
  123. package/linthost/print_nodes_function.go +2 -2
  124. package/linthost/print_nodes_object.go +1 -1
  125. package/linthost/rule_names.go +14 -0
  126. package/linthost/rules_arrays.go +2 -2
  127. package/linthost/rules_boundaries.go +532 -0
  128. package/linthost/rules_camelcase.go +133 -0
  129. package/linthost/rules_complexity.go +94 -0
  130. package/linthost/rules_consistent_return.go +130 -0
  131. package/linthost/rules_console.go +1 -1
  132. package/linthost/rules_core_extra.go +739 -0
  133. package/linthost/rules_curly.go +70 -0
  134. package/linthost/rules_cypress.go +608 -0
  135. package/linthost/rules_debugger.go +2 -2
  136. package/linthost/rules_default_case.go +39 -0
  137. package/linthost/rules_default_case_last.go +46 -0
  138. package/linthost/rules_dupes.go +3 -3
  139. package/linthost/rules_empty.go +3 -3
  140. package/linthost/rules_escape.go +44 -24
  141. package/linthost/rules_eval.go +2 -2
  142. package/linthost/rules_finally.go +2 -2
  143. package/linthost/rules_format_jsdoc.go +1 -1
  144. package/linthost/rules_format_print_width.go +9 -9
  145. package/linthost/rules_format_quotes.go +1 -1
  146. package/linthost/rules_format_semi.go +1 -1
  147. package/linthost/rules_format_sort_imports.go +1 -1
  148. package/linthost/rules_format_trailing_comma.go +1 -1
  149. package/linthost/rules_functional.go +967 -0
  150. package/linthost/rules_gap.go +24 -45
  151. package/linthost/rules_grouped_accessor_pairs.go +87 -0
  152. package/linthost/rules_guard_for_in.go +198 -0
  153. package/linthost/rules_id_length.go +77 -0
  154. package/linthost/rules_imports.go +70 -2
  155. package/linthost/rules_init_declarations.go +53 -0
  156. package/linthost/rules_jest.go +618 -0
  157. package/linthost/rules_jsdoc.go +502 -0
  158. package/linthost/rules_jsx_a11y.go +1264 -0
  159. package/linthost/rules_logic.go +12 -12
  160. package/linthost/rules_loops.go +1 -1
  161. package/linthost/rules_max_classes_per_file.go +58 -0
  162. package/linthost/rules_max_depth.go +83 -0
  163. package/linthost/rules_max_lines.go +101 -0
  164. package/linthost/rules_max_lines_per_function.go +57 -0
  165. package/linthost/rules_max_nested_callbacks.go +61 -0
  166. package/linthost/rules_max_params.go +49 -0
  167. package/linthost/rules_max_statements.go +59 -0
  168. package/linthost/rules_misc.go +1 -1
  169. package/linthost/rules_nextjs.go +697 -0
  170. package/linthost/rules_no_else_return.go +75 -0
  171. package/linthost/rules_no_empty_named_blocks.go +91 -0
  172. package/linthost/rules_no_extend_native.go +51 -0
  173. package/linthost/rules_no_import_assign.go +140 -0
  174. package/linthost/rules_no_invalid_this.go +52 -0
  175. package/linthost/rules_no_loop_func.go +85 -0
  176. package/linthost/rules_no_magic_numbers.go +123 -0
  177. package/linthost/rules_no_mixed_operators.go +80 -0
  178. package/linthost/rules_no_param_reassign.go +98 -0
  179. package/linthost/rules_no_redeclare.go +270 -0
  180. package/linthost/rules_no_restricted_imports.go +105 -0
  181. package/linthost/rules_no_restricted_syntax.go +49 -0
  182. package/linthost/rules_no_shadow.go +147 -0
  183. package/linthost/rules_no_unreachable.go +77 -0
  184. package/linthost/rules_no_useless_assignment.go +120 -0
  185. package/linthost/rules_no_useless_constructor.go +245 -0
  186. package/linthost/rules_no_useless_return.go +51 -0
  187. package/linthost/rules_params.go +1 -1
  188. package/linthost/rules_playwright.go +788 -0
  189. package/linthost/rules_prefer_arrow_callback.go +124 -0
  190. package/linthost/rules_prefer_destructuring.go +98 -0
  191. package/linthost/rules_prefer_named_capture_group.go +129 -0
  192. package/linthost/rules_prefer_rest_params.go +94 -0
  193. package/linthost/rules_problems.go +41 -30
  194. package/linthost/rules_promise.go +1128 -73
  195. package/linthost/rules_protos.go +2 -2
  196. package/linthost/rules_react.go +773 -0
  197. package/linthost/rules_react_extras.go +227 -0
  198. package/linthost/rules_react_hooks.go +848 -0
  199. package/linthost/rules_react_perf.go +293 -0
  200. package/linthost/rules_react_refresh.go +583 -0
  201. package/linthost/rules_regexp.go +410 -0
  202. package/linthost/rules_security.go +830 -0
  203. package/linthost/rules_self.go +2 -2
  204. package/linthost/rules_solid.go +1073 -0
  205. package/linthost/rules_sort_imports.go +69 -0
  206. package/linthost/rules_sort_keys.go +134 -0
  207. package/linthost/rules_storybook.go +1176 -0
  208. package/linthost/rules_strings.go +4 -4
  209. package/linthost/rules_suggestions.go +38 -38
  210. package/linthost/rules_tanstack_query.go +844 -0
  211. package/linthost/rules_testing_library.go +1204 -0
  212. package/linthost/rules_throw.go +1 -1
  213. package/linthost/rules_ts.go +19 -19
  214. package/linthost/rules_ts_async.go +399 -0
  215. package/linthost/rules_ts_class_literal_property_style.go +115 -0
  216. package/linthost/rules_ts_consistent_type_exports.go +256 -0
  217. package/linthost/rules_ts_explicit_function_return_type.go +67 -0
  218. package/linthost/rules_ts_extra.go +155 -36
  219. package/linthost/rules_ts_no_base_to_string.go +218 -0
  220. package/linthost/rules_ts_no_confusing_void.go +72 -0
  221. package/linthost/rules_ts_no_deprecated.go +195 -0
  222. package/linthost/rules_ts_no_for_in_array.go +84 -0
  223. package/linthost/rules_ts_no_magic_numbers.go +124 -0
  224. package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
  225. package/linthost/rules_ts_no_misused_spread.go +104 -0
  226. package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
  227. package/linthost/rules_ts_no_restricted_types.go +62 -0
  228. package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
  229. package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
  230. package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
  231. package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
  232. package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
  233. package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
  234. package/linthost/rules_ts_no_unsafe_argument.go +82 -0
  235. package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
  236. package/linthost/rules_ts_no_unsafe_call.go +82 -0
  237. package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
  238. package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
  239. package/linthost/rules_ts_no_unsafe_return.go +126 -0
  240. package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
  241. package/linthost/rules_ts_no_useless_constructor.go +52 -0
  242. package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
  243. package/linthost/rules_ts_parameter_properties.go +38 -0
  244. package/linthost/rules_ts_prefer_find.go +178 -0
  245. package/linthost/rules_ts_prefer_includes.go +255 -0
  246. package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
  247. package/linthost/rules_ts_prefer_optional_chain.go +228 -0
  248. package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
  249. package/linthost/rules_ts_prefer_readonly.go +73 -0
  250. package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
  251. package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
  252. package/linthost/rules_ts_prefer_return_this_type.go +135 -0
  253. package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
  254. package/linthost/rules_ts_promise_function_async.go +77 -0
  255. package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
  256. package/linthost/rules_ts_require_array_sort_compare.go +96 -0
  257. package/linthost/rules_ts_restrict_plus_operands.go +127 -0
  258. package/linthost/rules_ts_restrict_template_expressions.go +95 -0
  259. package/linthost/rules_ts_simple.go +387 -0
  260. package/linthost/rules_ts_sort_type_constituents.go +144 -0
  261. package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
  262. package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
  263. package/linthost/rules_ts_unbound_method.go +126 -0
  264. package/linthost/rules_tsdoc.go +136 -0
  265. package/linthost/rules_unicorn_better_regex.go +27 -0
  266. package/linthost/rules_unicorn_catch_error_name.go +46 -0
  267. package/linthost/rules_unicorn_consistent_assert.go +47 -0
  268. package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
  269. package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
  270. package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
  271. package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
  272. package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
  273. package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
  274. package/linthost/rules_unicorn_custom_error_definition.go +138 -0
  275. package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
  276. package/linthost/rules_unicorn_error_message.go +64 -0
  277. package/linthost/rules_unicorn_escape_case.go +51 -0
  278. package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
  279. package/linthost/rules_unicorn_explicit_length_check.go +88 -0
  280. package/linthost/rules_unicorn_filename_case.go +29 -0
  281. package/linthost/rules_unicorn_import_style.go +28 -0
  282. package/linthost/rules_unicorn_isolated_functions.go +29 -0
  283. package/linthost/rules_unicorn_new_for_builtins.go +87 -0
  284. package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
  285. package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
  286. package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
  287. package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
  288. package/linthost/rules_unicorn_no_array_for_each.go +40 -0
  289. package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
  290. package/linthost/rules_unicorn_no_array_reduce.go +41 -0
  291. package/linthost/rules_unicorn_no_array_reverse.go +44 -0
  292. package/linthost/rules_unicorn_no_array_sort.go +43 -0
  293. package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
  294. package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
  295. package/linthost/rules_unicorn_no_console_spaces.go +61 -0
  296. package/linthost/rules_unicorn_no_document_cookie.go +41 -0
  297. package/linthost/rules_unicorn_no_empty_file.go +44 -0
  298. package/linthost/rules_unicorn_no_for_loop.go +102 -0
  299. package/linthost/rules_unicorn_no_hex_escape.go +42 -0
  300. package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
  301. package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
  302. package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
  303. package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
  304. package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
  305. package/linthost/rules_unicorn_no_lonely_if.go +44 -0
  306. package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
  307. package/linthost/rules_unicorn_no_named_default.go +54 -0
  308. package/linthost/rules_unicorn_no_negated_condition.go +85 -0
  309. package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
  310. package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
  311. package/linthost/rules_unicorn_no_new_array.go +30 -0
  312. package/linthost/rules_unicorn_no_new_buffer.go +31 -0
  313. package/linthost/rules_unicorn_no_null.go +24 -0
  314. package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
  315. package/linthost/rules_unicorn_no_process_exit.go +43 -0
  316. package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
  317. package/linthost/rules_unicorn_no_static_only_class.go +56 -0
  318. package/linthost/rules_unicorn_no_thenable.go +74 -0
  319. package/linthost/rules_unicorn_no_this_assignment.go +35 -0
  320. package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
  321. package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
  322. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
  323. package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
  324. package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
  325. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
  326. package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
  327. package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
  328. package/linthost/rules_unicorn_no_unused_properties.go +30 -0
  329. package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
  330. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
  331. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
  332. package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
  333. package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
  334. package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
  335. package/linthost/rules_unicorn_no_useless_spread.go +67 -0
  336. package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
  337. package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
  338. package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
  339. package/linthost/rules_unicorn_number_literal_case.go +69 -0
  340. package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
  341. package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
  342. package/linthost/rules_unicorn_prefer_array_find.go +51 -0
  343. package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
  344. package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
  345. package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
  346. package/linthost/rules_unicorn_prefer_array_some.go +67 -0
  347. package/linthost/rules_unicorn_prefer_at.go +77 -0
  348. package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
  349. package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
  350. package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
  351. package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
  352. package/linthost/rules_unicorn_prefer_code_point.go +49 -0
  353. package/linthost/rules_unicorn_prefer_date_now.go +78 -0
  354. package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
  355. package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
  356. package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
  357. package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
  358. package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
  359. package/linthost/rules_unicorn_prefer_event_target.go +36 -0
  360. package/linthost/rules_unicorn_prefer_export_from.go +129 -0
  361. package/linthost/rules_unicorn_prefer_global_this.go +127 -0
  362. package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
  363. package/linthost/rules_unicorn_prefer_includes.go +149 -0
  364. package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
  365. package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
  366. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
  367. package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
  368. package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
  369. package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
  370. package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
  371. package/linthost/rules_unicorn_prefer_module.go +50 -0
  372. package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
  373. package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
  374. package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
  375. package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
  376. package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
  377. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
  378. package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
  379. package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
  380. package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
  381. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
  382. package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
  383. package/linthost/rules_unicorn_prefer_set_has.go +42 -0
  384. package/linthost/rules_unicorn_prefer_set_size.go +48 -0
  385. package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
  386. package/linthost/rules_unicorn_prefer_single_call.go +96 -0
  387. package/linthost/rules_unicorn_prefer_spread.go +51 -0
  388. package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
  389. package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
  390. package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
  391. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
  392. package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
  393. package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
  394. package/linthost/rules_unicorn_prefer_switch.go +103 -0
  395. package/linthost/rules_unicorn_prefer_ternary.go +71 -0
  396. package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
  397. package/linthost/rules_unicorn_prefer_type_error.go +127 -0
  398. package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
  399. package/linthost/rules_unicorn_relative_url_style.go +49 -0
  400. package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
  401. package/linthost/rules_unicorn_require_module_attributes.go +54 -0
  402. package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
  403. package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
  404. package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
  405. package/linthost/rules_unicorn_string_content.go +27 -0
  406. package/linthost/rules_unicorn_switch_case_braces.go +42 -0
  407. package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
  408. package/linthost/rules_unicorn_template_indent.go +28 -0
  409. package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
  410. package/linthost/rules_unicorn_throw_new_error.go +61 -0
  411. package/linthost/rules_var.go +4 -4
  412. package/linthost/rules_vitest.go +568 -0
  413. package/package.json +3 -3
  414. package/plugin/main.go +49 -3
  415. package/rule/astutil/astutil.go +10 -3
  416. package/rule/rule.go +12 -10
  417. package/src/defaultFormat.ts +11 -8
  418. package/src/index.ts +40 -16
  419. package/src/structures/ITtscLintConfig.ts +12 -6
  420. package/src/structures/{ITtscLintFormatConfig.ts → ITtscLintFormat.ts} +2 -2
  421. package/src/structures/TtscLintRuleSetting.ts +55 -0
  422. package/src/structures/index.ts +3 -4
  423. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +128 -0
  424. package/src/structures/rules/ITtscLintBoundariesRules.ts +95 -0
  425. package/src/structures/rules/ITtscLintContributorRules.ts +21 -0
  426. package/src/structures/rules/ITtscLintCoreRules.ts +1406 -0
  427. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
  428. package/src/structures/rules/ITtscLintCypressRules.ts +145 -0
  429. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +213 -0
  430. package/src/structures/rules/ITtscLintFunctionalRules.ts +202 -0
  431. package/src/structures/rules/ITtscLintJestRules.ts +220 -0
  432. package/src/structures/rules/ITtscLintJsdocRules.ts +153 -0
  433. package/src/structures/rules/ITtscLintJsxA11yRules.ts +339 -0
  434. package/src/structures/rules/ITtscLintNextjsRules.ts +206 -0
  435. package/src/structures/rules/ITtscLintPlaywrightRules.ts +361 -0
  436. package/src/structures/rules/ITtscLintPromiseRules.ts +205 -0
  437. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
  438. package/src/structures/rules/ITtscLintReactPerfRules.ts +55 -0
  439. package/src/structures/rules/ITtscLintReactRuleOptions.ts +43 -0
  440. package/src/structures/rules/ITtscLintReactRules.ts +321 -0
  441. package/src/structures/rules/ITtscLintRegexpRules.ts +212 -0
  442. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +89 -0
  443. package/src/structures/rules/ITtscLintRules.ts +77 -0
  444. package/src/structures/rules/ITtscLintSecurityRules.ts +162 -0
  445. package/src/structures/rules/ITtscLintSolidRules.ts +202 -0
  446. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +23 -0
  447. package/src/structures/rules/ITtscLintStorybookRules.ts +193 -0
  448. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +102 -0
  449. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +24 -0
  450. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +342 -0
  451. package/src/structures/rules/ITtscLintTypeScriptRules.ts +1230 -0
  452. package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
  453. package/src/structures/rules/ITtscLintVitestRules.ts +154 -0
  454. package/src/structures/rules/index.ts +31 -0
  455. package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
  456. package/lib/structures/TtscLintRule.d.ts +0 -17
  457. package/lib/structures/TtscLintRule.js.map +0 -1
  458. package/lib/structures/TtscLintRuleMap.d.ts +0 -46
  459. package/lib/structures/TtscLintRuleMap.js.map +0 -1
  460. package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
  461. package/lib/structures/TtscLintRuleOptions.js.map +0 -1
  462. package/src/structures/TtscLintRule.ts +0 -160
  463. package/src/structures/TtscLintRuleMap.ts +0 -55
  464. package/src/structures/TtscLintRuleOptions.ts +0 -151
@@ -0,0 +1,75 @@
1
+ // noElseReturn: when an `if` block ends in a `return` / `throw` /
2
+ // `break` / `continue` statement, the matching `else` block is
3
+ // redundant — control already left the function (or loop), so flatten
4
+ // the `else` body into the surrounding scope to keep one less level of
5
+ // nesting and one less branch to read.
6
+ // https://eslint.org/docs/latest/rules/no-else-return
7
+ //
8
+ // AST-only: each visited `IfStatement` whose `ThenStatement` provably
9
+ // terminates control flow on every branch reports on the `else`
10
+ // keyword. A `then` branch terminates when:
11
+ //
12
+ // - it is itself a terminating statement (`return`, `throw`, etc.), or
13
+ // - it is a `Block` whose final statement terminates AND every
14
+ // `if/else if/else` chain inside it terminates on every leaf, or
15
+ // - it is an `IfStatement` whose `then` AND `else` both terminate
16
+ // (chained early returns).
17
+ //
18
+ // The analysis is conservative; ambiguous shapes (e.g. an `if` with no
19
+ // `else`, or a loop with `break` only) are left alone.
20
+ package linthost
21
+
22
+ import (
23
+ shimast "github.com/microsoft/typescript-go/shim/ast"
24
+ )
25
+
26
+ type noElseReturn struct{}
27
+
28
+ func (noElseReturn) Name() string { return "no-else-return" }
29
+ func (noElseReturn) Visits() []shimast.Kind {
30
+ return []shimast.Kind{shimast.KindIfStatement}
31
+ }
32
+ func (noElseReturn) Check(ctx *Context, node *shimast.Node) {
33
+ ifStmt := node.AsIfStatement()
34
+ if ifStmt == nil || ifStmt.ElseStatement == nil {
35
+ return
36
+ }
37
+ if !noElseReturnTerminates(ifStmt.ThenStatement) {
38
+ return
39
+ }
40
+ ctx.Report(ifStmt.ElseStatement, "Remove the `else` — the preceding branch already terminates.")
41
+ }
42
+
43
+ func noElseReturnTerminates(stmt *shimast.Node) bool {
44
+ if stmt == nil {
45
+ return false
46
+ }
47
+ switch stmt.Kind {
48
+ case shimast.KindReturnStatement,
49
+ shimast.KindThrowStatement,
50
+ shimast.KindBreakStatement,
51
+ shimast.KindContinueStatement:
52
+ return true
53
+ case shimast.KindBlock:
54
+ block := stmt.AsBlock()
55
+ if block == nil || block.Statements == nil {
56
+ return false
57
+ }
58
+ stmts := block.Statements.Nodes
59
+ if len(stmts) == 0 {
60
+ return false
61
+ }
62
+ return noElseReturnTerminates(stmts[len(stmts)-1])
63
+ case shimast.KindIfStatement:
64
+ inner := stmt.AsIfStatement()
65
+ if inner == nil || inner.ElseStatement == nil {
66
+ return false
67
+ }
68
+ return noElseReturnTerminates(inner.ThenStatement) && noElseReturnTerminates(inner.ElseStatement)
69
+ }
70
+ return false
71
+ }
72
+
73
+ func init() {
74
+ Register(noElseReturn{})
75
+ }
@@ -0,0 +1,91 @@
1
+ // no-empty-named-blocks: empty `{}` clauses on import or export
2
+ // declarations bind nothing and almost always indicate a mid-edit
3
+ // mistake or a leftover marker. ESLint suggestions / extra-rules:
4
+ // https://eslint.org/docs/latest/rules/no-empty-named-blocks
5
+ //
6
+ // Three shapes fire the rule:
7
+ //
8
+ // - `import {} from "x"` — only the side-effect load remains; write
9
+ // `import "x"` instead if that is the intent.
10
+ // - `import name, {} from "x"` — once a default binding is present the
11
+ // `{}` adds nothing; drop the empty clause.
12
+ // - `export {}` — restates module-ness redundantly, or marks an
13
+ // otherwise non-module file in a way that has cleaner alternatives
14
+ // (`no-useless-empty-export` is the stricter sibling that fires
15
+ // only when another module-syntax statement is already present).
16
+ //
17
+ // AST-only; the rule never consults the Checker.
18
+ package linthost
19
+
20
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
21
+
22
+ type noEmptyNamedBlocks struct{}
23
+
24
+ func (noEmptyNamedBlocks) Name() string { return "no-empty-named-blocks" }
25
+ func (noEmptyNamedBlocks) Visits() []shimast.Kind {
26
+ return []shimast.Kind{shimast.KindImportDeclaration, shimast.KindExportDeclaration}
27
+ }
28
+ func (noEmptyNamedBlocks) Check(ctx *Context, node *shimast.Node) {
29
+ switch node.Kind {
30
+ case shimast.KindImportDeclaration:
31
+ noEmptyNamedBlocksCheckImport(ctx, node)
32
+ case shimast.KindExportDeclaration:
33
+ noEmptyNamedBlocksCheckExport(ctx, node)
34
+ }
35
+ }
36
+
37
+ // noEmptyNamedBlocksCheckImport flags `import {} from "x"` and
38
+ // `import name, {} from "x"`. The empty-clause-only form should become
39
+ // a bare `import "x"`; the default-plus-empty form should drop the
40
+ // empty clause and keep the default binding.
41
+ func noEmptyNamedBlocksCheckImport(ctx *Context, node *shimast.Node) {
42
+ decl := node.AsImportDeclaration()
43
+ if decl == nil || decl.ImportClause == nil {
44
+ return
45
+ }
46
+ clause := decl.ImportClause.AsImportClause()
47
+ if clause == nil {
48
+ return
49
+ }
50
+ if clause.NamedBindings == nil {
51
+ return
52
+ }
53
+ if clause.NamedBindings.Kind != shimast.KindNamedImports {
54
+ return
55
+ }
56
+ named := clause.NamedBindings.AsNamedImports()
57
+ if named == nil || named.Elements == nil || len(named.Elements.Nodes) > 0 {
58
+ return
59
+ }
60
+ // Two shapes both reach here:
61
+ // `import {} from "x"` — clause.Name() == nil
62
+ // `import name, {} from "x"` — clause.Name() != nil
63
+ // Either way the empty `{}` is what the rule blames; the report
64
+ // target is the empty named-imports node so the highlight points at
65
+ // the `{}` token, not the whole declaration.
66
+ ctx.Report(clause.NamedBindings, "Unexpected empty named import block.")
67
+ }
68
+
69
+ // noEmptyNamedBlocksCheckExport flags `export {}` (with or without a
70
+ // `from "x"` source). The form is always rewritable to either nothing
71
+ // or a bare side-effect `import "x"`; the rule's role is to surface it
72
+ // uniformly across both module and non-module sources, leaving
73
+ // `no-useless-empty-export` to gate the narrower redundant-marker case.
74
+ func noEmptyNamedBlocksCheckExport(ctx *Context, node *shimast.Node) {
75
+ decl := node.AsExportDeclaration()
76
+ if decl == nil || decl.ExportClause == nil {
77
+ return
78
+ }
79
+ if decl.ExportClause.Kind != shimast.KindNamedExports {
80
+ return
81
+ }
82
+ named := decl.ExportClause.AsNamedExports()
83
+ if named == nil || named.Elements == nil || len(named.Elements.Nodes) > 0 {
84
+ return
85
+ }
86
+ ctx.Report(node, "Unexpected empty named export block.")
87
+ }
88
+
89
+ func init() {
90
+ Register(noEmptyNamedBlocks{})
91
+ }
@@ -0,0 +1,51 @@
1
+ package linthost
2
+
3
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
4
+
5
+ // noExtendNative: forbid assignments to `<Builtin>.prototype.<key>`,
6
+ // which mutate a shared global and leak across the entire realm.
7
+ // https://eslint.org/docs/latest/rules/no-extend-native
8
+ type noExtendNative struct{}
9
+
10
+ func (noExtendNative) Name() string { return "no-extend-native" }
11
+ func (noExtendNative) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindBinaryExpression} }
12
+ func (noExtendNative) Check(ctx *Context, node *shimast.Node) {
13
+ expr := node.AsBinaryExpression()
14
+ if expr == nil || expr.OperatorToken == nil {
15
+ return
16
+ }
17
+ if expr.OperatorToken.Kind != shimast.KindEqualsToken {
18
+ return
19
+ }
20
+ outer := stripParens(expr.Left)
21
+ if outer == nil || outer.Kind != shimast.KindPropertyAccessExpression {
22
+ return
23
+ }
24
+ receiver := stripParens(outer.AsPropertyAccessExpression().Expression)
25
+ if receiver == nil || receiver.Kind != shimast.KindPropertyAccessExpression {
26
+ return
27
+ }
28
+ inner := receiver.AsPropertyAccessExpression()
29
+ if identifierText(inner.Name()) != "prototype" {
30
+ return
31
+ }
32
+ builtin := identifierText(stripParens(inner.Expression))
33
+ if !isExtendNativeBuiltin(builtin) {
34
+ return
35
+ }
36
+ ctx.Report(node, builtin+" prototype is read only, properties should not be added.")
37
+ }
38
+
39
+ func isExtendNativeBuiltin(name string) bool {
40
+ switch name {
41
+ case "Object", "Array", "String", "Number", "Boolean", "Function",
42
+ "Date", "RegExp", "Error", "Map", "Set", "WeakMap", "WeakSet",
43
+ "Promise", "Symbol":
44
+ return true
45
+ }
46
+ return false
47
+ }
48
+
49
+ func init() {
50
+ Register(noExtendNative{})
51
+ }
@@ -0,0 +1,140 @@
1
+ // noImportAssign: writes to a binding introduced by an `import`
2
+ // declaration. Imported bindings are read-only at runtime; mutating
3
+ // them either throws under strict mode or silently desynchronises the
4
+ // module's view of its own exports.
5
+ //
6
+ // Conservative scope tracking: collect the local names introduced by
7
+ // every `import` declaration in the file (default specifier, named
8
+ // specifier, namespace alias), then walk descendants once and flag
9
+ // `name = …` / `name op= …` / `++name` / `name--` assignments whose
10
+ // left-hand side is one of those names. Namespace imports are also
11
+ // flagged on `ns.foo = …` / `++ns.foo` because the namespace object
12
+ // is itself frozen — mutating any property throws in strict mode.
13
+ //
14
+ // Like `no-param-reassign`, this is an AST-only baseline: a later
15
+ // `const name = …` inside an inner scope that shadows an imported
16
+ // name will produce a false positive. Proper resolution needs the
17
+ // real binder, which the AST-only baseline avoids.
18
+ // https://eslint.org/docs/latest/rules/no-import-assign
19
+ package linthost
20
+
21
+ import shimast "github.com/microsoft/typescript-go/shim/ast"
22
+
23
+ type noImportAssign struct{}
24
+
25
+ func (noImportAssign) Name() string { return "no-import-assign" }
26
+ func (noImportAssign) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindSourceFile} }
27
+ func (noImportAssign) Check(ctx *Context, node *shimast.Node) {
28
+ if node == nil {
29
+ return
30
+ }
31
+ imported := map[string]bool{}
32
+ namespaces := map[string]bool{}
33
+ collectImportedBindings(node, imported, namespaces)
34
+ if len(imported) == 0 {
35
+ return
36
+ }
37
+ walkDescendants(node, func(n *shimast.Node) {
38
+ switch n.Kind {
39
+ case shimast.KindBinaryExpression:
40
+ expr := n.AsBinaryExpression()
41
+ if expr == nil || expr.OperatorToken == nil || !isAssignmentOperator(expr.OperatorToken.Kind) {
42
+ return
43
+ }
44
+ reportImportTarget(ctx, expr.Left, imported, namespaces)
45
+ case shimast.KindPrefixUnaryExpression:
46
+ pre := n.AsPrefixUnaryExpression()
47
+ if pre == nil || (pre.Operator != shimast.KindPlusPlusToken && pre.Operator != shimast.KindMinusMinusToken) {
48
+ return
49
+ }
50
+ reportImportTarget(ctx, pre.Operand, imported, namespaces)
51
+ case shimast.KindPostfixUnaryExpression:
52
+ post := n.AsPostfixUnaryExpression()
53
+ if post == nil || (post.Operator != shimast.KindPlusPlusToken && post.Operator != shimast.KindMinusMinusToken) {
54
+ return
55
+ }
56
+ reportImportTarget(ctx, post.Operand, imported, namespaces)
57
+ }
58
+ })
59
+ }
60
+
61
+ // collectImportedBindings walks every `import` declaration in `file` and
62
+ // records the local names introduced. Namespace bindings (`* as ns`) are
63
+ // additionally remembered so callers can flag property mutations like
64
+ // `ns.foo = …`.
65
+ func collectImportedBindings(file *shimast.Node, imported, namespaces map[string]bool) {
66
+ walkDescendants(file, func(n *shimast.Node) {
67
+ if n == nil || n.Kind != shimast.KindImportDeclaration {
68
+ return
69
+ }
70
+ decl := n.AsImportDeclaration()
71
+ if decl == nil || decl.ImportClause == nil {
72
+ return
73
+ }
74
+ clause := decl.ImportClause.AsImportClause()
75
+ if clause == nil {
76
+ return
77
+ }
78
+ // `import Default from "x"` — default specifier.
79
+ if name := identifierText(clause.Name()); name != "" {
80
+ imported[name] = true
81
+ }
82
+ if clause.NamedBindings == nil {
83
+ return
84
+ }
85
+ switch clause.NamedBindings.Kind {
86
+ case shimast.KindNamedImports:
87
+ named := clause.NamedBindings.AsNamedImports()
88
+ if named == nil || named.Elements == nil {
89
+ return
90
+ }
91
+ for _, specNode := range named.Elements.Nodes {
92
+ spec := specNode.AsImportSpecifier()
93
+ if spec == nil {
94
+ continue
95
+ }
96
+ if name := identifierText(spec.Name()); name != "" {
97
+ imported[name] = true
98
+ }
99
+ }
100
+ case shimast.KindNamespaceImport:
101
+ ns := clause.NamedBindings.AsNamespaceImport()
102
+ if ns == nil {
103
+ return
104
+ }
105
+ if name := identifierText(ns.Name()); name != "" {
106
+ imported[name] = true
107
+ namespaces[name] = true
108
+ }
109
+ }
110
+ })
111
+ }
112
+
113
+ // reportImportTarget flags `target` when it writes to an imported name.
114
+ // A bare identifier matching an imported binding is always flagged; a
115
+ // `ns.<key>` property access is flagged when `ns` is a namespace import.
116
+ func reportImportTarget(ctx *Context, target *shimast.Node, imported, namespaces map[string]bool) {
117
+ stripped := stripParens(target)
118
+ if stripped == nil {
119
+ return
120
+ }
121
+ if name := identifierText(stripped); name != "" {
122
+ if imported[name] {
123
+ ctx.Report(target, "'"+name+"' is read-only.")
124
+ }
125
+ return
126
+ }
127
+ if stripped.Kind == shimast.KindPropertyAccessExpression {
128
+ access := stripped.AsPropertyAccessExpression()
129
+ if access == nil || access.Expression == nil {
130
+ return
131
+ }
132
+ if ns := identifierText(stripParens(access.Expression)); ns != "" && namespaces[ns] {
133
+ ctx.Report(target, "The members of '"+ns+"' are read-only.")
134
+ }
135
+ }
136
+ }
137
+
138
+ func init() {
139
+ Register(noImportAssign{})
140
+ }
@@ -0,0 +1,52 @@
1
+ // noInvalidThis: reject `this` references that have no meaningful
2
+ // binding — that is, `this` used outside any function-like context or
3
+ // class static block. At the top level of a module (and in strict-mode
4
+ // scripts) `this` is `undefined`, so reading from it usually signals a
5
+ // copy-paste from a class method.
6
+ //
7
+ // Arrow functions inherit `this` from their enclosing lexical scope, so
8
+ // the rule walks past arrow boundaries when searching for a binding
9
+ // site. Plain function declarations, function expressions, methods,
10
+ // accessors, constructors, and class static blocks each create their
11
+ // own `this` and stop the walk.
12
+ // https://eslint.org/docs/latest/rules/no-invalid-this
13
+ package linthost
14
+
15
+ import (
16
+ shimast "github.com/microsoft/typescript-go/shim/ast"
17
+ )
18
+
19
+ type noInvalidThis struct{}
20
+
21
+ func (noInvalidThis) Name() string { return "no-invalid-this" }
22
+ func (noInvalidThis) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindThisKeyword} }
23
+ func (noInvalidThis) Check(ctx *Context, node *shimast.Node) {
24
+ if hasThisBindingAncestor(node) {
25
+ return
26
+ }
27
+ ctx.Report(node, "Unexpected 'this'.")
28
+ }
29
+
30
+ // hasThisBindingAncestor reports whether `node` is lexically enclosed by
31
+ // a construct that defines its own `this`. Arrow functions are skipped
32
+ // because they capture `this` from the surrounding scope; the walk only
33
+ // stops on a real binding site or at the SourceFile root.
34
+ func hasThisBindingAncestor(node *shimast.Node) bool {
35
+ for cur := node.Parent; cur != nil; cur = cur.Parent {
36
+ switch cur.Kind {
37
+ case shimast.KindFunctionDeclaration,
38
+ shimast.KindFunctionExpression,
39
+ shimast.KindMethodDeclaration,
40
+ shimast.KindGetAccessor,
41
+ shimast.KindSetAccessor,
42
+ shimast.KindConstructor,
43
+ shimast.KindClassStaticBlockDeclaration:
44
+ return true
45
+ }
46
+ }
47
+ return false
48
+ }
49
+
50
+ func init() {
51
+ Register(noInvalidThis{})
52
+ }
@@ -0,0 +1,85 @@
1
+ // noLoopFunc reports a `function` declaration, function expression, or
2
+ // arrow function defined inside the body of a loop. The function value
3
+ // allocated each iteration almost always closes over the loop counter or
4
+ // some other binding that changes between iterations, so a deferred call
5
+ // (timer, microtask, event handler) observes whatever the binding holds
6
+ // at call time — usually the loop's terminal value, never the value the
7
+ // developer reasoned about at the textual position.
8
+ // https://eslint.org/docs/latest/rules/no-loop-func
9
+ //
10
+ // Conservative baseline: every function-like syntactically inside a loop
11
+ // body is flagged. Capture analysis (the rule's full upstream
12
+ // implementation only fires when the function actually closes over a
13
+ // `let` / `var` / `const` declared outside) is deferred; the false-
14
+ // positive rate is acceptable because the fix — hoist the function out
15
+ // of the loop — is almost always the cleaner code in either case.
16
+ //
17
+ // The walk stops at nested loop boundaries — each enclosing loop visits
18
+ // itself once, so an inner loop reports its own nested function-likes
19
+ // and the outer loop only owns the function-likes directly inside it.
20
+ // Inner function-likes are also boundaries: a closure inside an outer
21
+ // function-likes is that inner scope's problem.
22
+ package linthost
23
+
24
+ import (
25
+ shimast "github.com/microsoft/typescript-go/shim/ast"
26
+ )
27
+
28
+ type noLoopFunc struct{}
29
+
30
+ func (noLoopFunc) Name() string { return "no-loop-func" }
31
+ func (noLoopFunc) Visits() []shimast.Kind {
32
+ return []shimast.Kind{
33
+ shimast.KindForStatement,
34
+ shimast.KindForInStatement,
35
+ shimast.KindForOfStatement,
36
+ shimast.KindWhileStatement,
37
+ shimast.KindDoStatement,
38
+ }
39
+ }
40
+ func (noLoopFunc) Check(ctx *Context, node *shimast.Node) {
41
+ var walk func(n *shimast.Node)
42
+ walk = func(n *shimast.Node) {
43
+ if n == nil {
44
+ return
45
+ }
46
+ if isFunctionLikeKind(n) {
47
+ ctx.Report(n, "Function declared in a loop closes over the loop's bindings — hoist it out.")
48
+ return
49
+ }
50
+ if n != node && isLoopKind(n) {
51
+ // Nested loops report their own contents when visited.
52
+ return
53
+ }
54
+ n.ForEachChild(func(child *shimast.Node) bool {
55
+ walk(child)
56
+ return false
57
+ })
58
+ }
59
+ node.ForEachChild(func(child *shimast.Node) bool {
60
+ walk(child)
61
+ return false
62
+ })
63
+ }
64
+
65
+ // isLoopKind reports whether n is one of the loop statement kinds this
66
+ // rule visits. Used to stop the walk at a nested loop boundary so each
67
+ // loop reports only the function-likes directly inside its own body.
68
+ func isLoopKind(n *shimast.Node) bool {
69
+ if n == nil {
70
+ return false
71
+ }
72
+ switch n.Kind {
73
+ case shimast.KindForStatement,
74
+ shimast.KindForInStatement,
75
+ shimast.KindForOfStatement,
76
+ shimast.KindWhileStatement,
77
+ shimast.KindDoStatement:
78
+ return true
79
+ }
80
+ return false
81
+ }
82
+
83
+ func init() {
84
+ Register(noLoopFunc{})
85
+ }
@@ -0,0 +1,123 @@
1
+ // noMagicNumbers reports a numeric literal that appears in a position
2
+ // other than the initializer of a `const` declaration. Magic numbers
3
+ // scattered through expressions make a reader pause: a literal `60`
4
+ // inside a multiplication says nothing about whether it stands for
5
+ // seconds, frames, or items-per-page, while the same number bound to a
6
+ // `const SECONDS_PER_MINUTE = 60` carries its meaning along with it.
7
+ //
8
+ // Conservative baseline:
9
+ //
10
+ // - Three numbers are silently ignored — `0`, `1`, and `-1`. The
11
+ // first two are pervasive in counters and identity-style code; the
12
+ // third is the canonical "not-found" return from `indexOf` and
13
+ // similar APIs. Flagging them produces nothing but noise.
14
+ // - A numeric literal that is the initializer of a `const x = …`
15
+ // declaration is the named binding the rule is asking for, so it
16
+ // is not flagged.
17
+ // - A numeric literal that is the index of a `KindElementAccessExpression`
18
+ // (`arr[0]`, `tuple[3]`) is treated as an array index and ignored;
19
+ // ESLint's `ignoreArrayIndexes` option is on by default here.
20
+ // - A numeric literal that initializes an `enum` member is the
21
+ // binding's value, not a magic number — enums exist precisely to
22
+ // give numeric values names, so the value position is the point of
23
+ // the construct.
24
+ //
25
+ // https://eslint.org/docs/latest/rules/no-magic-numbers
26
+ package linthost
27
+
28
+ import (
29
+ shimast "github.com/microsoft/typescript-go/shim/ast"
30
+ )
31
+
32
+ type noMagicNumbers struct{}
33
+
34
+ func (noMagicNumbers) Name() string { return "no-magic-numbers" }
35
+ func (noMagicNumbers) Visits() []shimast.Kind {
36
+ return []shimast.Kind{shimast.KindNumericLiteral}
37
+ }
38
+ func (noMagicNumbers) Check(ctx *Context, node *shimast.Node) {
39
+ if node == nil {
40
+ return
41
+ }
42
+ text := numericLiteralText(node)
43
+ if isIgnoredMagicLiteralText(text) {
44
+ return
45
+ }
46
+ parent := node.Parent
47
+ if parent == nil {
48
+ return
49
+ }
50
+ // `-N` is a PrefixUnaryExpression whose Operand is the literal. The
51
+ // `-1` ignore list lives on the unary expression's combined text;
52
+ // recognize the negated form here so the rule does not flag the `1`
53
+ // inside `-1`.
54
+ if parent.Kind == shimast.KindPrefixUnaryExpression {
55
+ pre := parent.AsPrefixUnaryExpression()
56
+ if pre != nil && pre.Operator == shimast.KindMinusToken && text == "1" {
57
+ return
58
+ }
59
+ }
60
+ // Initializer of a `const x = N` declaration: the named binding the
61
+ // rule wants users to introduce.
62
+ if isConstVariableInitializer(parent, node) {
63
+ return
64
+ }
65
+ // Enum member value: `enum E { A = 0, B = 1 }` — the literal is
66
+ // the binding's value position, so leave it alone.
67
+ if parent.Kind == shimast.KindEnumMember {
68
+ return
69
+ }
70
+ // `arr[0]` / `tuple[3]`: numeric index position of an element access.
71
+ if isArrayIndexArgument(parent, node) {
72
+ return
73
+ }
74
+ ctx.Report(node, "No magic number: "+text+".")
75
+ }
76
+
77
+ // isIgnoredMagicLiteralText reports whether the literal text falls into
78
+ // the always-ignored set. `-1` is handled by the caller (the leading
79
+ // minus lives on a PrefixUnaryExpression parent), so the table here only
80
+ // needs the two zero / one shapes.
81
+ func isIgnoredMagicLiteralText(text string) bool {
82
+ switch text {
83
+ case "0", "1":
84
+ return true
85
+ }
86
+ return false
87
+ }
88
+
89
+ // isConstVariableInitializer reports whether `literal` sits in the
90
+ // Initializer slot of a `const x = literal` VariableDeclaration. `let`
91
+ // and `var` are deliberately excluded — a `let x = 60` binding can be
92
+ // reassigned, so the number is still magic in the position it was
93
+ // written.
94
+ func isConstVariableInitializer(parent, literal *shimast.Node) bool {
95
+ if parent == nil || parent.Kind != shimast.KindVariableDeclaration {
96
+ return false
97
+ }
98
+ decl := parent.AsVariableDeclaration()
99
+ if decl == nil || decl.Initializer != literal {
100
+ return false
101
+ }
102
+ return shimast.IsConst(parent)
103
+ }
104
+
105
+ // isArrayIndexArgument reports whether `literal` sits in the
106
+ // ArgumentExpression slot of a `target[literal]` ElementAccessExpression.
107
+ // ESLint calls this `ignoreArrayIndexes`; the rule's conservative
108
+ // baseline enables it because mixing numeric subscripts with renamed
109
+ // constants reads worse than the literal.
110
+ func isArrayIndexArgument(parent, literal *shimast.Node) bool {
111
+ if parent == nil || parent.Kind != shimast.KindElementAccessExpression {
112
+ return false
113
+ }
114
+ access := parent.AsElementAccessExpression()
115
+ if access == nil {
116
+ return false
117
+ }
118
+ return access.ArgumentExpression == literal
119
+ }
120
+
121
+ func init() {
122
+ Register(noMagicNumbers{})
123
+ }