@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
@@ -244,12 +244,27 @@ func (noWrapperObjectTypes) Check(ctx *Context, node *shimast.Node) {
244
244
  )
245
245
  }
246
246
 
247
- // fileShadowsWrapperName reports whether the source file declares its own
248
- // `String`/`Number`/`Boolean`/`Symbol`/`BigInt`/`Object` at top level via
249
- // `type`, `interface`, or `class`. Walks SourceFile.Statements once; no
247
+ // fileShadowsWrapperName reports whether the source file binds its own
248
+ // `String`/`Number`/`Boolean`/`Symbol`/`BigInt`/`Object` at top level, so
249
+ // the referenced name is NOT the global wrapper and a rewrite to the
250
+ // primitive would change the type. Walks SourceFile.Statements once; no
250
251
  // memoization because the rule already runs once per TypeReference and
251
252
  // the average statement count per file dominates the cost over the inner
252
253
  // loop.
254
+ //
255
+ // The guard is intentionally comprehensive: it returns true when the
256
+ // wrapper name is bound by ANY file-scope declaration, because over-bailing
257
+ // (declining to rewrite a real global wrapper because a same-named binding
258
+ // exists) is safe — it only skips a lint fix — whereas under-bailing
259
+ // silently corrupts the type. A binding shadows the global when it comes
260
+ // from:
261
+ // - a `type` / `interface` / `class` / `enum` declaration,
262
+ // - a `function` declaration,
263
+ // - a `namespace` / `module` declaration,
264
+ // - a top-level `let` / `const` / `var` value declaration,
265
+ // - an import binding (default, namespace, or named — including an
266
+ // aliased `{ X as String }`, where the LOCAL name is what binds), or
267
+ // - an `import X = require(...)` / `import X = A.B` binding.
253
268
  func fileShadowsWrapperName(file *shimast.SourceFile, name string) bool {
254
269
  if file == nil || file.Statements == nil {
255
270
  return false
@@ -258,24 +273,144 @@ func fileShadowsWrapperName(file *shimast.SourceFile, name string) bool {
258
273
  if stmt == nil {
259
274
  continue
260
275
  }
261
- var declName *shimast.Node
262
276
  switch stmt.Kind {
263
277
  case shimast.KindTypeAliasDeclaration:
264
- if alias := stmt.AsTypeAliasDeclaration(); alias != nil {
265
- declName = alias.Name()
278
+ if alias := stmt.AsTypeAliasDeclaration(); alias != nil &&
279
+ identifierText(alias.Name()) == name {
280
+ return true
266
281
  }
267
282
  case shimast.KindInterfaceDeclaration:
268
- if iface := stmt.AsInterfaceDeclaration(); iface != nil {
269
- declName = iface.Name()
283
+ if iface := stmt.AsInterfaceDeclaration(); iface != nil &&
284
+ identifierText(iface.Name()) == name {
285
+ return true
270
286
  }
271
287
  case shimast.KindClassDeclaration:
272
- if cls := stmt.AsClassDeclaration(); cls != nil {
273
- declName = cls.Name()
288
+ if cls := stmt.AsClassDeclaration(); cls != nil &&
289
+ identifierText(cls.Name()) == name {
290
+ return true
291
+ }
292
+ case shimast.KindEnumDeclaration:
293
+ if enm := stmt.AsEnumDeclaration(); enm != nil &&
294
+ identifierText(enm.Name()) == name {
295
+ return true
296
+ }
297
+ case shimast.KindFunctionDeclaration:
298
+ if fn := stmt.AsFunctionDeclaration(); fn != nil &&
299
+ identifierText(fn.Name()) == name {
300
+ return true
301
+ }
302
+ case shimast.KindModuleDeclaration:
303
+ if mod := stmt.AsModuleDeclaration(); mod != nil &&
304
+ identifierText(mod.Name()) == name {
305
+ return true
306
+ }
307
+ case shimast.KindVariableStatement:
308
+ if variableStatementBindsName(stmt, name) {
309
+ return true
310
+ }
311
+ case shimast.KindImportDeclaration:
312
+ if importDeclarationBindsName(stmt, name) {
313
+ return true
314
+ }
315
+ case shimast.KindImportEqualsDeclaration:
316
+ if imp := stmt.AsImportEqualsDeclaration(); imp != nil &&
317
+ identifierText(imp.Name()) == name {
318
+ return true
319
+ }
320
+ }
321
+ }
322
+ return false
323
+ }
324
+
325
+ // variableStatementBindsName reports whether a top-level `let`/`const`/`var`
326
+ // statement binds `name` through a (possibly destructured) declaration.
327
+ func variableStatementBindsName(stmt *shimast.Node, name string) bool {
328
+ vs := stmt.AsVariableStatement()
329
+ if vs == nil || vs.DeclarationList == nil {
330
+ return false
331
+ }
332
+ list := vs.DeclarationList.AsVariableDeclarationList()
333
+ if list == nil || list.Declarations == nil {
334
+ return false
335
+ }
336
+ for _, declNode := range list.Declarations.Nodes {
337
+ if declNode == nil {
338
+ continue
339
+ }
340
+ decl := declNode.AsVariableDeclaration()
341
+ if decl != nil && bindingNameContains(decl.Name(), name) {
342
+ return true
343
+ }
344
+ }
345
+ return false
346
+ }
347
+
348
+ // bindingNameContains reports whether a binding name (a plain identifier or
349
+ // an object/array binding pattern) introduces `name`.
350
+ func bindingNameContains(binding *shimast.Node, name string) bool {
351
+ if binding == nil {
352
+ return false
353
+ }
354
+ if binding.Kind == shimast.KindIdentifier {
355
+ return identifierText(binding) == name
356
+ }
357
+ found := false
358
+ binding.ForEachChild(func(child *shimast.Node) bool {
359
+ if child == nil {
360
+ return false
361
+ }
362
+ if child.Kind == shimast.KindBindingElement {
363
+ if elem := child.AsBindingElement(); elem != nil &&
364
+ bindingNameContains(elem.Name(), name) {
365
+ found = true
366
+ return true
274
367
  }
275
368
  }
276
- if declName != nil && identifierText(declName) == name {
369
+ return false
370
+ })
371
+ return found
372
+ }
373
+
374
+ // importDeclarationBindsName reports whether a top-level import statement
375
+ // introduces `name` as a local binding: a default import, a namespace
376
+ // import, or a named import (using the LOCAL name, so `{ X as String }`
377
+ // binds `String`).
378
+ func importDeclarationBindsName(stmt *shimast.Node, name string) bool {
379
+ decl := stmt.AsImportDeclaration()
380
+ if decl == nil || decl.ImportClause == nil {
381
+ return false
382
+ }
383
+ clause := decl.ImportClause.AsImportClause()
384
+ if clause == nil {
385
+ return false
386
+ }
387
+ if identifierText(clause.Name()) == name {
388
+ return true
389
+ }
390
+ bindings := clause.NamedBindings
391
+ if bindings == nil {
392
+ return false
393
+ }
394
+ switch bindings.Kind {
395
+ case shimast.KindNamespaceImport:
396
+ if ns := bindings.AsNamespaceImport(); ns != nil &&
397
+ identifierText(ns.Name()) == name {
277
398
  return true
278
399
  }
400
+ case shimast.KindNamedImports:
401
+ named := bindings.AsNamedImports()
402
+ if named == nil || named.Elements == nil {
403
+ return false
404
+ }
405
+ for _, specNode := range named.Elements.Nodes {
406
+ if specNode == nil {
407
+ continue
408
+ }
409
+ if spec := specNode.AsImportSpecifier(); spec != nil &&
410
+ identifierText(spec.Name()) == name {
411
+ return true
412
+ }
413
+ }
279
414
  }
280
415
  return false
281
416
  }
@@ -19,69 +19,69 @@ type groupedAccessorPairs struct{}
19
19
 
20
20
  func (groupedAccessorPairs) Name() string { return "grouped-accessor-pairs" }
21
21
  func (groupedAccessorPairs) Visits() []shimast.Kind {
22
- return []shimast.Kind{shimast.KindClassDeclaration, shimast.KindClassExpression}
22
+ return []shimast.Kind{shimast.KindClassDeclaration, shimast.KindClassExpression}
23
23
  }
24
24
  func (groupedAccessorPairs) Check(ctx *Context, node *shimast.Node) {
25
- members := classMembers(node)
26
- if len(members) < 2 {
27
- return
28
- }
29
- type slot struct {
30
- name string
31
- static bool
32
- }
33
- type entry struct {
34
- index int
35
- kind shimast.Kind
36
- node *shimast.Node
37
- }
38
- groups := map[slot][]entry{}
39
- for i, member := range members {
40
- if member == nil {
41
- continue
42
- }
43
- if member.Kind != shimast.KindGetAccessor && member.Kind != shimast.KindSetAccessor {
44
- continue
45
- }
46
- name := classMemberName(member)
47
- if name == "" {
48
- continue
49
- }
50
- key := slot{name: name, static: hasModifier(member, shimast.KindStaticKeyword)}
51
- groups[key] = append(groups[key], entry{index: i, kind: member.Kind, node: member})
52
- }
53
- for _, entries := range groups {
54
- if len(entries) < 2 {
55
- continue
56
- }
57
- // Find a getter/setter pair within the group.
58
- var get, set *entry
59
- for i := range entries {
60
- e := &entries[i]
61
- if e.kind == shimast.KindGetAccessor && get == nil {
62
- get = e
63
- } else if e.kind == shimast.KindSetAccessor && set == nil {
64
- set = e
65
- }
66
- }
67
- if get == nil || set == nil {
68
- continue
69
- }
70
- // Adjacent indices in the members list satisfy the rule.
71
- diff := get.index - set.index
72
- if diff == 1 || diff == -1 {
73
- continue
74
- }
75
- // Report on whichever half appears later — the earlier one
76
- // reads fine in isolation; the later one is the surprise.
77
- later := get
78
- if set.index > get.index {
79
- later = set
80
- }
81
- ctx.Report(later.node, "Accessor pair should be grouped.")
82
- }
25
+ members := classMembers(node)
26
+ if len(members) < 2 {
27
+ return
28
+ }
29
+ type slot struct {
30
+ name string
31
+ static bool
32
+ }
33
+ type entry struct {
34
+ index int
35
+ kind shimast.Kind
36
+ node *shimast.Node
37
+ }
38
+ groups := map[slot][]entry{}
39
+ for i, member := range members {
40
+ if member == nil {
41
+ continue
42
+ }
43
+ if member.Kind != shimast.KindGetAccessor && member.Kind != shimast.KindSetAccessor {
44
+ continue
45
+ }
46
+ name := classMemberName(member)
47
+ if name == "" {
48
+ continue
49
+ }
50
+ key := slot{name: name, static: hasModifier(member, shimast.KindStaticKeyword)}
51
+ groups[key] = append(groups[key], entry{index: i, kind: member.Kind, node: member})
52
+ }
53
+ for _, entries := range groups {
54
+ if len(entries) < 2 {
55
+ continue
56
+ }
57
+ // Find a getter/setter pair within the group.
58
+ var get, set *entry
59
+ for i := range entries {
60
+ e := &entries[i]
61
+ if e.kind == shimast.KindGetAccessor && get == nil {
62
+ get = e
63
+ } else if e.kind == shimast.KindSetAccessor && set == nil {
64
+ set = e
65
+ }
66
+ }
67
+ if get == nil || set == nil {
68
+ continue
69
+ }
70
+ // Adjacent indices in the members list satisfy the rule.
71
+ diff := get.index - set.index
72
+ if diff == 1 || diff == -1 {
73
+ continue
74
+ }
75
+ // Report on whichever half appears later — the earlier one
76
+ // reads fine in isolation; the later one is the surprise.
77
+ later := get
78
+ if set.index > get.index {
79
+ later = set
80
+ }
81
+ ctx.Report(later.node, "Accessor pair should be grouped.")
82
+ }
83
83
  }
84
84
 
85
85
  func init() {
86
- Register(groupedAccessorPairs{})
86
+ Register(groupedAccessorPairs{})
87
87
  }
@@ -17,7 +17,7 @@
17
17
  package linthost
18
18
 
19
19
  import (
20
- shimast "github.com/microsoft/typescript-go/shim/ast"
20
+ shimast "github.com/microsoft/typescript-go/shim/ast"
21
21
  )
22
22
 
23
23
  type guardForIn struct{}
@@ -25,19 +25,19 @@ type guardForIn struct{}
25
25
  func (guardForIn) Name() string { return "guard-for-in" }
26
26
  func (guardForIn) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindForInStatement} }
27
27
  func (guardForIn) Check(ctx *Context, node *shimast.Node) {
28
- stmt := node.AsForInOrOfStatement()
29
- if stmt == nil || stmt.Statement == nil {
30
- return
31
- }
32
- first := firstBodyStatement(stmt.Statement)
33
- if first == nil {
34
- return
35
- }
36
- key := forInKeyName(stmt.Initializer)
37
- if isHasOwnGuard(first, key) {
38
- return
39
- }
40
- ctx.Report(node, "The body of a `for...in` should be wrapped in an `if (Object.hasOwn(...))` statement to filter unwanted properties from the prototype.")
28
+ stmt := node.AsForInOrOfStatement()
29
+ if stmt == nil || stmt.Statement == nil {
30
+ return
31
+ }
32
+ first := firstBodyStatement(stmt.Statement)
33
+ if first == nil {
34
+ return
35
+ }
36
+ key := forInKeyName(stmt.Initializer)
37
+ if isHasOwnGuard(first, key) {
38
+ return
39
+ }
40
+ ctx.Report(node, "The body of a `for...in` should be wrapped in an `if (Object.hasOwn(...))` statement to filter unwanted properties from the prototype.")
41
41
  }
42
42
 
43
43
  // firstBodyStatement returns the first executable statement inside a
@@ -45,22 +45,22 @@ func (guardForIn) Check(ctx *Context, node *shimast.Node) {
45
45
  // non-block body is itself the only statement. Returns nil for an
46
46
  // empty block — an empty body cannot leak inherited keys.
47
47
  func firstBodyStatement(body *shimast.Node) *shimast.Node {
48
- if body == nil {
49
- return nil
50
- }
51
- if body.Kind != shimast.KindBlock {
52
- return body
53
- }
54
- block := body.AsBlock()
55
- if block == nil || block.Statements == nil {
56
- return nil
57
- }
58
- for _, s := range block.Statements.Nodes {
59
- if s != nil {
60
- return s
61
- }
62
- }
63
- return nil
48
+ if body == nil {
49
+ return nil
50
+ }
51
+ if body.Kind != shimast.KindBlock {
52
+ return body
53
+ }
54
+ block := body.AsBlock()
55
+ if block == nil || block.Statements == nil {
56
+ return nil
57
+ }
58
+ for _, s := range block.Statements.Nodes {
59
+ if s != nil {
60
+ return s
61
+ }
62
+ }
63
+ return nil
64
64
  }
65
65
 
66
66
  // forInKeyName extracts the identifier text of the loop key from a
@@ -69,28 +69,28 @@ func firstBodyStatement(body *shimast.Node) *shimast.Node {
69
69
  // or a bare Identifier (`for (key in …)`). Destructuring patterns and
70
70
  // other shapes return "" so the rule skips its key-identity check.
71
71
  func forInKeyName(init *shimast.Node) string {
72
- if init == nil {
73
- return ""
74
- }
75
- if name := identifierText(init); name != "" {
76
- return name
77
- }
78
- if init.Kind != shimast.KindVariableDeclarationList {
79
- return ""
80
- }
81
- list := init.AsVariableDeclarationList()
82
- if list == nil || list.Declarations == nil || len(list.Declarations.Nodes) != 1 {
83
- return ""
84
- }
85
- decl := list.Declarations.Nodes[0]
86
- if decl == nil {
87
- return ""
88
- }
89
- v := decl.AsVariableDeclaration()
90
- if v == nil {
91
- return ""
92
- }
93
- return identifierText(v.Name())
72
+ if init == nil {
73
+ return ""
74
+ }
75
+ if name := identifierText(init); name != "" {
76
+ return name
77
+ }
78
+ if init.Kind != shimast.KindVariableDeclarationList {
79
+ return ""
80
+ }
81
+ list := init.AsVariableDeclarationList()
82
+ if list == nil || list.Declarations == nil || len(list.Declarations.Nodes) != 1 {
83
+ return ""
84
+ }
85
+ decl := list.Declarations.Nodes[0]
86
+ if decl == nil {
87
+ return ""
88
+ }
89
+ v := decl.AsVariableDeclaration()
90
+ if v == nil {
91
+ return ""
92
+ }
93
+ return identifierText(v.Name())
94
94
  }
95
95
 
96
96
  // isHasOwnGuard reports whether `stmt` is the canonical own-key guard
@@ -110,89 +110,89 @@ func forInKeyName(init *shimast.Node) string {
110
110
  // initializer; otherwise any second argument is accepted (the rule
111
111
  // has no reliable handle on the key name).
112
112
  func isHasOwnGuard(stmt *shimast.Node, key string) bool {
113
- if stmt == nil || stmt.Kind != shimast.KindIfStatement {
114
- return false
115
- }
116
- ifStmt := stmt.AsIfStatement()
117
- if ifStmt == nil || ifStmt.Expression == nil {
118
- return false
119
- }
120
- cond := stripParens(ifStmt.Expression)
121
- if cond == nil {
122
- return false
123
- }
124
- if isHasOwnCall(cond, key) {
125
- return true
126
- }
127
- if cond.Kind != shimast.KindPrefixUnaryExpression {
128
- return false
129
- }
130
- pre := cond.AsPrefixUnaryExpression()
131
- if pre == nil || pre.Operator != shimast.KindExclamationToken {
132
- return false
133
- }
134
- if !isHasOwnCall(stripParens(pre.Operand), key) {
135
- return false
136
- }
137
- // Negated guard: require the then branch to be a single `continue`
138
- // so the rest of the loop runs only for own keys.
139
- return isLoneContinue(ifStmt.ThenStatement)
113
+ if stmt == nil || stmt.Kind != shimast.KindIfStatement {
114
+ return false
115
+ }
116
+ ifStmt := stmt.AsIfStatement()
117
+ if ifStmt == nil || ifStmt.Expression == nil {
118
+ return false
119
+ }
120
+ cond := stripParens(ifStmt.Expression)
121
+ if cond == nil {
122
+ return false
123
+ }
124
+ if isHasOwnCall(cond, key) {
125
+ return true
126
+ }
127
+ if cond.Kind != shimast.KindPrefixUnaryExpression {
128
+ return false
129
+ }
130
+ pre := cond.AsPrefixUnaryExpression()
131
+ if pre == nil || pre.Operator != shimast.KindExclamationToken {
132
+ return false
133
+ }
134
+ if !isHasOwnCall(stripParens(pre.Operand), key) {
135
+ return false
136
+ }
137
+ // Negated guard: require the then branch to be a single `continue`
138
+ // so the rest of the loop runs only for own keys.
139
+ return isLoneContinue(ifStmt.ThenStatement)
140
140
  }
141
141
 
142
142
  // isHasOwnCall reports whether `node` is `Object.hasOwn(obj, key)` or
143
143
  // `Object.prototype.hasOwnProperty.call(obj, key)`. The second
144
144
  // argument must match `key` when one is supplied.
145
145
  func isHasOwnCall(node *shimast.Node, key string) bool {
146
- if node == nil || node.Kind != shimast.KindCallExpression {
147
- return false
148
- }
149
- call := node.AsCallExpression()
150
- if call == nil || call.Expression == nil || call.Arguments == nil {
151
- return false
152
- }
153
- args := call.Arguments.Nodes
154
- if len(args) < 2 {
155
- return false
156
- }
157
- callee := stripParens(call.Expression)
158
- switch {
159
- case isMatchingPropertyAccess(callee, "Object", "hasOwn"):
160
- // `Object.hasOwn(obj, key)` — both arguments belong to the
161
- // caller; the key check is the second argument.
162
- case isMatchingPropertyAccess(callee, "Object", "prototype", "hasOwnProperty", "call"):
163
- // `Object.prototype.hasOwnProperty.call(obj, key)` — same
164
- // argument layout because `.call(obj, key)` passes the
165
- // receiver explicitly.
166
- default:
167
- return false
168
- }
169
- if key == "" {
170
- return true
171
- }
172
- return identifierText(stripParens(args[1])) == key
146
+ if node == nil || node.Kind != shimast.KindCallExpression {
147
+ return false
148
+ }
149
+ call := node.AsCallExpression()
150
+ if call == nil || call.Expression == nil || call.Arguments == nil {
151
+ return false
152
+ }
153
+ args := call.Arguments.Nodes
154
+ if len(args) < 2 {
155
+ return false
156
+ }
157
+ callee := stripParens(call.Expression)
158
+ switch {
159
+ case isMatchingPropertyAccess(callee, "Object", "hasOwn"):
160
+ // `Object.hasOwn(obj, key)` — both arguments belong to the
161
+ // caller; the key check is the second argument.
162
+ case isMatchingPropertyAccess(callee, "Object", "prototype", "hasOwnProperty", "call"):
163
+ // `Object.prototype.hasOwnProperty.call(obj, key)` — same
164
+ // argument layout because `.call(obj, key)` passes the
165
+ // receiver explicitly.
166
+ default:
167
+ return false
168
+ }
169
+ if key == "" {
170
+ return true
171
+ }
172
+ return identifierText(stripParens(args[1])) == key
173
173
  }
174
174
 
175
175
  // isLoneContinue reports whether `stmt` is a bare `continue;` (or a
176
176
  // block containing exactly one `continue;`). Used to validate the
177
177
  // then-branch of the negated-guard shape.
178
178
  func isLoneContinue(stmt *shimast.Node) bool {
179
- if stmt == nil {
180
- return false
181
- }
182
- if stmt.Kind == shimast.KindContinueStatement {
183
- return true
184
- }
185
- if stmt.Kind != shimast.KindBlock {
186
- return false
187
- }
188
- block := stmt.AsBlock()
189
- if block == nil || block.Statements == nil || len(block.Statements.Nodes) != 1 {
190
- return false
191
- }
192
- return block.Statements.Nodes[0] != nil &&
193
- block.Statements.Nodes[0].Kind == shimast.KindContinueStatement
179
+ if stmt == nil {
180
+ return false
181
+ }
182
+ if stmt.Kind == shimast.KindContinueStatement {
183
+ return true
184
+ }
185
+ if stmt.Kind != shimast.KindBlock {
186
+ return false
187
+ }
188
+ block := stmt.AsBlock()
189
+ if block == nil || block.Statements == nil || len(block.Statements.Nodes) != 1 {
190
+ return false
191
+ }
192
+ return block.Statements.Nodes[0] != nil &&
193
+ block.Statements.Nodes[0].Kind == shimast.KindContinueStatement
194
194
  }
195
195
 
196
196
  func init() {
197
- Register(guardForIn{})
197
+ Register(guardForIn{})
198
198
  }