@ttsc/lint 0.14.0-dev.20260529.2 → 0.14.0

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 (380) hide show
  1. package/README.md +21 -23
  2. package/lib/defaultFormat.d.ts +10 -6
  3. package/lib/defaultFormat.js +10 -6
  4. package/lib/defaultFormat.js.map +1 -1
  5. package/lib/structures/ITtscLintConfig.d.ts +5 -5
  6. package/lib/structures/TtscLintRuleSetting.d.ts +19 -19
  7. package/lib/structures/{ITtscLintFormat.d.ts → format/ITtscLintFormat.d.ts} +45 -70
  8. package/lib/structures/format/ITtscLintFormat.js.map +1 -0
  9. package/lib/structures/format/ITtscLintFormatJsDoc.d.ts +15 -0
  10. package/lib/structures/format/ITtscLintFormatJsDoc.js +3 -0
  11. package/lib/structures/format/ITtscLintFormatJsDoc.js.map +1 -0
  12. package/lib/structures/format/ITtscLintFormatSortImports.d.ts +54 -0
  13. package/lib/structures/format/ITtscLintFormatSortImports.js +3 -0
  14. package/lib/structures/format/ITtscLintFormatSortImports.js.map +1 -0
  15. package/lib/structures/format/index.d.ts +3 -0
  16. package/lib/structures/format/index.js +20 -0
  17. package/lib/structures/format/index.js.map +1 -0
  18. package/lib/structures/index.d.ts +1 -1
  19. package/lib/structures/index.js +1 -1
  20. package/lib/structures/index.js.map +1 -1
  21. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +18 -27
  22. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +4 -5
  23. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -1
  24. package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +29 -33
  25. package/lib/structures/rules/ITtscLintContributorRules.d.ts +6 -7
  26. package/lib/structures/rules/ITtscLintCoreRules.d.ts +380 -408
  27. package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +5 -5
  28. package/lib/structures/rules/ITtscLintCypressRuleOptions.js +2 -2
  29. package/lib/structures/rules/ITtscLintCypressRules.d.ts +34 -38
  30. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +21 -24
  31. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +2 -2
  32. package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +51 -56
  33. package/lib/structures/rules/ITtscLintJestRules.d.ts +63 -74
  34. package/lib/structures/rules/ITtscLintJsdocRules.d.ts +47 -54
  35. package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +94 -102
  36. package/lib/structures/rules/ITtscLintNextjsRules.d.ts +50 -55
  37. package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +104 -122
  38. package/lib/structures/rules/ITtscLintPromiseRules.d.ts +62 -71
  39. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +4 -4
  40. package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +17 -19
  41. package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +8 -10
  42. package/lib/structures/rules/ITtscLintReactRuleOptions.js +1 -2
  43. package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -1
  44. package/lib/structures/rules/ITtscLintReactRules.d.ts +91 -104
  45. package/lib/structures/rules/ITtscLintRegexpRules.d.ts +46 -54
  46. package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +7 -8
  47. package/lib/structures/rules/ITtscLintSecurityRules.d.ts +45 -52
  48. package/lib/structures/rules/ITtscLintSolidRules.d.ts +53 -56
  49. package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +3 -4
  50. package/lib/structures/rules/ITtscLintStorybookRules.d.ts +60 -69
  51. package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +31 -37
  52. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +2 -3
  53. package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +102 -119
  54. package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +460 -518
  55. package/lib/structures/rules/ITtscLintVitestRules.d.ts +43 -51
  56. package/linthost/config.go +89 -72
  57. package/linthost/config_format.go +265 -99
  58. package/linthost/directives.go +5 -1
  59. package/linthost/display_width.go +72 -0
  60. package/linthost/fix.go +26 -1
  61. package/linthost/format.go +222 -25
  62. package/linthost/format_editor_settings.go +262 -0
  63. package/linthost/lsp.go +8 -4
  64. package/linthost/print_dispatch.go +3 -0
  65. package/linthost/print_doc.go +13 -0
  66. package/linthost/print_engine.go +68 -11
  67. package/linthost/print_nodes_array.go +108 -5
  68. package/linthost/print_nodes_call.go +515 -74
  69. package/linthost/print_nodes_function.go +25 -0
  70. package/linthost/print_nodes_imports.go +47 -14
  71. package/linthost/print_nodes_list.go +191 -8
  72. package/linthost/print_nodes_object.go +12 -6
  73. package/linthost/print_nodes_ternary.go +106 -0
  74. package/linthost/rules_boundaries.go +400 -400
  75. package/linthost/rules_camelcase.go +81 -81
  76. package/linthost/rules_complexity.go +52 -51
  77. package/linthost/rules_consistent_return.go +81 -81
  78. package/linthost/rules_core_extra.go +472 -472
  79. package/linthost/rules_curly.go +43 -43
  80. package/linthost/rules_default_case.go +15 -15
  81. package/linthost/rules_default_case_last.go +22 -22
  82. package/linthost/rules_format_arrow_parens.go +167 -0
  83. package/linthost/rules_format_bracket_spacing.go +117 -0
  84. package/linthost/rules_format_clause_join.go +172 -0
  85. package/linthost/rules_format_declaration_header.go +664 -0
  86. package/linthost/rules_format_indent.go +616 -0
  87. package/linthost/rules_format_jsdoc.go +4 -4
  88. package/linthost/rules_format_orphan_semi.go +106 -0
  89. package/linthost/rules_format_parameter_properties.go +175 -0
  90. package/linthost/rules_format_print_width.go +185 -69
  91. package/linthost/rules_format_quote_props.go +169 -0
  92. package/linthost/rules_format_quotes.go +75 -29
  93. package/linthost/rules_format_semi.go +185 -10
  94. package/linthost/rules_format_sort_imports.go +456 -121
  95. package/linthost/rules_format_statement_split.go +368 -0
  96. package/linthost/rules_format_ternary_nullish_parens.go +77 -0
  97. package/linthost/rules_format_trailing_comma.go +21 -2
  98. package/linthost/rules_format_whitespace.go +336 -0
  99. package/linthost/rules_functional.go +688 -688
  100. package/linthost/rules_gap.go +146 -11
  101. package/linthost/rules_grouped_accessor_pairs.go +60 -60
  102. package/linthost/rules_guard_for_in.go +122 -122
  103. package/linthost/rules_id_length.go +44 -44
  104. package/linthost/rules_imports.go +11 -3
  105. package/linthost/rules_init_declarations.go +25 -25
  106. package/linthost/rules_jsx_a11y.go +844 -844
  107. package/linthost/rules_max_classes_per_file.go +24 -24
  108. package/linthost/rules_max_depth.go +43 -43
  109. package/linthost/rules_max_lines.go +53 -53
  110. package/linthost/rules_max_lines_per_function.go +28 -28
  111. package/linthost/rules_max_nested_callbacks.go +26 -26
  112. package/linthost/rules_max_params.go +20 -20
  113. package/linthost/rules_max_statements.go +29 -29
  114. package/linthost/rules_nextjs.go +5 -5
  115. package/linthost/rules_no_else_return.go +38 -38
  116. package/linthost/rules_no_empty_named_blocks.go +45 -45
  117. package/linthost/rules_no_import_assign.go +96 -96
  118. package/linthost/rules_no_invalid_this.go +19 -19
  119. package/linthost/rules_no_loop_func.go +43 -43
  120. package/linthost/rules_no_magic_numbers.go +60 -60
  121. package/linthost/rules_no_mixed_operators.go +44 -44
  122. package/linthost/rules_no_param_reassign.go +64 -64
  123. package/linthost/rules_no_restricted_imports.go +45 -45
  124. package/linthost/rules_no_restricted_syntax.go +17 -17
  125. package/linthost/rules_no_shadow.go +112 -112
  126. package/linthost/rules_no_unreachable.go +36 -36
  127. package/linthost/rules_no_useless_assignment.go +79 -79
  128. package/linthost/rules_no_useless_constructor.go +167 -167
  129. package/linthost/rules_no_useless_return.go +28 -28
  130. package/linthost/rules_prefer_arrow_callback.go +74 -74
  131. package/linthost/rules_prefer_destructuring.go +61 -61
  132. package/linthost/rules_prefer_named_capture_group.go +87 -87
  133. package/linthost/rules_prefer_rest_params.go +61 -61
  134. package/linthost/rules_promise.go +800 -800
  135. package/linthost/rules_react.go +600 -600
  136. package/linthost/rules_react_extras.go +162 -162
  137. package/linthost/rules_react_hooks.go +2 -2
  138. package/linthost/rules_react_perf.go +231 -231
  139. package/linthost/rules_regexp.go +293 -293
  140. package/linthost/rules_security.go +613 -613
  141. package/linthost/rules_sort_imports.go +37 -37
  142. package/linthost/rules_sort_keys.go +88 -88
  143. package/linthost/rules_suggestions.go +13 -0
  144. package/linthost/rules_ts.go +2 -2
  145. package/linthost/rules_ts_async.go +247 -247
  146. package/linthost/rules_ts_class_literal_property_style.go +64 -64
  147. package/linthost/rules_ts_consistent_type_exports.go +209 -209
  148. package/linthost/rules_ts_explicit_function_return_type.go +35 -35
  149. package/linthost/rules_ts_extra.go +6 -2
  150. package/linthost/rules_ts_no_base_to_string.go +140 -140
  151. package/linthost/rules_ts_no_confusing_void.go +28 -28
  152. package/linthost/rules_ts_no_deprecated.go +110 -110
  153. package/linthost/rules_ts_no_for_in_array.go +45 -45
  154. package/linthost/rules_ts_no_magic_numbers.go +67 -67
  155. package/linthost/rules_ts_no_meaningless_void_operator.go +44 -44
  156. package/linthost/rules_ts_no_misused_spread.go +64 -64
  157. package/linthost/rules_ts_no_redundant_type_constituents.go +72 -72
  158. package/linthost/rules_ts_no_restricted_types.go +28 -28
  159. package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +87 -87
  160. package/linthost/rules_ts_no_unnecessary_condition.go +184 -184
  161. package/linthost/rules_ts_no_unnecessary_qualifier.go +72 -72
  162. package/linthost/rules_ts_no_unnecessary_template_expression.go +120 -120
  163. package/linthost/rules_ts_no_unnecessary_type_arguments.go +171 -171
  164. package/linthost/rules_ts_no_unnecessary_type_assertion.go +90 -90
  165. package/linthost/rules_ts_no_unsafe_argument.go +50 -50
  166. package/linthost/rules_ts_no_unsafe_assignment.go +60 -60
  167. package/linthost/rules_ts_no_unsafe_call.go +40 -40
  168. package/linthost/rules_ts_no_unsafe_enum_comparison.go +147 -147
  169. package/linthost/rules_ts_no_unsafe_member_access.go +29 -29
  170. package/linthost/rules_ts_no_unsafe_return.go +64 -64
  171. package/linthost/rules_ts_no_unsafe_unary_minus.go +42 -42
  172. package/linthost/rules_ts_no_useless_constructor.go +20 -20
  173. package/linthost/rules_ts_non_nullable_type_assertion_style.go +60 -60
  174. package/linthost/rules_ts_parameter_properties.go +10 -10
  175. package/linthost/rules_ts_prefer_find.go +116 -116
  176. package/linthost/rules_ts_prefer_includes.go +173 -173
  177. package/linthost/rules_ts_prefer_nullish_coalescing.go +54 -54
  178. package/linthost/rules_ts_prefer_optional_chain.go +156 -156
  179. package/linthost/rules_ts_prefer_promise_reject_errors.go +104 -104
  180. package/linthost/rules_ts_prefer_readonly.go +31 -31
  181. package/linthost/rules_ts_prefer_reduce_type_parameter.go +74 -74
  182. package/linthost/rules_ts_prefer_regexp_exec.go +69 -69
  183. package/linthost/rules_ts_prefer_return_this_type.go +79 -79
  184. package/linthost/rules_ts_prefer_string_starts_ends_with.go +237 -237
  185. package/linthost/rules_ts_promise_function_async.go +41 -41
  186. package/linthost/rules_ts_related_getter_setter_pairs.go +61 -61
  187. package/linthost/rules_ts_require_array_sort_compare.go +58 -58
  188. package/linthost/rules_ts_restrict_plus_operands.go +82 -82
  189. package/linthost/rules_ts_restrict_template_expressions.go +50 -50
  190. package/linthost/rules_ts_simple.go +249 -249
  191. package/linthost/rules_ts_sort_type_constituents.go +88 -88
  192. package/linthost/rules_ts_strict_boolean_expressions.go +103 -103
  193. package/linthost/rules_ts_switch_exhaustiveness_check.go +90 -90
  194. package/linthost/rules_ts_unbound_method.go +65 -65
  195. package/linthost/rules_tsdoc.go +88 -88
  196. package/linthost/rules_unicorn_better_regex.go +1 -1
  197. package/linthost/rules_unicorn_catch_error_name.go +19 -19
  198. package/linthost/rules_unicorn_consistent_assert.go +20 -20
  199. package/linthost/rules_unicorn_consistent_date_clone.go +27 -27
  200. package/linthost/rules_unicorn_consistent_destructuring.go +3 -3
  201. package/linthost/rules_unicorn_consistent_empty_array_spread.go +34 -34
  202. package/linthost/rules_unicorn_consistent_existence_index_check.go +42 -42
  203. package/linthost/rules_unicorn_consistent_function_scoping.go +3 -3
  204. package/linthost/rules_unicorn_consistent_template_literal_escape.go +3 -3
  205. package/linthost/rules_unicorn_custom_error_definition.go +92 -92
  206. package/linthost/rules_unicorn_empty_brace_spaces.go +47 -47
  207. package/linthost/rules_unicorn_error_message.go +34 -34
  208. package/linthost/rules_unicorn_escape_case.go +14 -14
  209. package/linthost/rules_unicorn_expiring_todo_comments.go +36 -36
  210. package/linthost/rules_unicorn_explicit_length_check.go +51 -51
  211. package/linthost/rules_unicorn_filename_case.go +1 -1
  212. package/linthost/rules_unicorn_import_style.go +1 -1
  213. package/linthost/rules_unicorn_isolated_functions.go +2 -2
  214. package/linthost/rules_unicorn_new_for_builtins.go +49 -49
  215. package/linthost/rules_unicorn_no_abusive_eslint_disable.go +31 -31
  216. package/linthost/rules_unicorn_no_accessor_recursion.go +69 -69
  217. package/linthost/rules_unicorn_no_anonymous_default_export.go +40 -40
  218. package/linthost/rules_unicorn_no_array_callback_reference.go +33 -33
  219. package/linthost/rules_unicorn_no_array_for_each.go +14 -14
  220. package/linthost/rules_unicorn_no_array_method_this_argument.go +29 -29
  221. package/linthost/rules_unicorn_no_array_reduce.go +15 -15
  222. package/linthost/rules_unicorn_no_array_reverse.go +17 -17
  223. package/linthost/rules_unicorn_no_array_sort.go +17 -17
  224. package/linthost/rules_unicorn_no_await_expression_member.go +12 -12
  225. package/linthost/rules_unicorn_no_await_in_promise_methods.go +38 -38
  226. package/linthost/rules_unicorn_no_console_spaces.go +30 -30
  227. package/linthost/rules_unicorn_no_document_cookie.go +13 -13
  228. package/linthost/rules_unicorn_no_empty_file.go +16 -16
  229. package/linthost/rules_unicorn_no_for_loop.go +58 -58
  230. package/linthost/rules_unicorn_no_hex_escape.go +11 -11
  231. package/linthost/rules_unicorn_no_immediate_mutation.go +55 -55
  232. package/linthost/rules_unicorn_no_instanceof_builtins.go +34 -34
  233. package/linthost/rules_unicorn_no_invalid_fetch_options.go +52 -52
  234. package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +25 -25
  235. package/linthost/rules_unicorn_no_keyword_prefix.go +56 -56
  236. package/linthost/rules_unicorn_no_lonely_if.go +21 -21
  237. package/linthost/rules_unicorn_no_magic_array_flat_depth.go +22 -22
  238. package/linthost/rules_unicorn_no_named_default.go +25 -25
  239. package/linthost/rules_unicorn_no_negated_condition.go +54 -54
  240. package/linthost/rules_unicorn_no_negation_in_equality_check.go +23 -23
  241. package/linthost/rules_unicorn_no_nested_ternary.go +15 -15
  242. package/linthost/rules_unicorn_no_new_array.go +5 -5
  243. package/linthost/rules_unicorn_no_new_buffer.go +5 -5
  244. package/linthost/rules_unicorn_no_null.go +2 -2
  245. package/linthost/rules_unicorn_no_object_as_default_parameter.go +19 -19
  246. package/linthost/rules_unicorn_no_process_exit.go +17 -17
  247. package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +29 -29
  248. package/linthost/rules_unicorn_no_static_only_class.go +27 -27
  249. package/linthost/rules_unicorn_no_thenable.go +47 -47
  250. package/linthost/rules_unicorn_no_this_assignment.go +10 -10
  251. package/linthost/rules_unicorn_no_typeof_undefined.go +31 -31
  252. package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +23 -23
  253. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +37 -37
  254. package/linthost/rules_unicorn_no_unnecessary_await.go +24 -24
  255. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +22 -22
  256. package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +67 -67
  257. package/linthost/rules_unicorn_no_unreadable_iife.go +22 -22
  258. package/linthost/rules_unicorn_no_useless_collection_argument.go +34 -34
  259. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +18 -18
  260. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +49 -49
  261. package/linthost/rules_unicorn_no_useless_iterator_to_array.go +41 -41
  262. package/linthost/rules_unicorn_no_useless_length_check.go +82 -82
  263. package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +42 -42
  264. package/linthost/rules_unicorn_no_useless_spread.go +38 -38
  265. package/linthost/rules_unicorn_no_useless_switch_case.go +29 -29
  266. package/linthost/rules_unicorn_no_useless_undefined.go +25 -25
  267. package/linthost/rules_unicorn_no_zero_fractions.go +17 -17
  268. package/linthost/rules_unicorn_number_literal_case.go +33 -33
  269. package/linthost/rules_unicorn_numeric_separators_style.go +36 -36
  270. package/linthost/rules_unicorn_prefer_add_event_listener.go +30 -30
  271. package/linthost/rules_unicorn_prefer_array_find.go +27 -27
  272. package/linthost/rules_unicorn_prefer_array_flat.go +25 -25
  273. package/linthost/rules_unicorn_prefer_array_flat_map.go +37 -37
  274. package/linthost/rules_unicorn_prefer_array_index_of.go +108 -108
  275. package/linthost/rules_unicorn_prefer_array_some.go +43 -43
  276. package/linthost/rules_unicorn_prefer_at.go +42 -42
  277. package/linthost/rules_unicorn_prefer_bigint_literals.go +42 -42
  278. package/linthost/rules_unicorn_prefer_blob_reading_methods.go +15 -15
  279. package/linthost/rules_unicorn_prefer_class_fields.go +57 -57
  280. package/linthost/rules_unicorn_prefer_classlist_toggle.go +76 -76
  281. package/linthost/rules_unicorn_prefer_code_point.go +21 -21
  282. package/linthost/rules_unicorn_prefer_date_now.go +47 -47
  283. package/linthost/rules_unicorn_prefer_default_parameters.go +96 -96
  284. package/linthost/rules_unicorn_prefer_dom_node_append.go +14 -14
  285. package/linthost/rules_unicorn_prefer_dom_node_dataset.go +27 -27
  286. package/linthost/rules_unicorn_prefer_dom_node_remove.go +17 -17
  287. package/linthost/rules_unicorn_prefer_dom_node_text_content.go +11 -11
  288. package/linthost/rules_unicorn_prefer_event_target.go +10 -10
  289. package/linthost/rules_unicorn_prefer_export_from.go +99 -99
  290. package/linthost/rules_unicorn_prefer_global_this.go +91 -91
  291. package/linthost/rules_unicorn_prefer_import_meta_properties.go +38 -38
  292. package/linthost/rules_unicorn_prefer_includes.go +108 -108
  293. package/linthost/rules_unicorn_prefer_json_parse_buffer.go +37 -37
  294. package/linthost/rules_unicorn_prefer_keyboard_event_key.go +10 -10
  295. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +20 -20
  296. package/linthost/rules_unicorn_prefer_math_min_max.go +33 -33
  297. package/linthost/rules_unicorn_prefer_math_trunc.go +32 -32
  298. package/linthost/rules_unicorn_prefer_modern_dom_apis.go +18 -18
  299. package/linthost/rules_unicorn_prefer_modern_math_apis.go +38 -38
  300. package/linthost/rules_unicorn_prefer_module.go +22 -22
  301. package/linthost/rules_unicorn_prefer_native_coercion_functions.go +73 -73
  302. package/linthost/rules_unicorn_prefer_negative_index.go +46 -46
  303. package/linthost/rules_unicorn_prefer_node_protocol.go +90 -90
  304. package/linthost/rules_unicorn_prefer_number_properties.go +57 -57
  305. package/linthost/rules_unicorn_prefer_object_from_entries.go +26 -26
  306. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +24 -24
  307. package/linthost/rules_unicorn_prefer_prototype_methods.go +25 -25
  308. package/linthost/rules_unicorn_prefer_query_selector.go +25 -25
  309. package/linthost/rules_unicorn_prefer_reflect_apply.go +10 -10
  310. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +47 -47
  311. package/linthost/rules_unicorn_prefer_response_static_json.go +26 -26
  312. package/linthost/rules_unicorn_prefer_set_has.go +16 -16
  313. package/linthost/rules_unicorn_prefer_set_size.go +22 -22
  314. package/linthost/rules_unicorn_prefer_simple_condition_first.go +3 -3
  315. package/linthost/rules_unicorn_prefer_single_call.go +59 -59
  316. package/linthost/rules_unicorn_prefer_spread.go +24 -24
  317. package/linthost/rules_unicorn_prefer_string_raw.go +12 -12
  318. package/linthost/rules_unicorn_prefer_string_replace_all.go +46 -46
  319. package/linthost/rules_unicorn_prefer_string_slice.go +17 -17
  320. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +104 -104
  321. package/linthost/rules_unicorn_prefer_string_trim_start_end.go +21 -21
  322. package/linthost/rules_unicorn_prefer_structured_clone.go +36 -36
  323. package/linthost/rules_unicorn_prefer_switch.go +65 -65
  324. package/linthost/rules_unicorn_prefer_ternary.go +35 -35
  325. package/linthost/rules_unicorn_prefer_top_level_await.go +34 -34
  326. package/linthost/rules_unicorn_prefer_type_error.go +84 -84
  327. package/linthost/rules_unicorn_prevent_abbreviations.go +68 -68
  328. package/linthost/rules_unicorn_relative_url_style.go +19 -19
  329. package/linthost/rules_unicorn_require_array_join_separator.go +18 -18
  330. package/linthost/rules_unicorn_require_module_attributes.go +25 -25
  331. package/linthost/rules_unicorn_require_module_specifiers.go +28 -28
  332. package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +18 -18
  333. package/linthost/rules_unicorn_require_post_message_target_origin.go +18 -18
  334. package/linthost/rules_unicorn_string_content.go +1 -1
  335. package/linthost/rules_unicorn_switch_case_braces.go +16 -16
  336. package/linthost/rules_unicorn_switch_case_break_position.go +3 -3
  337. package/linthost/rules_unicorn_template_indent.go +1 -1
  338. package/linthost/rules_unicorn_text_encoding_identifier_case.go +36 -36
  339. package/linthost/rules_unicorn_throw_new_error.go +30 -30
  340. package/linthost/rules_var.go +273 -3
  341. package/package.json +3 -3
  342. package/src/defaultFormat.ts +11 -7
  343. package/src/structures/ITtscLintConfig.ts +5 -5
  344. package/src/structures/TtscLintRuleSetting.ts +19 -19
  345. package/src/structures/{ITtscLintFormat.ts → format/ITtscLintFormat.ts} +48 -75
  346. package/src/structures/format/ITtscLintFormatJsDoc.ts +16 -0
  347. package/src/structures/format/ITtscLintFormatSortImports.ts +62 -0
  348. package/src/structures/format/index.ts +3 -0
  349. package/src/structures/index.ts +1 -1
  350. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +20 -31
  351. package/src/structures/rules/ITtscLintBoundariesRules.ts +32 -36
  352. package/src/structures/rules/ITtscLintContributorRules.ts +6 -7
  353. package/src/structures/rules/ITtscLintCoreRules.ts +380 -408
  354. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +5 -5
  355. package/src/structures/rules/ITtscLintCypressRules.ts +34 -38
  356. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +28 -41
  357. package/src/structures/rules/ITtscLintFunctionalRules.ts +51 -56
  358. package/src/structures/rules/ITtscLintJestRules.ts +63 -74
  359. package/src/structures/rules/ITtscLintJsdocRules.ts +47 -54
  360. package/src/structures/rules/ITtscLintJsxA11yRules.ts +94 -102
  361. package/src/structures/rules/ITtscLintNextjsRules.ts +50 -55
  362. package/src/structures/rules/ITtscLintPlaywrightRules.ts +104 -122
  363. package/src/structures/rules/ITtscLintPromiseRules.ts +62 -71
  364. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +4 -4
  365. package/src/structures/rules/ITtscLintReactPerfRules.ts +17 -19
  366. package/src/structures/rules/ITtscLintReactRuleOptions.ts +8 -10
  367. package/src/structures/rules/ITtscLintReactRules.ts +91 -104
  368. package/src/structures/rules/ITtscLintRegexpRules.ts +46 -54
  369. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +7 -8
  370. package/src/structures/rules/ITtscLintSecurityRules.ts +45 -52
  371. package/src/structures/rules/ITtscLintSolidRules.ts +53 -56
  372. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +3 -4
  373. package/src/structures/rules/ITtscLintStorybookRules.ts +60 -69
  374. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +31 -37
  375. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +2 -3
  376. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +102 -119
  377. package/src/structures/rules/ITtscLintTypeScriptRules.ts +460 -518
  378. package/src/structures/rules/ITtscLintVitestRules.ts +43 -51
  379. package/lib/structures/ITtscLintFormat.js.map +0 -1
  380. /package/lib/structures/{ITtscLintFormat.js → format/ITtscLintFormat.js} +0 -0
@@ -1,10 +1,10 @@
1
1
  package linthost
2
2
 
3
3
  import (
4
- "regexp"
5
- "strings"
4
+ "regexp"
5
+ "strings"
6
6
 
7
- shimast "github.com/microsoft/typescript-go/shim/ast"
7
+ shimast "github.com/microsoft/typescript-go/shim/ast"
8
8
  )
9
9
 
10
10
  type functionalParameters struct{}
@@ -44,778 +44,778 @@ func (functionalNoThrowStatements) Name() string { return "functional/no-t
44
44
  func (functionalNoTryStatements) Name() string { return "functional/no-try-statements" }
45
45
  func (functionalPreferImmutableTypes) Name() string { return "functional/prefer-immutable-types" }
46
46
  func (functionalPreferPropertySignatures) Name() string {
47
- return "functional/prefer-property-signatures"
47
+ return "functional/prefer-property-signatures"
48
48
  }
49
49
  func (functionalPreferReadonlyType) Name() string { return "functional/prefer-readonly-type" }
50
50
  func (functionalPreferTacit) Name() string { return "functional/prefer-tacit" }
51
51
  func (functionalReadonlyType) Name() string { return "functional/readonly-type" }
52
52
  func (functionalTypeDeclarationImmutability) Name() string {
53
- return "functional/type-declaration-immutability"
53
+ return "functional/type-declaration-immutability"
54
54
  }
55
55
 
56
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
- }
57
+ return []shimast.Kind{
58
+ shimast.KindParameter,
59
+ shimast.KindIdentifier,
60
+ shimast.KindFunctionDeclaration,
61
+ shimast.KindFunctionExpression,
62
+ shimast.KindArrowFunction,
63
+ shimast.KindMethodDeclaration,
64
+ }
65
65
  }
66
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
- }
67
+ return []shimast.Kind{
68
+ shimast.KindBinaryExpression,
69
+ shimast.KindPrefixUnaryExpression,
70
+ shimast.KindPostfixUnaryExpression,
71
+ shimast.KindDeleteExpression,
72
+ shimast.KindCallExpression,
73
+ }
74
74
  }
75
75
  func (functionalNoClassInheritance) Visits() []shimast.Kind {
76
- return []shimast.Kind{shimast.KindClassDeclaration, shimast.KindClassExpression}
76
+ return []shimast.Kind{shimast.KindClassDeclaration, shimast.KindClassExpression}
77
77
  }
78
78
  func (functionalNoClasses) Visits() []shimast.Kind {
79
- return []shimast.Kind{shimast.KindClassDeclaration, shimast.KindClassExpression}
79
+ return []shimast.Kind{shimast.KindClassDeclaration, shimast.KindClassExpression}
80
80
  }
81
81
  func (functionalNoConditionalStatements) Visits() []shimast.Kind {
82
- return []shimast.Kind{shimast.KindIfStatement, shimast.KindSwitchStatement}
82
+ return []shimast.Kind{shimast.KindIfStatement, shimast.KindSwitchStatement}
83
83
  }
84
84
  func (functionalNoExpressionStatements) Visits() []shimast.Kind {
85
- return []shimast.Kind{shimast.KindExpressionStatement}
85
+ return []shimast.Kind{shimast.KindExpressionStatement}
86
86
  }
87
87
  func (functionalNoLet) Visits() []shimast.Kind {
88
- return []shimast.Kind{shimast.KindVariableDeclarationList}
88
+ return []shimast.Kind{shimast.KindVariableDeclarationList}
89
89
  }
90
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
- }
91
+ return []shimast.Kind{
92
+ shimast.KindForStatement,
93
+ shimast.KindForInStatement,
94
+ shimast.KindForOfStatement,
95
+ shimast.KindWhileStatement,
96
+ shimast.KindDoStatement,
97
+ }
98
98
  }
99
99
  func (functionalNoMixedTypes) Visits() []shimast.Kind {
100
- return []shimast.Kind{shimast.KindInterfaceDeclaration, shimast.KindTypeLiteral}
100
+ return []shimast.Kind{shimast.KindInterfaceDeclaration, shimast.KindTypeLiteral}
101
101
  }
102
102
  func (functionalNoPromiseReject) Visits() []shimast.Kind {
103
- return []shimast.Kind{shimast.KindCallExpression}
103
+ return []shimast.Kind{shimast.KindCallExpression}
104
104
  }
105
105
  func (functionalNoReturnVoid) Visits() []shimast.Kind {
106
- return []shimast.Kind{shimast.KindReturnStatement, shimast.KindFunctionDeclaration, shimast.KindFunctionExpression, shimast.KindArrowFunction, shimast.KindMethodDeclaration}
106
+ return []shimast.Kind{shimast.KindReturnStatement, shimast.KindFunctionDeclaration, shimast.KindFunctionExpression, shimast.KindArrowFunction, shimast.KindMethodDeclaration}
107
107
  }
108
108
  func (functionalNoThisExpressions) Visits() []shimast.Kind {
109
- return []shimast.Kind{shimast.KindThisKeyword}
109
+ return []shimast.Kind{shimast.KindThisKeyword}
110
110
  }
111
111
  func (functionalNoThrowStatements) Visits() []shimast.Kind {
112
- return []shimast.Kind{shimast.KindThrowStatement}
112
+ return []shimast.Kind{shimast.KindThrowStatement}
113
113
  }
114
114
  func (functionalNoTryStatements) Visits() []shimast.Kind {
115
- return []shimast.Kind{shimast.KindTryStatement}
115
+ return []shimast.Kind{shimast.KindTryStatement}
116
116
  }
117
117
  func (functionalPreferImmutableTypes) Visits() []shimast.Kind {
118
- return []shimast.Kind{shimast.KindVariableDeclaration, shimast.KindParameter, shimast.KindPropertyDeclaration, shimast.KindPropertySignature}
118
+ return []shimast.Kind{shimast.KindVariableDeclaration, shimast.KindParameter, shimast.KindPropertyDeclaration, shimast.KindPropertySignature}
119
119
  }
120
120
  func (functionalPreferPropertySignatures) Visits() []shimast.Kind {
121
- return []shimast.Kind{shimast.KindMethodSignature}
121
+ return []shimast.Kind{shimast.KindMethodSignature}
122
122
  }
123
123
  func (functionalPreferReadonlyType) Visits() []shimast.Kind {
124
- return []shimast.Kind{shimast.KindArrayType, shimast.KindTupleType, shimast.KindTypeReference, shimast.KindPropertySignature}
124
+ return []shimast.Kind{shimast.KindArrayType, shimast.KindTupleType, shimast.KindTypeReference, shimast.KindPropertySignature}
125
125
  }
126
126
  func (functionalPreferTacit) Visits() []shimast.Kind {
127
- return []shimast.Kind{shimast.KindArrowFunction}
127
+ return []shimast.Kind{shimast.KindArrowFunction}
128
128
  }
129
129
  func (functionalReadonlyType) Visits() []shimast.Kind {
130
- return []shimast.Kind{shimast.KindTypeReference, shimast.KindTypeOperator}
130
+ return []shimast.Kind{shimast.KindTypeReference, shimast.KindTypeOperator}
131
131
  }
132
132
  func (functionalTypeDeclarationImmutability) Visits() []shimast.Kind {
133
- return []shimast.Kind{shimast.KindInterfaceDeclaration, shimast.KindTypeAliasDeclaration}
133
+ return []shimast.Kind{shimast.KindInterfaceDeclaration, shimast.KindTypeAliasDeclaration}
134
134
  }
135
135
 
136
136
  type functionalNoLetOptions struct {
137
- functionalPatternOptions
138
- AllowInForLoopInit bool `json:"allowInForLoopInit"`
139
- AllowInFunctions bool `json:"allowInFunctions"`
137
+ functionalPatternOptions
138
+ AllowInForLoopInit bool `json:"allowInForLoopInit"`
139
+ AllowInFunctions bool `json:"allowInFunctions"`
140
140
  }
141
141
 
142
142
  type functionalNoTryOptions struct {
143
- AllowCatch bool `json:"allowCatch"`
144
- AllowFinally bool `json:"allowFinally"`
143
+ AllowCatch bool `json:"allowCatch"`
144
+ AllowFinally bool `json:"allowFinally"`
145
145
  }
146
146
 
147
147
  type functionalImmutableDataOptions struct {
148
- functionalPatternOptions
149
- IgnoreMapsAndSets bool `json:"ignoreMapsAndSets"`
148
+ functionalPatternOptions
149
+ IgnoreMapsAndSets bool `json:"ignoreMapsAndSets"`
150
150
  }
151
151
 
152
152
  type functionalParametersOptions struct {
153
- functionalPatternOptions
154
- AllowRestParameter bool `json:"allowRestParameter"`
155
- AllowArgumentsKeyword bool `json:"allowArgumentsKeyword"`
156
- EnforceParameterCount interface{} `json:"enforceParameterCount"`
153
+ functionalPatternOptions
154
+ AllowRestParameter bool `json:"allowRestParameter"`
155
+ AllowArgumentsKeyword bool `json:"allowArgumentsKeyword"`
156
+ EnforceParameterCount interface{} `json:"enforceParameterCount"`
157
157
  }
158
158
 
159
159
  type functionalPreferImmutableTypesOptions struct {
160
- functionalPatternOptions
160
+ functionalPatternOptions
161
161
  }
162
162
 
163
163
  type functionalPreferReadonlyTypeOptions struct {
164
- functionalPatternOptions
164
+ functionalPatternOptions
165
165
  }
166
166
 
167
167
  type functionalReadonlyTypeOptions struct {
168
- Prefer string `json:"prefer"`
168
+ Prefer string `json:"prefer"`
169
169
  }
170
170
 
171
171
  type functionalPatternOptions struct {
172
- IgnoreIdentifierPattern interface{} `json:"ignoreIdentifierPattern"`
173
- IgnoreCodePattern interface{} `json:"ignoreCodePattern"`
172
+ IgnoreIdentifierPattern interface{} `json:"ignoreIdentifierPattern"`
173
+ IgnoreCodePattern interface{} `json:"ignoreCodePattern"`
174
174
  }
175
175
 
176
176
  type functionalImmutabilityDeclarationOptions struct {
177
- functionalPatternOptions
178
- Rules []functionalImmutabilityRule `json:"rules"`
179
- IgnoreInterfaces bool `json:"ignoreInterfaces"`
177
+ functionalPatternOptions
178
+ Rules []functionalImmutabilityRule `json:"rules"`
179
+ IgnoreInterfaces bool `json:"ignoreInterfaces"`
180
180
  }
181
181
 
182
182
  type functionalImmutabilityRule struct {
183
- Identifiers interface{} `json:"identifiers"`
183
+ Identifiers interface{} `json:"identifiers"`
184
184
  }
185
185
 
186
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
- }
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
217
  }
218
218
 
219
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
- }
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
275
  }
276
276
 
277
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
- }
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
285
  }
286
286
 
287
287
  func (functionalNoClasses) Check(ctx *Context, node *shimast.Node) {
288
- ctx.Report(node, "Unexpected class, use functions not classes.")
288
+ ctx.Report(node, "Unexpected class, use functions not classes.")
289
289
  }
290
290
 
291
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
- }
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
298
  }
299
299
 
300
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.")
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
306
  }
307
307
 
308
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.")
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
329
  }
330
330
 
331
331
  func (functionalNoLoopStatements) Check(ctx *Context, node *shimast.Node) {
332
- ctx.Report(node, "Unexpected loop, use map or reduce instead.")
332
+ ctx.Report(node, "Unexpected loop, use map or reduce instead.")
333
333
  }
334
334
 
335
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
- }
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
355
  }
356
356
 
357
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
- }
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
362
  }
363
363
 
364
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
- }
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
375
  }
376
376
 
377
377
  func (functionalNoThisExpressions) Check(ctx *Context, node *shimast.Node) {
378
- ctx.Report(node, "Unexpected this, use functions not classes.")
378
+ ctx.Report(node, "Unexpected this, use functions not classes.")
379
379
  }
380
380
 
381
381
  func (functionalNoThrowStatements) Check(ctx *Context, node *shimast.Node) {
382
- ctx.Report(node, "Unexpected throw, throwing exceptions is not functional.")
382
+ ctx.Report(node, "Unexpected throw, throwing exceptions is not functional.")
383
383
  }
384
384
 
385
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
- }
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
399
  }
400
400
 
401
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.")
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
413
  }
414
414
 
415
415
  func (functionalPreferPropertySignatures) Check(ctx *Context, node *shimast.Node) {
416
- ctx.Report(node, "Use a property signature instead of a method signature.")
416
+ ctx.Report(node, "Use a property signature instead of a method signature.")
417
417
  }
418
418
 
419
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
- }
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
452
  }
453
453
 
454
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
- }
455
+ text := compactFunctionalWhitespace(nodeText(ctx.File, node))
456
+ if isTacitWrapperText(text) {
457
+ ctx.Report(node, "Potentially unnecessary function wrapper.")
458
+ }
459
459
  }
460
460
 
461
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
- }
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
478
  }
479
479
 
480
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
- }
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
496
  }
497
497
 
498
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)
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
504
  }
505
505
 
506
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
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
516
  }
517
517
 
518
518
  func isUpdateOperator(kind shimast.Kind) bool {
519
- return kind == shimast.KindPlusPlusToken || kind == shimast.KindMinusMinusToken
519
+ return kind == shimast.KindPlusPlusToken || kind == shimast.KindMinusMinusToken
520
520
  }
521
521
 
522
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
- }
523
+ switch name {
524
+ case "copyWithin", "fill", "pop", "push", "reverse", "shift", "sort", "splice", "unshift":
525
+ return true
526
+ default:
527
+ return false
528
+ }
529
529
  }
530
530
 
531
531
  func isMutableCollectionMethod(name string) bool {
532
- switch name {
533
- case "add", "clear", "delete", "set":
534
- return true
535
- default:
536
- return false
537
- }
532
+ switch name {
533
+ case "add", "clear", "delete", "set":
534
+ return true
535
+ default:
536
+ return false
537
+ }
538
538
  }
539
539
 
540
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
- }
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
551
  }
552
552
 
553
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
554
+ for cur := node.Parent; cur != nil; cur = cur.Parent {
555
+ if pred(cur) {
556
+ return true
557
+ }
558
+ }
559
+ return false
560
560
  }
561
561
 
562
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
- }
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
578
  }
579
579
 
580
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
- }
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
597
  }
598
598
 
599
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))
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
620
  }
621
621
 
622
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 ""
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
637
  }
638
638
 
639
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
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
662
  }
663
663
 
664
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 ""
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
695
  }
696
696
 
697
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
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
709
  }
710
710
 
711
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
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
719
  }
720
720
 
721
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
- }
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
741
  }
742
742
 
743
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 "))
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
750
  }
751
751
 
752
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
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
759
  }
760
760
 
761
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
- }
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
772
  }
773
773
 
774
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
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
791
  }
792
792
 
793
793
  func compactFunctionalWhitespace(text string) string {
794
- text = strings.TrimSpace(text)
795
- text = strings.Join(strings.Fields(text), "")
796
- return strings.TrimSuffix(text, ";")
794
+ text = strings.TrimSpace(text)
795
+ text = strings.Join(strings.Fields(text), "")
796
+ return strings.TrimSuffix(text, ";")
797
797
  }
798
798
 
799
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)
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
819
  }
820
820
 
821
821
  // tacitWrapperParameterName returns the bare identifier of a single
@@ -825,143 +825,143 @@ func isTacitWrapperText(text string) bool {
825
825
  // list is empty, contains a destructured pattern, or has more than one
826
826
  // parameter (a multi-arg list is split by `=>` further upstream).
827
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
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
846
  }
847
847
 
848
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
849
+ parts := strings.Split(text, ".")
850
+ for _, part := range parts {
851
+ if !isFunctionalIdentifier(part) {
852
+ return false
853
+ }
854
+ }
855
+ return true
856
856
  }
857
857
 
858
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
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
875
  }
876
876
 
877
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 ""
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
889
  }
890
890
 
891
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
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
901
  }
902
902
 
903
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
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
915
  }
916
916
 
917
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)
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
926
  }
927
927
 
928
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
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
944
  }
945
945
 
946
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{})
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
967
  }