@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,967 @@
1
+ package linthost
2
+
3
+ import (
4
+ "regexp"
5
+ "strings"
6
+
7
+ shimast "github.com/microsoft/typescript-go/shim/ast"
8
+ )
9
+
10
+ type functionalParameters struct{}
11
+ type functionalImmutableData struct{}
12
+ type functionalNoClassInheritance struct{}
13
+ type functionalNoClasses struct{}
14
+ type functionalNoConditionalStatements struct{}
15
+ type functionalNoExpressionStatements struct{}
16
+ type functionalNoLet struct{}
17
+ type functionalNoLoopStatements struct{}
18
+ type functionalNoMixedTypes struct{}
19
+ type functionalNoPromiseReject struct{}
20
+ type functionalNoReturnVoid struct{}
21
+ type functionalNoThisExpressions struct{}
22
+ type functionalNoThrowStatements struct{}
23
+ type functionalNoTryStatements struct{}
24
+ type functionalPreferImmutableTypes struct{}
25
+ type functionalPreferPropertySignatures struct{}
26
+ type functionalPreferReadonlyType struct{}
27
+ type functionalPreferTacit struct{}
28
+ type functionalReadonlyType struct{}
29
+ type functionalTypeDeclarationImmutability struct{}
30
+
31
+ func (functionalParameters) Name() string { return "functional/functional-parameters" }
32
+ func (functionalImmutableData) Name() string { return "functional/immutable-data" }
33
+ func (functionalNoClassInheritance) Name() string { return "functional/no-class-inheritance" }
34
+ func (functionalNoClasses) Name() string { return "functional/no-classes" }
35
+ func (functionalNoConditionalStatements) Name() string { return "functional/no-conditional-statements" }
36
+ func (functionalNoExpressionStatements) Name() string { return "functional/no-expression-statements" }
37
+ func (functionalNoLet) Name() string { return "functional/no-let" }
38
+ func (functionalNoLoopStatements) Name() string { return "functional/no-loop-statements" }
39
+ func (functionalNoMixedTypes) Name() string { return "functional/no-mixed-types" }
40
+ func (functionalNoPromiseReject) Name() string { return "functional/no-promise-reject" }
41
+ func (functionalNoReturnVoid) Name() string { return "functional/no-return-void" }
42
+ func (functionalNoThisExpressions) Name() string { return "functional/no-this-expressions" }
43
+ func (functionalNoThrowStatements) Name() string { return "functional/no-throw-statements" }
44
+ func (functionalNoTryStatements) Name() string { return "functional/no-try-statements" }
45
+ func (functionalPreferImmutableTypes) Name() string { return "functional/prefer-immutable-types" }
46
+ func (functionalPreferPropertySignatures) Name() string {
47
+ return "functional/prefer-property-signatures"
48
+ }
49
+ func (functionalPreferReadonlyType) Name() string { return "functional/prefer-readonly-type" }
50
+ func (functionalPreferTacit) Name() string { return "functional/prefer-tacit" }
51
+ func (functionalReadonlyType) Name() string { return "functional/readonly-type" }
52
+ func (functionalTypeDeclarationImmutability) Name() string {
53
+ return "functional/type-declaration-immutability"
54
+ }
55
+
56
+ func (functionalParameters) Visits() []shimast.Kind {
57
+ return []shimast.Kind{
58
+ shimast.KindParameter,
59
+ shimast.KindIdentifier,
60
+ shimast.KindFunctionDeclaration,
61
+ shimast.KindFunctionExpression,
62
+ shimast.KindArrowFunction,
63
+ shimast.KindMethodDeclaration,
64
+ }
65
+ }
66
+ func (functionalImmutableData) Visits() []shimast.Kind {
67
+ return []shimast.Kind{
68
+ shimast.KindBinaryExpression,
69
+ shimast.KindPrefixUnaryExpression,
70
+ shimast.KindPostfixUnaryExpression,
71
+ shimast.KindDeleteExpression,
72
+ shimast.KindCallExpression,
73
+ }
74
+ }
75
+ func (functionalNoClassInheritance) Visits() []shimast.Kind {
76
+ return []shimast.Kind{shimast.KindClassDeclaration, shimast.KindClassExpression}
77
+ }
78
+ func (functionalNoClasses) Visits() []shimast.Kind {
79
+ return []shimast.Kind{shimast.KindClassDeclaration, shimast.KindClassExpression}
80
+ }
81
+ func (functionalNoConditionalStatements) Visits() []shimast.Kind {
82
+ return []shimast.Kind{shimast.KindIfStatement, shimast.KindSwitchStatement}
83
+ }
84
+ func (functionalNoExpressionStatements) Visits() []shimast.Kind {
85
+ return []shimast.Kind{shimast.KindExpressionStatement}
86
+ }
87
+ func (functionalNoLet) Visits() []shimast.Kind {
88
+ return []shimast.Kind{shimast.KindVariableDeclarationList}
89
+ }
90
+ func (functionalNoLoopStatements) Visits() []shimast.Kind {
91
+ return []shimast.Kind{
92
+ shimast.KindForStatement,
93
+ shimast.KindForInStatement,
94
+ shimast.KindForOfStatement,
95
+ shimast.KindWhileStatement,
96
+ shimast.KindDoStatement,
97
+ }
98
+ }
99
+ func (functionalNoMixedTypes) Visits() []shimast.Kind {
100
+ return []shimast.Kind{shimast.KindInterfaceDeclaration, shimast.KindTypeLiteral}
101
+ }
102
+ func (functionalNoPromiseReject) Visits() []shimast.Kind {
103
+ return []shimast.Kind{shimast.KindCallExpression}
104
+ }
105
+ func (functionalNoReturnVoid) Visits() []shimast.Kind {
106
+ return []shimast.Kind{shimast.KindReturnStatement, shimast.KindFunctionDeclaration, shimast.KindFunctionExpression, shimast.KindArrowFunction, shimast.KindMethodDeclaration}
107
+ }
108
+ func (functionalNoThisExpressions) Visits() []shimast.Kind {
109
+ return []shimast.Kind{shimast.KindThisKeyword}
110
+ }
111
+ func (functionalNoThrowStatements) Visits() []shimast.Kind {
112
+ return []shimast.Kind{shimast.KindThrowStatement}
113
+ }
114
+ func (functionalNoTryStatements) Visits() []shimast.Kind {
115
+ return []shimast.Kind{shimast.KindTryStatement}
116
+ }
117
+ func (functionalPreferImmutableTypes) Visits() []shimast.Kind {
118
+ return []shimast.Kind{shimast.KindVariableDeclaration, shimast.KindParameter, shimast.KindPropertyDeclaration, shimast.KindPropertySignature}
119
+ }
120
+ func (functionalPreferPropertySignatures) Visits() []shimast.Kind {
121
+ return []shimast.Kind{shimast.KindMethodSignature}
122
+ }
123
+ func (functionalPreferReadonlyType) Visits() []shimast.Kind {
124
+ return []shimast.Kind{shimast.KindArrayType, shimast.KindTupleType, shimast.KindTypeReference, shimast.KindPropertySignature}
125
+ }
126
+ func (functionalPreferTacit) Visits() []shimast.Kind {
127
+ return []shimast.Kind{shimast.KindArrowFunction}
128
+ }
129
+ func (functionalReadonlyType) Visits() []shimast.Kind {
130
+ return []shimast.Kind{shimast.KindTypeReference, shimast.KindTypeOperator}
131
+ }
132
+ func (functionalTypeDeclarationImmutability) Visits() []shimast.Kind {
133
+ return []shimast.Kind{shimast.KindInterfaceDeclaration, shimast.KindTypeAliasDeclaration}
134
+ }
135
+
136
+ type functionalNoLetOptions struct {
137
+ functionalPatternOptions
138
+ AllowInForLoopInit bool `json:"allowInForLoopInit"`
139
+ AllowInFunctions bool `json:"allowInFunctions"`
140
+ }
141
+
142
+ type functionalNoTryOptions struct {
143
+ AllowCatch bool `json:"allowCatch"`
144
+ AllowFinally bool `json:"allowFinally"`
145
+ }
146
+
147
+ type functionalImmutableDataOptions struct {
148
+ functionalPatternOptions
149
+ IgnoreMapsAndSets bool `json:"ignoreMapsAndSets"`
150
+ }
151
+
152
+ type functionalParametersOptions struct {
153
+ functionalPatternOptions
154
+ AllowRestParameter bool `json:"allowRestParameter"`
155
+ AllowArgumentsKeyword bool `json:"allowArgumentsKeyword"`
156
+ EnforceParameterCount interface{} `json:"enforceParameterCount"`
157
+ }
158
+
159
+ type functionalPreferImmutableTypesOptions struct {
160
+ functionalPatternOptions
161
+ }
162
+
163
+ type functionalPreferReadonlyTypeOptions struct {
164
+ functionalPatternOptions
165
+ }
166
+
167
+ type functionalReadonlyTypeOptions struct {
168
+ Prefer string `json:"prefer"`
169
+ }
170
+
171
+ type functionalPatternOptions struct {
172
+ IgnoreIdentifierPattern interface{} `json:"ignoreIdentifierPattern"`
173
+ IgnoreCodePattern interface{} `json:"ignoreCodePattern"`
174
+ }
175
+
176
+ type functionalImmutabilityDeclarationOptions struct {
177
+ functionalPatternOptions
178
+ Rules []functionalImmutabilityRule `json:"rules"`
179
+ IgnoreInterfaces bool `json:"ignoreInterfaces"`
180
+ }
181
+
182
+ type functionalImmutabilityRule struct {
183
+ Identifiers interface{} `json:"identifiers"`
184
+ }
185
+
186
+ func (functionalParameters) Check(ctx *Context, node *shimast.Node) {
187
+ var opts functionalParametersOptions
188
+ _ = ctx.DecodeOptions(&opts)
189
+ switch node.Kind {
190
+ case shimast.KindParameter:
191
+ param := node.AsParameterDeclaration()
192
+ if param != nil && param.DotDotDotToken != nil && !opts.AllowRestParameter {
193
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, node, identifierText(param.Name())) {
194
+ return
195
+ }
196
+ ctx.Report(node, "Unexpected rest parameter. Use a regular parameter of array type instead.")
197
+ }
198
+ case shimast.KindIdentifier:
199
+ if opts.AllowArgumentsKeyword || identifierText(node) != "arguments" || isDeclarationName(node) {
200
+ return
201
+ }
202
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, node, "arguments") {
203
+ return
204
+ }
205
+ ctx.Report(node, "Unexpected use of `arguments`. Use regular function arguments instead.")
206
+ default:
207
+ if opts.EnforceParameterCount == nil || opts.EnforceParameterCount == false {
208
+ return
209
+ }
210
+ if len(node.Parameters()) == 0 {
211
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, node, functionalFunctionLikeName(node)) {
212
+ return
213
+ }
214
+ ctx.Report(node, "Functions must have at least one parameter.")
215
+ }
216
+ }
217
+ }
218
+
219
+ func (functionalImmutableData) Check(ctx *Context, node *shimast.Node) {
220
+ var opts functionalImmutableDataOptions
221
+ _ = ctx.DecodeOptions(&opts)
222
+ switch node.Kind {
223
+ case shimast.KindBinaryExpression:
224
+ expr := node.AsBinaryExpression()
225
+ if expr == nil || expr.OperatorToken == nil || !isAssignmentOperator(expr.OperatorToken.Kind) {
226
+ return
227
+ }
228
+ if isMemberMutationTarget(expr.Left) {
229
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, expr.Left, functionalIdentifierTexts(expr.Left)...) {
230
+ return
231
+ }
232
+ ctx.Report(expr.Left, "Modifying an existing object/array is not allowed.")
233
+ }
234
+ case shimast.KindPrefixUnaryExpression:
235
+ expr := node.AsPrefixUnaryExpression()
236
+ if expr != nil && isUpdateOperator(expr.Operator) && isMemberMutationTarget(expr.Operand) {
237
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, expr.Operand, functionalIdentifierTexts(expr.Operand)...) {
238
+ return
239
+ }
240
+ ctx.Report(expr.Operand, "Modifying an existing object/array is not allowed.")
241
+ }
242
+ case shimast.KindPostfixUnaryExpression:
243
+ expr := node.AsPostfixUnaryExpression()
244
+ if expr != nil && isUpdateOperator(expr.Operator) && isMemberMutationTarget(expr.Operand) {
245
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, expr.Operand, functionalIdentifierTexts(expr.Operand)...) {
246
+ return
247
+ }
248
+ ctx.Report(expr.Operand, "Modifying an existing object/array is not allowed.")
249
+ }
250
+ case shimast.KindDeleteExpression:
251
+ expr := node.AsDeleteExpression()
252
+ if expr != nil && isMemberMutationTarget(expr.Expression) {
253
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, expr.Expression, functionalIdentifierTexts(expr.Expression)...) {
254
+ return
255
+ }
256
+ ctx.Report(expr.Expression, "Modifying an existing object/array is not allowed.")
257
+ }
258
+ case shimast.KindCallExpression:
259
+ call := node.AsCallExpression()
260
+ if call == nil || call.Expression == nil || call.Expression.Kind != shimast.KindPropertyAccessExpression {
261
+ return
262
+ }
263
+ access := call.Expression.AsPropertyAccessExpression()
264
+ if access == nil {
265
+ return
266
+ }
267
+ method := identifierText(access.Name())
268
+ if isMutableArrayMethod(method) || (!opts.IgnoreMapsAndSets && isMutableCollectionMethod(method)) {
269
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, call.Expression, functionalIdentifierTexts(call.Expression)...) {
270
+ return
271
+ }
272
+ ctx.Report(call.Expression, "Modifying an existing object/array is not allowed.")
273
+ }
274
+ }
275
+ }
276
+
277
+ func (functionalNoClassInheritance) Check(ctx *Context, node *shimast.Node) {
278
+ if hasModifier(node, shimast.KindAbstractKeyword) {
279
+ ctx.Report(node, "Unexpected abstract class.")
280
+ return
281
+ }
282
+ if classHasHeritage(node) {
283
+ ctx.Report(node, "Unexpected inheritance, use composition instead.")
284
+ }
285
+ }
286
+
287
+ func (functionalNoClasses) Check(ctx *Context, node *shimast.Node) {
288
+ ctx.Report(node, "Unexpected class, use functions not classes.")
289
+ }
290
+
291
+ func (functionalNoConditionalStatements) Check(ctx *Context, node *shimast.Node) {
292
+ switch node.Kind {
293
+ case shimast.KindIfStatement:
294
+ ctx.Report(node, "Unexpected if, use a conditional expression instead.")
295
+ case shimast.KindSwitchStatement:
296
+ ctx.Report(node, "Unexpected switch, use a conditional expression instead.")
297
+ }
298
+ }
299
+
300
+ func (functionalNoExpressionStatements) Check(ctx *Context, node *shimast.Node) {
301
+ text := strings.TrimSpace(nodeText(ctx.File, node))
302
+ if strings.HasPrefix(text, `"use `) || strings.HasPrefix(text, `'use `) {
303
+ return
304
+ }
305
+ ctx.Report(node, "Using expressions to cause side effects is not allowed.")
306
+ }
307
+
308
+ func (functionalNoLet) Check(ctx *Context, node *shimast.Node) {
309
+ if !shimast.IsLet(node) {
310
+ return
311
+ }
312
+ var opts functionalNoLetOptions
313
+ _ = ctx.DecodeOptions(&opts)
314
+ if opts.AllowInForLoopInit && node.Parent != nil && node.Parent.Kind == shimast.KindForStatement {
315
+ return
316
+ }
317
+ if opts.AllowInFunctions && hasAncestor(node, isFunctionLikeKind) {
318
+ return
319
+ }
320
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, node, functionalVariableDeclarationListNames(node)...) {
321
+ return
322
+ }
323
+ start := keywordStart(ctx.File, node, "let")
324
+ if start >= 0 {
325
+ ctx.ReportRange(start, start+len("let"), "Unexpected let, use const instead.")
326
+ return
327
+ }
328
+ ctx.Report(node, "Unexpected let, use const instead.")
329
+ }
330
+
331
+ func (functionalNoLoopStatements) Check(ctx *Context, node *shimast.Node) {
332
+ ctx.Report(node, "Unexpected loop, use map or reduce instead.")
333
+ }
334
+
335
+ func (functionalNoMixedTypes) Check(ctx *Context, node *shimast.Node) {
336
+ members := containerMembers(node)
337
+ if len(members) < 2 {
338
+ return
339
+ }
340
+ first := ""
341
+ for _, member := range members {
342
+ kind := functionalMemberKind(member)
343
+ if kind == "" {
344
+ continue
345
+ }
346
+ if first == "" {
347
+ first = kind
348
+ continue
349
+ }
350
+ if first != kind {
351
+ ctx.Report(member, "Only the same kind of members are allowed in types.")
352
+ return
353
+ }
354
+ }
355
+ }
356
+
357
+ func (functionalNoPromiseReject) Check(ctx *Context, node *shimast.Node) {
358
+ call := node.AsCallExpression()
359
+ if call != nil && isMatchingPropertyAccess(call.Expression, "Promise", "reject") {
360
+ ctx.Report(node, "Unexpected rejection, resolve an error instead.")
361
+ }
362
+ }
363
+
364
+ func (functionalNoReturnVoid) Check(ctx *Context, node *shimast.Node) {
365
+ if node.Kind == shimast.KindReturnStatement {
366
+ ret := node.AsReturnStatement()
367
+ if ret != nil && ret.Expression == nil {
368
+ ctx.Report(node, "Function must return a value.")
369
+ }
370
+ return
371
+ }
372
+ if functionalReturnTypeText(ctx, node) == "void" {
373
+ ctx.Report(node, "Function must return a value.")
374
+ }
375
+ }
376
+
377
+ func (functionalNoThisExpressions) Check(ctx *Context, node *shimast.Node) {
378
+ ctx.Report(node, "Unexpected this, use functions not classes.")
379
+ }
380
+
381
+ func (functionalNoThrowStatements) Check(ctx *Context, node *shimast.Node) {
382
+ ctx.Report(node, "Unexpected throw, throwing exceptions is not functional.")
383
+ }
384
+
385
+ func (functionalNoTryStatements) Check(ctx *Context, node *shimast.Node) {
386
+ var opts functionalNoTryOptions
387
+ _ = ctx.DecodeOptions(&opts)
388
+ try := node.AsTryStatement()
389
+ if try == nil {
390
+ return
391
+ }
392
+ if try.CatchClause != nil && !opts.AllowCatch {
393
+ ctx.Report(node, "Unexpected try-catch, this pattern is not functional.")
394
+ return
395
+ }
396
+ if try.FinallyBlock != nil && !opts.AllowFinally {
397
+ ctx.Report(node, "Unexpected try-finally, this pattern is not functional.")
398
+ }
399
+ }
400
+
401
+ func (functionalPreferImmutableTypes) Check(ctx *Context, node *shimast.Node) {
402
+ var opts functionalPreferImmutableTypesOptions
403
+ _ = ctx.DecodeOptions(&opts)
404
+ typeNode := declarationTypeNode(node)
405
+ if typeNode == nil || !functionalMutableType(typeNode) {
406
+ return
407
+ }
408
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, node, functionalDeclarationName(node)) ||
409
+ functionalShouldIgnore(ctx, opts.functionalPatternOptions, typeNode) {
410
+ return
411
+ }
412
+ ctx.Report(typeNode, "Type should be readonly or immutable.")
413
+ }
414
+
415
+ func (functionalPreferPropertySignatures) Check(ctx *Context, node *shimast.Node) {
416
+ ctx.Report(node, "Use a property signature instead of a method signature.")
417
+ }
418
+
419
+ func (functionalPreferReadonlyType) Check(ctx *Context, node *shimast.Node) {
420
+ var opts functionalPreferReadonlyTypeOptions
421
+ _ = ctx.DecodeOptions(&opts)
422
+ switch node.Kind {
423
+ case shimast.KindArrayType:
424
+ if !isReadonlyTypeNode(node) {
425
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, node) {
426
+ return
427
+ }
428
+ ctx.Report(node, "Only readonly arrays allowed.")
429
+ }
430
+ case shimast.KindTupleType:
431
+ if !isReadonlyTypeNode(node) {
432
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, node) {
433
+ return
434
+ }
435
+ ctx.Report(node, "Only readonly tuples allowed.")
436
+ }
437
+ case shimast.KindTypeReference:
438
+ if isMutableTypeReference(node) {
439
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, node, functionalIdentifierTexts(node)...) {
440
+ return
441
+ }
442
+ ctx.Report(node, "Only readonly types allowed.")
443
+ }
444
+ case shimast.KindPropertySignature:
445
+ if !hasModifier(node, shimast.KindReadonlyKeyword) {
446
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, node, functionalDeclarationName(node)) {
447
+ return
448
+ }
449
+ ctx.Report(node, "A readonly modifier is required.")
450
+ }
451
+ }
452
+ }
453
+
454
+ func (functionalPreferTacit) Check(ctx *Context, node *shimast.Node) {
455
+ text := compactFunctionalWhitespace(nodeText(ctx.File, node))
456
+ if isTacitWrapperText(text) {
457
+ ctx.Report(node, "Potentially unnecessary function wrapper.")
458
+ }
459
+ }
460
+
461
+ func (functionalReadonlyType) Check(ctx *Context, node *shimast.Node) {
462
+ var opts functionalReadonlyTypeOptions
463
+ _ = ctx.DecodeOptions(&opts)
464
+ prefer := opts.Prefer
465
+ if prefer == "" {
466
+ prefer = "keyword"
467
+ }
468
+ switch node.Kind {
469
+ case shimast.KindTypeReference:
470
+ if prefer == "keyword" && identifierText(node.AsTypeReferenceNode().TypeName) == "ReadonlyArray" {
471
+ ctx.Report(node, "Use the readonly keyword instead of ReadonlyArray<T>.")
472
+ }
473
+ case shimast.KindTypeOperator:
474
+ if prefer == "generic" && strings.HasPrefix(strings.TrimSpace(nodeText(ctx.File, node)), "readonly ") {
475
+ ctx.Report(node, "Use Readonly<T> instead of the readonly keyword.")
476
+ }
477
+ }
478
+ }
479
+
480
+ func (functionalTypeDeclarationImmutability) Check(ctx *Context, node *shimast.Node) {
481
+ var opts functionalImmutabilityDeclarationOptions
482
+ _ = ctx.DecodeOptions(&opts)
483
+ if opts.IgnoreInterfaces && node.Kind == shimast.KindInterfaceDeclaration {
484
+ return
485
+ }
486
+ name := functionalTypeDeclarationName(node)
487
+ if functionalShouldIgnore(ctx, opts.functionalPatternOptions, node, name) {
488
+ return
489
+ }
490
+ if !functionalDeclarationRuleApplies(opts, name) {
491
+ return
492
+ }
493
+ if functionalDeclarationIsMutable(node) {
494
+ ctx.Report(node, "Type declaration should only expose readonly members and immutable property types.")
495
+ }
496
+ }
497
+
498
+ func isMemberMutationTarget(node *shimast.Node) bool {
499
+ if node == nil {
500
+ return false
501
+ }
502
+ node = stripParens(node)
503
+ return node != nil && (node.Kind == shimast.KindPropertyAccessExpression || node.Kind == shimast.KindElementAccessExpression)
504
+ }
505
+
506
+ func functionalShouldIgnore(ctx *Context, opts functionalPatternOptions, node *shimast.Node, identifiers ...string) bool {
507
+ if functionalPatternOptionMatches(opts.IgnoreCodePattern, strings.TrimSpace(nodeText(ctx.File, node))) {
508
+ return true
509
+ }
510
+ for _, name := range identifiers {
511
+ if functionalPatternOptionMatches(opts.IgnoreIdentifierPattern, name) {
512
+ return true
513
+ }
514
+ }
515
+ return false
516
+ }
517
+
518
+ func isUpdateOperator(kind shimast.Kind) bool {
519
+ return kind == shimast.KindPlusPlusToken || kind == shimast.KindMinusMinusToken
520
+ }
521
+
522
+ func isMutableArrayMethod(name string) bool {
523
+ switch name {
524
+ case "copyWithin", "fill", "pop", "push", "reverse", "shift", "sort", "splice", "unshift":
525
+ return true
526
+ default:
527
+ return false
528
+ }
529
+ }
530
+
531
+ func isMutableCollectionMethod(name string) bool {
532
+ switch name {
533
+ case "add", "clear", "delete", "set":
534
+ return true
535
+ default:
536
+ return false
537
+ }
538
+ }
539
+
540
+ func classHasHeritage(node *shimast.Node) bool {
541
+ switch node.Kind {
542
+ case shimast.KindClassDeclaration:
543
+ decl := node.AsClassDeclaration()
544
+ return decl != nil && decl.HeritageClauses != nil && len(decl.HeritageClauses.Nodes) > 0
545
+ case shimast.KindClassExpression:
546
+ decl := node.AsClassExpression()
547
+ return decl != nil && decl.HeritageClauses != nil && len(decl.HeritageClauses.Nodes) > 0
548
+ default:
549
+ return false
550
+ }
551
+ }
552
+
553
+ func hasAncestor(node *shimast.Node, pred func(*shimast.Node) bool) bool {
554
+ for cur := node.Parent; cur != nil; cur = cur.Parent {
555
+ if pred(cur) {
556
+ return true
557
+ }
558
+ }
559
+ return false
560
+ }
561
+
562
+ func functionalMemberKind(node *shimast.Node) string {
563
+ if node == nil {
564
+ return ""
565
+ }
566
+ switch node.Kind {
567
+ case shimast.KindPropertySignature, shimast.KindPropertyDeclaration:
568
+ return "property"
569
+ case shimast.KindMethodSignature, shimast.KindMethodDeclaration:
570
+ return "method"
571
+ case shimast.KindCallSignature:
572
+ return "call"
573
+ case shimast.KindIndexSignature:
574
+ return "index"
575
+ default:
576
+ return ""
577
+ }
578
+ }
579
+
580
+ func isDeclarationName(node *shimast.Node) bool {
581
+ if node == nil || node.Parent == nil {
582
+ return false
583
+ }
584
+ parent := node.Parent
585
+ switch parent.Kind {
586
+ case shimast.KindVariableDeclaration:
587
+ decl := parent.AsVariableDeclaration()
588
+ return decl != nil && decl.Name() == node
589
+ case shimast.KindParameter:
590
+ decl := parent.AsParameterDeclaration()
591
+ return decl != nil && decl.Name() == node
592
+ case shimast.KindFunctionDeclaration, shimast.KindClassDeclaration, shimast.KindInterfaceDeclaration, shimast.KindTypeAliasDeclaration:
593
+ return true
594
+ default:
595
+ return false
596
+ }
597
+ }
598
+
599
+ func functionalReturnTypeText(ctx *Context, node *shimast.Node) string {
600
+ var typeNode *shimast.Node
601
+ switch node.Kind {
602
+ case shimast.KindFunctionDeclaration:
603
+ if decl := node.AsFunctionDeclaration(); decl != nil {
604
+ typeNode = decl.Type
605
+ }
606
+ case shimast.KindFunctionExpression:
607
+ if decl := node.AsFunctionExpression(); decl != nil {
608
+ typeNode = decl.Type
609
+ }
610
+ case shimast.KindArrowFunction:
611
+ if decl := node.AsArrowFunction(); decl != nil {
612
+ typeNode = decl.Type
613
+ }
614
+ case shimast.KindMethodDeclaration:
615
+ if decl := node.AsMethodDeclaration(); decl != nil {
616
+ typeNode = decl.Type
617
+ }
618
+ }
619
+ return strings.TrimSpace(nodeText(ctx.File, typeNode))
620
+ }
621
+
622
+ func functionalFunctionLikeName(node *shimast.Node) string {
623
+ if node == nil {
624
+ return ""
625
+ }
626
+ switch node.Kind {
627
+ case shimast.KindFunctionDeclaration:
628
+ if decl := node.AsFunctionDeclaration(); decl != nil {
629
+ return identifierText(decl.Name())
630
+ }
631
+ case shimast.KindMethodDeclaration:
632
+ if decl := node.AsMethodDeclaration(); decl != nil {
633
+ return identifierText(decl.Name())
634
+ }
635
+ }
636
+ return ""
637
+ }
638
+
639
+ func declarationTypeNode(node *shimast.Node) *shimast.Node {
640
+ if node == nil {
641
+ return nil
642
+ }
643
+ switch node.Kind {
644
+ case shimast.KindVariableDeclaration:
645
+ if decl := node.AsVariableDeclaration(); decl != nil {
646
+ return decl.Type
647
+ }
648
+ case shimast.KindParameter:
649
+ if decl := node.AsParameterDeclaration(); decl != nil {
650
+ return decl.Type
651
+ }
652
+ case shimast.KindPropertyDeclaration:
653
+ if decl := node.AsPropertyDeclaration(); decl != nil {
654
+ return decl.Type
655
+ }
656
+ case shimast.KindPropertySignature:
657
+ if decl := node.AsPropertySignatureDeclaration(); decl != nil {
658
+ return decl.Type
659
+ }
660
+ }
661
+ return nil
662
+ }
663
+
664
+ func functionalDeclarationName(node *shimast.Node) string {
665
+ if node == nil {
666
+ return ""
667
+ }
668
+ switch node.Kind {
669
+ case shimast.KindVariableDeclaration:
670
+ if decl := node.AsVariableDeclaration(); decl != nil {
671
+ return identifierText(decl.Name())
672
+ }
673
+ case shimast.KindParameter:
674
+ if decl := node.AsParameterDeclaration(); decl != nil {
675
+ return identifierText(decl.Name())
676
+ }
677
+ case shimast.KindPropertyDeclaration:
678
+ if decl := node.AsPropertyDeclaration(); decl != nil {
679
+ return identifierText(decl.Name())
680
+ }
681
+ case shimast.KindPropertySignature:
682
+ if decl := node.AsPropertySignatureDeclaration(); decl != nil {
683
+ return identifierText(decl.Name())
684
+ }
685
+ case shimast.KindFunctionDeclaration:
686
+ if decl := node.AsFunctionDeclaration(); decl != nil {
687
+ return identifierText(decl.Name())
688
+ }
689
+ case shimast.KindMethodDeclaration:
690
+ if decl := node.AsMethodDeclaration(); decl != nil {
691
+ return identifierText(decl.Name())
692
+ }
693
+ }
694
+ return ""
695
+ }
696
+
697
+ func functionalVariableDeclarationListNames(node *shimast.Node) []string {
698
+ list := node.AsVariableDeclarationList()
699
+ if list == nil || list.Declarations == nil {
700
+ return nil
701
+ }
702
+ names := make([]string, 0, len(list.Declarations.Nodes))
703
+ for _, child := range list.Declarations.Nodes {
704
+ if name := functionalDeclarationName(child); name != "" {
705
+ names = append(names, name)
706
+ }
707
+ }
708
+ return names
709
+ }
710
+
711
+ func functionalIdentifierTexts(node *shimast.Node) []string {
712
+ var names []string
713
+ walkDescendants(node, func(child *shimast.Node) {
714
+ if name := identifierText(child); name != "" {
715
+ names = append(names, name)
716
+ }
717
+ })
718
+ return names
719
+ }
720
+
721
+ func functionalMutableType(node *shimast.Node) bool {
722
+ if node == nil || isReadonlyTypeNode(node) {
723
+ return false
724
+ }
725
+ switch node.Kind {
726
+ case shimast.KindArrayType, shimast.KindTupleType:
727
+ return true
728
+ case shimast.KindTypeReference:
729
+ return isMutableTypeReference(node)
730
+ case shimast.KindTypeLiteral:
731
+ return functionalTypeLiteralIsMutable(node)
732
+ default:
733
+ found := false
734
+ walkDescendants(node, func(child *shimast.Node) {
735
+ if child != node && functionalMutableType(child) {
736
+ found = true
737
+ }
738
+ })
739
+ return found
740
+ }
741
+ }
742
+
743
+ func isReadonlyTypeNode(node *shimast.Node) bool {
744
+ if node == nil {
745
+ return false
746
+ }
747
+ return node.Kind == shimast.KindTypeOperator ||
748
+ (node.Parent != nil && node.Parent.Kind == shimast.KindTypeOperator &&
749
+ strings.HasPrefix(strings.TrimSpace(nodeText(nilSafeFile(node), node.Parent)), "readonly "))
750
+ }
751
+
752
+ func nilSafeFile(node *shimast.Node) *shimast.SourceFile {
753
+ for cur := node; cur != nil; cur = cur.Parent {
754
+ if cur.Kind == shimast.KindSourceFile {
755
+ return cur.AsSourceFile()
756
+ }
757
+ }
758
+ return nil
759
+ }
760
+
761
+ func isMutableTypeReference(node *shimast.Node) bool {
762
+ ref := node.AsTypeReferenceNode()
763
+ if ref == nil || ref.TypeName == nil {
764
+ return false
765
+ }
766
+ switch identifierText(ref.TypeName) {
767
+ case "Array", "Map", "Set", "WeakMap", "WeakSet":
768
+ return true
769
+ default:
770
+ return false
771
+ }
772
+ }
773
+
774
+ func functionalTypeLiteralIsMutable(node *shimast.Node) bool {
775
+ lit := node.AsTypeLiteralNode()
776
+ if lit == nil || lit.Members == nil {
777
+ return false
778
+ }
779
+ for _, member := range lit.Members.Nodes {
780
+ if member == nil {
781
+ continue
782
+ }
783
+ if member.Kind == shimast.KindPropertySignature && !hasModifier(member, shimast.KindReadonlyKeyword) {
784
+ return true
785
+ }
786
+ if functionalMutableType(declarationTypeNode(member)) {
787
+ return true
788
+ }
789
+ }
790
+ return false
791
+ }
792
+
793
+ func compactFunctionalWhitespace(text string) string {
794
+ text = strings.TrimSpace(text)
795
+ text = strings.Join(strings.Fields(text), "")
796
+ return strings.TrimSuffix(text, ";")
797
+ }
798
+
799
+ func isTacitWrapperText(text string) bool {
800
+ parts := strings.Split(text, "=>")
801
+ if len(parts) != 2 {
802
+ return false
803
+ }
804
+ param := tacitWrapperParameterName(strings.Trim(parts[0], "()"))
805
+ if param == "" {
806
+ return false
807
+ }
808
+ call := parts[1]
809
+ if !strings.HasSuffix(call, ")") {
810
+ return false
811
+ }
812
+ open := strings.LastIndex(call, "(")
813
+ if open <= 0 {
814
+ return false
815
+ }
816
+ callee := call[:open]
817
+ arg := strings.TrimSuffix(call[open+1:], ")")
818
+ return arg == param && isFunctionalMemberChain(callee)
819
+ }
820
+
821
+ // tacitWrapperParameterName returns the bare identifier of a single
822
+ // arrow-function parameter, peeling off a `: Type` annotation and an
823
+ // optional `?` so the rule still matches typed wrappers like
824
+ // `(value: number) => transform(value)`. Returns "" when the parameter
825
+ // list is empty, contains a destructured pattern, or has more than one
826
+ // parameter (a multi-arg list is split by `=>` further upstream).
827
+ func tacitWrapperParameterName(param string) string {
828
+ if param == "" {
829
+ return ""
830
+ }
831
+ // Strip default value: `x = 0`. The default would re-evaluate
832
+ // inside the wrapper, so the tacit form would lose it — bail.
833
+ if strings.ContainsRune(param, '=') {
834
+ return ""
835
+ }
836
+ // Strip optional marker and type annotation.
837
+ if i := strings.IndexRune(param, ':'); i >= 0 {
838
+ param = param[:i]
839
+ }
840
+ param = strings.TrimSuffix(param, "?")
841
+ param = strings.TrimSpace(param)
842
+ if !isFunctionalIdentifier(param) {
843
+ return ""
844
+ }
845
+ return param
846
+ }
847
+
848
+ func isFunctionalMemberChain(text string) bool {
849
+ parts := strings.Split(text, ".")
850
+ for _, part := range parts {
851
+ if !isFunctionalIdentifier(part) {
852
+ return false
853
+ }
854
+ }
855
+ return true
856
+ }
857
+
858
+ func isFunctionalIdentifier(text string) bool {
859
+ if text == "" {
860
+ return false
861
+ }
862
+ for i, r := range text {
863
+ if i == 0 {
864
+ if r == '_' || r == '$' || ('A' <= r && r <= 'Z') || ('a' <= r && r <= 'z') {
865
+ continue
866
+ }
867
+ return false
868
+ }
869
+ if r == '_' || r == '$' || ('A' <= r && r <= 'Z') || ('a' <= r && r <= 'z') || ('0' <= r && r <= '9') {
870
+ continue
871
+ }
872
+ return false
873
+ }
874
+ return true
875
+ }
876
+
877
+ func functionalTypeDeclarationName(node *shimast.Node) string {
878
+ switch node.Kind {
879
+ case shimast.KindInterfaceDeclaration:
880
+ if decl := node.AsInterfaceDeclaration(); decl != nil {
881
+ return identifierText(decl.Name())
882
+ }
883
+ case shimast.KindTypeAliasDeclaration:
884
+ if decl := node.AsTypeAliasDeclaration(); decl != nil {
885
+ return identifierText(decl.Name())
886
+ }
887
+ }
888
+ return ""
889
+ }
890
+
891
+ func functionalDeclarationRuleApplies(opts functionalImmutabilityDeclarationOptions, name string) bool {
892
+ if len(opts.Rules) == 0 {
893
+ return true
894
+ }
895
+ for _, rule := range opts.Rules {
896
+ if functionalPatternOptionMatches(rule.Identifiers, name) {
897
+ return true
898
+ }
899
+ }
900
+ return false
901
+ }
902
+
903
+ func functionalPatternOptionMatches(raw interface{}, text string) bool {
904
+ switch value := raw.(type) {
905
+ case string:
906
+ return functionalPatternMatches(value, text)
907
+ case []interface{}:
908
+ for _, item := range value {
909
+ if pattern, ok := item.(string); ok && functionalPatternMatches(pattern, text) {
910
+ return true
911
+ }
912
+ }
913
+ }
914
+ return false
915
+ }
916
+
917
+ func functionalPatternMatches(pattern, name string) bool {
918
+ if pattern == "" || name == "" {
919
+ return false
920
+ }
921
+ if pattern == name {
922
+ return true
923
+ }
924
+ re, err := regexp.Compile(pattern)
925
+ return err == nil && re.MatchString(name)
926
+ }
927
+
928
+ func functionalDeclarationIsMutable(node *shimast.Node) bool {
929
+ switch node.Kind {
930
+ case shimast.KindInterfaceDeclaration:
931
+ for _, member := range containerMembers(node) {
932
+ if member.Kind == shimast.KindPropertySignature && !hasModifier(member, shimast.KindReadonlyKeyword) {
933
+ return true
934
+ }
935
+ if functionalMutableType(declarationTypeNode(member)) {
936
+ return true
937
+ }
938
+ }
939
+ case shimast.KindTypeAliasDeclaration:
940
+ decl := node.AsTypeAliasDeclaration()
941
+ return decl != nil && functionalMutableType(decl.Type)
942
+ }
943
+ return false
944
+ }
945
+
946
+ func init() {
947
+ Register(functionalParameters{})
948
+ Register(functionalImmutableData{})
949
+ Register(functionalNoClassInheritance{})
950
+ Register(functionalNoClasses{})
951
+ Register(functionalNoConditionalStatements{})
952
+ Register(functionalNoExpressionStatements{})
953
+ Register(functionalNoLet{})
954
+ Register(functionalNoLoopStatements{})
955
+ Register(functionalNoMixedTypes{})
956
+ Register(functionalNoPromiseReject{})
957
+ Register(functionalNoReturnVoid{})
958
+ Register(functionalNoThisExpressions{})
959
+ Register(functionalNoThrowStatements{})
960
+ Register(functionalNoTryStatements{})
961
+ Register(functionalPreferImmutableTypes{})
962
+ Register(functionalPreferPropertySignatures{})
963
+ Register(functionalPreferReadonlyType{})
964
+ Register(functionalPreferTacit{})
965
+ Register(functionalReadonlyType{})
966
+ Register(functionalTypeDeclarationImmutability{})
967
+ }