@ttsc/lint 0.14.0-dev.20260529.2 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/README.md +23 -25
  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 +167 -5
  68. package/linthost/print_nodes_call.go +786 -77
  69. package/linthost/print_nodes_function.go +43 -0
  70. package/linthost/print_nodes_imports.go +64 -14
  71. package/linthost/print_nodes_list.go +214 -8
  72. package/linthost/print_nodes_object.go +14 -6
  73. package/linthost/print_nodes_ternary.go +147 -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 +213 -0
  83. package/linthost/rules_format_bracket_spacing.go +117 -0
  84. package/linthost/rules_format_clause_join.go +179 -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 +180 -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 +517 -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
@@ -21,37 +21,37 @@
21
21
  package linthost
22
22
 
23
23
  import (
24
- shimast "github.com/microsoft/typescript-go/shim/ast"
24
+ shimast "github.com/microsoft/typescript-go/shim/ast"
25
25
  )
26
26
 
27
27
  type preferReadonly struct{}
28
28
 
29
29
  func (preferReadonly) Name() string { return "typescript/prefer-readonly" }
30
30
  func (preferReadonly) Visits() []shimast.Kind {
31
- return []shimast.Kind{shimast.KindPropertyDeclaration}
31
+ return []shimast.Kind{shimast.KindPropertyDeclaration}
32
32
  }
33
33
  func (preferReadonly) Check(ctx *Context, node *shimast.Node) {
34
- // Skip non-class-scoped properties; PropertyDeclaration also appears
35
- // inside object literals in some grammars, but the readonly modifier
36
- // is a class-only concern.
37
- parent := node.Parent
38
- if parent == nil ||
39
- (parent.Kind != shimast.KindClassDeclaration && parent.Kind != shimast.KindClassExpression) {
40
- return
41
- }
42
- if hasModifier(node, shimast.KindReadonlyKeyword) {
43
- return
44
- }
45
- if !preferReadonlyIsPrivate(node) {
46
- return
47
- }
48
- decl := node.AsPropertyDeclaration()
49
- if decl == nil || decl.Initializer == nil {
50
- return
51
- }
52
- // Static fields are still candidates — `private static readonly` is
53
- // the canonical form for class-scoped constants.
54
- ctx.Report(node, "Private field is only initialized at declaration time — mark it `readonly`.")
34
+ // Skip non-class-scoped properties; PropertyDeclaration also appears
35
+ // inside object literals in some grammars, but the readonly modifier
36
+ // is a class-only concern.
37
+ parent := node.Parent
38
+ if parent == nil ||
39
+ (parent.Kind != shimast.KindClassDeclaration && parent.Kind != shimast.KindClassExpression) {
40
+ return
41
+ }
42
+ if hasModifier(node, shimast.KindReadonlyKeyword) {
43
+ return
44
+ }
45
+ if !preferReadonlyIsPrivate(node) {
46
+ return
47
+ }
48
+ decl := node.AsPropertyDeclaration()
49
+ if decl == nil || decl.Initializer == nil {
50
+ return
51
+ }
52
+ // Static fields are still candidates — `private static readonly` is
53
+ // the canonical form for class-scoped constants.
54
+ ctx.Report(node, "Private field is only initialized at declaration time — mark it `readonly`.")
55
55
  }
56
56
 
57
57
  // preferReadonlyIsPrivate reports whether the property is private either
@@ -59,15 +59,15 @@ func (preferReadonly) Check(ctx *Context, node *shimast.Node) {
59
59
  // identifier form. Both make the field inaccessible from outside the
60
60
  // class, so `readonly` is a safe local refinement.
61
61
  func preferReadonlyIsPrivate(node *shimast.Node) bool {
62
- if hasModifier(node, shimast.KindPrivateKeyword) {
63
- return true
64
- }
65
- if name := node.Name(); name != nil && name.Kind == shimast.KindPrivateIdentifier {
66
- return true
67
- }
68
- return false
62
+ if hasModifier(node, shimast.KindPrivateKeyword) {
63
+ return true
64
+ }
65
+ if name := node.Name(); name != nil && name.Kind == shimast.KindPrivateIdentifier {
66
+ return true
67
+ }
68
+ return false
69
69
  }
70
70
 
71
71
  func init() {
72
- Register(preferReadonly{})
72
+ Register(preferReadonly{})
73
73
  }
@@ -15,65 +15,65 @@
15
15
  package linthost
16
16
 
17
17
  import (
18
- shimast "github.com/microsoft/typescript-go/shim/ast"
19
- shimchecker "github.com/microsoft/typescript-go/shim/checker"
18
+ shimast "github.com/microsoft/typescript-go/shim/ast"
19
+ shimchecker "github.com/microsoft/typescript-go/shim/checker"
20
20
  )
21
21
 
22
22
  type preferReduceTypeParameter struct{}
23
23
 
24
24
  func (preferReduceTypeParameter) Name() string {
25
- return "typescript/prefer-reduce-type-parameter"
25
+ return "typescript/prefer-reduce-type-parameter"
26
26
  }
27
27
  func (preferReduceTypeParameter) NeedsTypeChecker() bool {
28
- return true
28
+ return true
29
29
  }
30
30
  func (preferReduceTypeParameter) Visits() []shimast.Kind {
31
- return []shimast.Kind{shimast.KindCallExpression}
31
+ return []shimast.Kind{shimast.KindCallExpression}
32
32
  }
33
33
  func (preferReduceTypeParameter) Check(ctx *Context, node *shimast.Node) {
34
- if ctx.Checker == nil {
35
- return
36
- }
37
- call := node.AsCallExpression()
38
- if call == nil || call.Expression == nil {
39
- return
40
- }
41
- // `arr.reduce<T>(...)` already pins the accumulator at the call
42
- // site — the rule has nothing left to suggest.
43
- if call.TypeArguments != nil && len(call.TypeArguments.Nodes) > 0 {
44
- return
45
- }
46
- // The call must be `<receiver>.reduce(callback, initial)` — the
47
- // two-argument form whose seed is the accumulator. The single-
48
- // argument `arr.reduce(cb)` shape has no seed to assert against.
49
- if call.Arguments == nil || len(call.Arguments.Nodes) != 2 {
50
- return
51
- }
52
- receiver, method, ok := promisePropertyAccessParts(call.Expression)
53
- if !ok || method != "reduce" {
54
- return
55
- }
56
- initial := stripParens(call.Arguments.Nodes[1])
57
- if initial == nil {
58
- return
59
- }
60
- // The initial value must carry an explicit type assertion that the
61
- // rule can hoist into the call's type parameter list. Both the
62
- // canonical `init as T` form and the legacy `<T>init` form qualify.
63
- if initial.Kind != shimast.KindAsExpression && initial.Kind != shimast.KindTypeAssertionExpression {
64
- return
65
- }
66
- if receiver == nil {
67
- return
68
- }
69
- t := ctx.Checker.GetTypeAtLocation(receiver)
70
- if t == nil {
71
- return
72
- }
73
- if !preferReduceIsArrayOrTuple(ctx.Checker, t) {
74
- return
75
- }
76
- ctx.Report(initial, preferReduceMessage)
34
+ if ctx.Checker == nil {
35
+ return
36
+ }
37
+ call := node.AsCallExpression()
38
+ if call == nil || call.Expression == nil {
39
+ return
40
+ }
41
+ // `arr.reduce<T>(...)` already pins the accumulator at the call
42
+ // site — the rule has nothing left to suggest.
43
+ if call.TypeArguments != nil && len(call.TypeArguments.Nodes) > 0 {
44
+ return
45
+ }
46
+ // The call must be `<receiver>.reduce(callback, initial)` — the
47
+ // two-argument form whose seed is the accumulator. The single-
48
+ // argument `arr.reduce(cb)` shape has no seed to assert against.
49
+ if call.Arguments == nil || len(call.Arguments.Nodes) != 2 {
50
+ return
51
+ }
52
+ receiver, method, ok := promisePropertyAccessParts(call.Expression)
53
+ if !ok || method != "reduce" {
54
+ return
55
+ }
56
+ initial := stripParens(call.Arguments.Nodes[1])
57
+ if initial == nil {
58
+ return
59
+ }
60
+ // The initial value must carry an explicit type assertion that the
61
+ // rule can hoist into the call's type parameter list. Both the
62
+ // canonical `init as T` form and the legacy `<T>init` form qualify.
63
+ if initial.Kind != shimast.KindAsExpression && initial.Kind != shimast.KindTypeAssertionExpression {
64
+ return
65
+ }
66
+ if receiver == nil {
67
+ return
68
+ }
69
+ t := ctx.Checker.GetTypeAtLocation(receiver)
70
+ if t == nil {
71
+ return
72
+ }
73
+ if !preferReduceIsArrayOrTuple(ctx.Checker, t) {
74
+ return
75
+ }
76
+ ctx.Report(initial, preferReduceMessage)
77
77
  }
78
78
 
79
79
  const preferReduceMessage = "Pass the accumulator type to `reduce` as a type parameter — `arr.reduce<T>(cb, init)` — instead of asserting on the initial value."
@@ -84,33 +84,33 @@ const preferReduceMessage = "Pass the accumulator type to `reduce` as a type par
84
84
  // intentionally fail closed so the rule does not blow up on generic
85
85
  // helpers whose receiver type leaks downward.
86
86
  func preferReduceIsArrayOrTuple(checker *shimchecker.Checker, t *shimchecker.Type) bool {
87
- if checker == nil || t == nil {
88
- return false
89
- }
90
- flags := t.Flags()
91
- if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
92
- return false
93
- }
94
- if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
95
- for _, part := range t.Types() {
96
- if part == nil {
97
- continue
98
- }
99
- if !preferReduceIsArrayOrTuple(checker, part) {
100
- return false
101
- }
102
- }
103
- return true
104
- }
105
- if shimchecker.Checker_isArrayType(checker, t) {
106
- return true
107
- }
108
- if shimchecker.IsTupleType(t) {
109
- return true
110
- }
111
- return false
87
+ if checker == nil || t == nil {
88
+ return false
89
+ }
90
+ flags := t.Flags()
91
+ if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
92
+ return false
93
+ }
94
+ if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
95
+ for _, part := range t.Types() {
96
+ if part == nil {
97
+ continue
98
+ }
99
+ if !preferReduceIsArrayOrTuple(checker, part) {
100
+ return false
101
+ }
102
+ }
103
+ return true
104
+ }
105
+ if shimchecker.Checker_isArrayType(checker, t) {
106
+ return true
107
+ }
108
+ if shimchecker.IsTupleType(t) {
109
+ return true
110
+ }
111
+ return false
112
112
  }
113
113
 
114
114
  func init() {
115
- Register(preferReduceTypeParameter{})
115
+ Register(preferReduceTypeParameter{})
116
116
  }
@@ -19,53 +19,53 @@
19
19
  package linthost
20
20
 
21
21
  import (
22
- "strings"
22
+ "strings"
23
23
 
24
- shimast "github.com/microsoft/typescript-go/shim/ast"
25
- shimchecker "github.com/microsoft/typescript-go/shim/checker"
24
+ shimast "github.com/microsoft/typescript-go/shim/ast"
25
+ shimchecker "github.com/microsoft/typescript-go/shim/checker"
26
26
  )
27
27
 
28
28
  type preferRegexpExec struct{}
29
29
 
30
30
  func (preferRegexpExec) Name() string { return "typescript/prefer-regexp-exec" }
31
31
  func (preferRegexpExec) NeedsTypeChecker() bool {
32
- return true
32
+ return true
33
33
  }
34
34
  func (preferRegexpExec) Visits() []shimast.Kind {
35
- return []shimast.Kind{shimast.KindCallExpression}
35
+ return []shimast.Kind{shimast.KindCallExpression}
36
36
  }
37
37
  func (preferRegexpExec) Check(ctx *Context, node *shimast.Node) {
38
- if ctx.Checker == nil {
39
- return
40
- }
41
- call := node.AsCallExpression()
42
- if call == nil || call.Expression == nil {
43
- return
44
- }
45
- receiver, method, ok := promisePropertyAccessParts(call.Expression)
46
- if !ok || method != "match" {
47
- return
48
- }
49
- if receiver == nil {
50
- return
51
- }
52
- if call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
53
- return
54
- }
55
- arg := stripParens(call.Arguments.Nodes[0])
56
- if arg == nil || arg.Kind != shimast.KindRegularExpressionLiteral {
57
- return
58
- }
59
- // Skip when the regex literal carries the `g` flag — `String#match`
60
- // returns every match in that mode, which `RegExp#exec` cannot
61
- // replicate in a single call.
62
- if preferRegexpExecHasGlobalFlag(ctx.File, arg) {
63
- return
64
- }
65
- if !preferRegexpExecIsString(ctx.Checker.GetTypeAtLocation(receiver)) {
66
- return
67
- }
68
- ctx.Report(node, preferRegexpExecMessage)
38
+ if ctx.Checker == nil {
39
+ return
40
+ }
41
+ call := node.AsCallExpression()
42
+ if call == nil || call.Expression == nil {
43
+ return
44
+ }
45
+ receiver, method, ok := promisePropertyAccessParts(call.Expression)
46
+ if !ok || method != "match" {
47
+ return
48
+ }
49
+ if receiver == nil {
50
+ return
51
+ }
52
+ if call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
53
+ return
54
+ }
55
+ arg := stripParens(call.Arguments.Nodes[0])
56
+ if arg == nil || arg.Kind != shimast.KindRegularExpressionLiteral {
57
+ return
58
+ }
59
+ // Skip when the regex literal carries the `g` flag — `String#match`
60
+ // returns every match in that mode, which `RegExp#exec` cannot
61
+ // replicate in a single call.
62
+ if preferRegexpExecHasGlobalFlag(ctx.File, arg) {
63
+ return
64
+ }
65
+ if !preferRegexpExecIsString(ctx.Checker.GetTypeAtLocation(receiver)) {
66
+ return
67
+ }
68
+ ctx.Report(node, preferRegexpExecMessage)
69
69
  }
70
70
 
71
71
  const preferRegexpExecMessage = "Prefer `RegExp#exec(str)` over `String#match(re)` when the regex has no `g` flag — `exec` returns the same first-match shape and avoids the `g`-flag fallthrough that silently changes the return type of `match`."
@@ -76,16 +76,16 @@ const preferRegexpExecMessage = "Prefer `RegExp#exec(str)` over `String#match(re
76
76
  // already validated the token, so a textual scan of the trailing
77
77
  // suffix is sufficient.
78
78
  func preferRegexpExecHasGlobalFlag(file *shimast.SourceFile, node *shimast.Node) bool {
79
- raw := nodeText(file, node)
80
- if len(raw) < 2 || raw[0] != '/' {
81
- return false
82
- }
83
- closing := strings.LastIndexByte(raw, '/')
84
- if closing <= 0 {
85
- return false
86
- }
87
- flags := raw[closing+1:]
88
- return strings.Contains(flags, "g")
79
+ raw := nodeText(file, node)
80
+ if len(raw) < 2 || raw[0] != '/' {
81
+ return false
82
+ }
83
+ closing := strings.LastIndexByte(raw, '/')
84
+ if closing <= 0 {
85
+ return false
86
+ }
87
+ flags := raw[closing+1:]
88
+ return strings.Contains(flags, "g")
89
89
  }
90
90
 
91
91
  // preferRegexpExecIsString reports whether t is provably string-like.
@@ -93,30 +93,30 @@ func preferRegexpExecHasGlobalFlag(file *shimast.SourceFile, node *shimast.Node)
93
93
  // `never` are rejected so generic helpers don't fire. Union and
94
94
  // intersection types must have every constituent string-like.
95
95
  func preferRegexpExecIsString(t *shimchecker.Type) bool {
96
- if t == nil {
97
- return false
98
- }
99
- flags := t.Flags()
100
- if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
101
- return false
102
- }
103
- if flags&shimchecker.TypeFlagsStringLike != 0 {
104
- return true
105
- }
106
- if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
107
- for _, part := range t.Types() {
108
- if part == nil {
109
- continue
110
- }
111
- if !preferRegexpExecIsString(part) {
112
- return false
113
- }
114
- }
115
- return true
116
- }
117
- return false
96
+ if t == nil {
97
+ return false
98
+ }
99
+ flags := t.Flags()
100
+ if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
101
+ return false
102
+ }
103
+ if flags&shimchecker.TypeFlagsStringLike != 0 {
104
+ return true
105
+ }
106
+ if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
107
+ for _, part := range t.Types() {
108
+ if part == nil {
109
+ continue
110
+ }
111
+ if !preferRegexpExecIsString(part) {
112
+ return false
113
+ }
114
+ }
115
+ return true
116
+ }
117
+ return false
118
118
  }
119
119
 
120
120
  func init() {
121
- Register(preferRegexpExec{})
121
+ Register(preferRegexpExec{})
122
122
  }
@@ -26,68 +26,68 @@
26
26
  package linthost
27
27
 
28
28
  import (
29
- shimast "github.com/microsoft/typescript-go/shim/ast"
29
+ shimast "github.com/microsoft/typescript-go/shim/ast"
30
30
  )
31
31
 
32
32
  type preferReturnThisType struct{}
33
33
 
34
34
  func (preferReturnThisType) Name() string { return "typescript/prefer-return-this-type" }
35
35
  func (preferReturnThisType) NeedsTypeChecker() bool {
36
- return true
36
+ return true
37
37
  }
38
38
  func (preferReturnThisType) Visits() []shimast.Kind {
39
- return []shimast.Kind{shimast.KindMethodDeclaration}
39
+ return []shimast.Kind{shimast.KindMethodDeclaration}
40
40
  }
41
41
  func (preferReturnThisType) Check(ctx *Context, node *shimast.Node) {
42
- if ctx.Checker == nil {
43
- return
44
- }
45
- decl := node.AsMethodDeclaration()
46
- if decl == nil || decl.Body == nil {
47
- return
48
- }
49
- // Skip async / generator methods — their return shape is wrapped
50
- // (`Promise<...>` / `Generator<...>`) and not directly `this`.
51
- if hasAsyncModifier(node) {
52
- return
53
- }
54
- if decl.AsteriskToken != nil {
55
- return
56
- }
57
- // Skip static methods — the upstream rule targets instance-method
58
- // chains where the receiver type is the subclass; static dispatch
59
- // uses the class itself and `this` rewriting changes nothing.
60
- if hasModifier(node, shimast.KindStaticKeyword) {
61
- return
62
- }
63
- // The method must have an explicit return-type annotation that is
64
- // NOT already `this`. The rewrite-target is the existing annotation;
65
- // without one, adding `this` would force a new annotation that the
66
- // upstream rule does not propose.
67
- if decl.Type == nil {
68
- return
69
- }
70
- if decl.Type.Kind == shimast.KindThisType {
71
- return
72
- }
73
- // The enclosing class must exist — the rule applies to instance
74
- // methods of class declarations / expressions only.
75
- parent := node.Parent
76
- if parent == nil {
77
- return
78
- }
79
- if parent.Kind != shimast.KindClassDeclaration &&
80
- parent.Kind != shimast.KindClassExpression {
81
- return
82
- }
83
- // Walk the method body. Every value-returning `return` must
84
- // return exactly `this`; we also require at least one return
85
- // statement so we don't fire on methods that fall off the end.
86
- hasValueReturn, allAreThis := preferReturnThisTypeAnalyzeBody(decl.Body)
87
- if !hasValueReturn || !allAreThis {
88
- return
89
- }
90
- ctx.Report(decl.Type, preferReturnThisTypeMessage)
42
+ if ctx.Checker == nil {
43
+ return
44
+ }
45
+ decl := node.AsMethodDeclaration()
46
+ if decl == nil || decl.Body == nil {
47
+ return
48
+ }
49
+ // Skip async / generator methods — their return shape is wrapped
50
+ // (`Promise<...>` / `Generator<...>`) and not directly `this`.
51
+ if hasAsyncModifier(node) {
52
+ return
53
+ }
54
+ if decl.AsteriskToken != nil {
55
+ return
56
+ }
57
+ // Skip static methods — the upstream rule targets instance-method
58
+ // chains where the receiver type is the subclass; static dispatch
59
+ // uses the class itself and `this` rewriting changes nothing.
60
+ if hasModifier(node, shimast.KindStaticKeyword) {
61
+ return
62
+ }
63
+ // The method must have an explicit return-type annotation that is
64
+ // NOT already `this`. The rewrite-target is the existing annotation;
65
+ // without one, adding `this` would force a new annotation that the
66
+ // upstream rule does not propose.
67
+ if decl.Type == nil {
68
+ return
69
+ }
70
+ if decl.Type.Kind == shimast.KindThisType {
71
+ return
72
+ }
73
+ // The enclosing class must exist — the rule applies to instance
74
+ // methods of class declarations / expressions only.
75
+ parent := node.Parent
76
+ if parent == nil {
77
+ return
78
+ }
79
+ if parent.Kind != shimast.KindClassDeclaration &&
80
+ parent.Kind != shimast.KindClassExpression {
81
+ return
82
+ }
83
+ // Walk the method body. Every value-returning `return` must
84
+ // return exactly `this`; we also require at least one return
85
+ // statement so we don't fire on methods that fall off the end.
86
+ hasValueReturn, allAreThis := preferReturnThisTypeAnalyzeBody(decl.Body)
87
+ if !hasValueReturn || !allAreThis {
88
+ return
89
+ }
90
+ ctx.Report(decl.Type, preferReturnThisTypeMessage)
91
91
  }
92
92
 
93
93
  const preferReturnThisTypeMessage = "Method always returns `this` — declare the return type as `this` so subclass call sites keep the narrower receiver type."
@@ -102,34 +102,34 @@ const preferReturnThisTypeMessage = "Method always returns `this` — declare th
102
102
  // cannot rewrite to `this` regardless. The conservative interpretation
103
103
  // matches the upstream rule's behavior.
104
104
  func preferReturnThisTypeAnalyzeBody(body *shimast.Node) (hasValueReturn, allAreThis bool) {
105
- allAreThis = true
106
- var walk func(*shimast.Node)
107
- walk = func(n *shimast.Node) {
108
- if n == nil {
109
- return
110
- }
111
- if n != body && isFunctionLikeKind(n) {
112
- return
113
- }
114
- if n.Kind == shimast.KindReturnStatement {
115
- ret := n.AsReturnStatement()
116
- if ret != nil && ret.Expression != nil {
117
- hasValueReturn = true
118
- inner := stripParens(ret.Expression)
119
- if inner == nil || inner.Kind != shimast.KindThisKeyword {
120
- allAreThis = false
121
- }
122
- }
123
- }
124
- n.ForEachChild(func(child *shimast.Node) bool {
125
- walk(child)
126
- return false
127
- })
128
- }
129
- walk(body)
130
- return hasValueReturn, allAreThis
105
+ allAreThis = true
106
+ var walk func(*shimast.Node)
107
+ walk = func(n *shimast.Node) {
108
+ if n == nil {
109
+ return
110
+ }
111
+ if n != body && isFunctionLikeKind(n) {
112
+ return
113
+ }
114
+ if n.Kind == shimast.KindReturnStatement {
115
+ ret := n.AsReturnStatement()
116
+ if ret != nil && ret.Expression != nil {
117
+ hasValueReturn = true
118
+ inner := stripParens(ret.Expression)
119
+ if inner == nil || inner.Kind != shimast.KindThisKeyword {
120
+ allAreThis = false
121
+ }
122
+ }
123
+ }
124
+ n.ForEachChild(func(child *shimast.Node) bool {
125
+ walk(child)
126
+ return false
127
+ })
128
+ }
129
+ walk(body)
130
+ return hasValueReturn, allAreThis
131
131
  }
132
132
 
133
133
  func init() {
134
- Register(preferReturnThisType{})
134
+ Register(preferReturnThisType{})
135
135
  }