@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
@@ -19,65 +19,65 @@
19
19
  package linthost
20
20
 
21
21
  import (
22
- shimast "github.com/microsoft/typescript-go/shim/ast"
22
+ shimast "github.com/microsoft/typescript-go/shim/ast"
23
23
  )
24
24
 
25
25
  type noMisusedSpread struct{}
26
26
 
27
27
  func (noMisusedSpread) Name() string { return "typescript/no-misused-spread" }
28
28
  func (noMisusedSpread) Visits() []shimast.Kind {
29
- return []shimast.Kind{
30
- shimast.KindArrayLiteralExpression,
31
- shimast.KindObjectLiteralExpression,
32
- shimast.KindCallExpression,
33
- shimast.KindNewExpression,
34
- }
29
+ return []shimast.Kind{
30
+ shimast.KindArrayLiteralExpression,
31
+ shimast.KindObjectLiteralExpression,
32
+ shimast.KindCallExpression,
33
+ shimast.KindNewExpression,
34
+ }
35
35
  }
36
36
  func (noMisusedSpread) Check(ctx *Context, node *shimast.Node) {
37
- switch node.Kind {
38
- case shimast.KindArrayLiteralExpression:
39
- arr := node.AsArrayLiteralExpression()
40
- if arr == nil || arr.Elements == nil {
41
- return
42
- }
43
- for _, elem := range arr.Elements.Nodes {
44
- reportObjectSpreadInIterable(ctx, elem)
45
- }
46
- case shimast.KindCallExpression:
47
- call := node.AsCallExpression()
48
- if call == nil || call.Arguments == nil {
49
- return
50
- }
51
- for _, arg := range call.Arguments.Nodes {
52
- reportObjectSpreadInIterable(ctx, arg)
53
- }
54
- case shimast.KindNewExpression:
55
- ne := node.AsNewExpression()
56
- if ne == nil || ne.Arguments == nil {
57
- return
58
- }
59
- for _, arg := range ne.Arguments.Nodes {
60
- reportObjectSpreadInIterable(ctx, arg)
61
- }
62
- case shimast.KindObjectLiteralExpression:
63
- obj := node.AsObjectLiteralExpression()
64
- if obj == nil || obj.Properties == nil {
65
- return
66
- }
67
- for _, prop := range obj.Properties.Nodes {
68
- if prop == nil || prop.Kind != shimast.KindSpreadAssignment {
69
- continue
70
- }
71
- spread := prop.AsSpreadAssignment()
72
- if spread == nil {
73
- continue
74
- }
75
- inner := stripParens(spread.Expression)
76
- if inner != nil && inner.Kind == shimast.KindArrayLiteralExpression {
77
- ctx.Report(prop, "Spreading an array literal into an object literal coerces numeric indices to string keys — likely a mistake.")
78
- }
79
- }
80
- }
37
+ switch node.Kind {
38
+ case shimast.KindArrayLiteralExpression:
39
+ arr := node.AsArrayLiteralExpression()
40
+ if arr == nil || arr.Elements == nil {
41
+ return
42
+ }
43
+ for _, elem := range arr.Elements.Nodes {
44
+ reportObjectSpreadInIterable(ctx, elem)
45
+ }
46
+ case shimast.KindCallExpression:
47
+ call := node.AsCallExpression()
48
+ if call == nil || call.Arguments == nil {
49
+ return
50
+ }
51
+ for _, arg := range call.Arguments.Nodes {
52
+ reportObjectSpreadInIterable(ctx, arg)
53
+ }
54
+ case shimast.KindNewExpression:
55
+ ne := node.AsNewExpression()
56
+ if ne == nil || ne.Arguments == nil {
57
+ return
58
+ }
59
+ for _, arg := range ne.Arguments.Nodes {
60
+ reportObjectSpreadInIterable(ctx, arg)
61
+ }
62
+ case shimast.KindObjectLiteralExpression:
63
+ obj := node.AsObjectLiteralExpression()
64
+ if obj == nil || obj.Properties == nil {
65
+ return
66
+ }
67
+ for _, prop := range obj.Properties.Nodes {
68
+ if prop == nil || prop.Kind != shimast.KindSpreadAssignment {
69
+ continue
70
+ }
71
+ spread := prop.AsSpreadAssignment()
72
+ if spread == nil {
73
+ continue
74
+ }
75
+ inner := stripParens(spread.Expression)
76
+ if inner != nil && inner.Kind == shimast.KindArrayLiteralExpression {
77
+ ctx.Report(prop, "Spreading an array literal into an object literal coerces numeric indices to string keys — likely a mistake.")
78
+ }
79
+ }
80
+ }
81
81
  }
82
82
 
83
83
  // reportObjectSpreadInIterable reports the spread element when its
@@ -85,20 +85,20 @@ func (noMisusedSpread) Check(ctx *Context, node *shimast.Node) {
85
85
  // via iteration (array literal element or function/constructor
86
86
  // argument).
87
87
  func reportObjectSpreadInIterable(ctx *Context, elem *shimast.Node) {
88
- if elem == nil || elem.Kind != shimast.KindSpreadElement {
89
- return
90
- }
91
- spread := elem.AsSpreadElement()
92
- if spread == nil {
93
- return
94
- }
95
- inner := stripParens(spread.Expression)
96
- if inner == nil || inner.Kind != shimast.KindObjectLiteralExpression {
97
- return
98
- }
99
- ctx.Report(elem, "Spread of an object literal into an iterable context is meaningless — object literals are not iterable.")
88
+ if elem == nil || elem.Kind != shimast.KindSpreadElement {
89
+ return
90
+ }
91
+ spread := elem.AsSpreadElement()
92
+ if spread == nil {
93
+ return
94
+ }
95
+ inner := stripParens(spread.Expression)
96
+ if inner == nil || inner.Kind != shimast.KindObjectLiteralExpression {
97
+ return
98
+ }
99
+ ctx.Report(elem, "Spread of an object literal into an iterable context is meaningless — object literals are not iterable.")
100
100
  }
101
101
 
102
102
  func init() {
103
- Register(noMisusedSpread{})
103
+ Register(noMisusedSpread{})
104
104
  }
@@ -14,100 +14,100 @@
14
14
  package linthost
15
15
 
16
16
  import (
17
- "strings"
17
+ "strings"
18
18
 
19
- shimast "github.com/microsoft/typescript-go/shim/ast"
19
+ shimast "github.com/microsoft/typescript-go/shim/ast"
20
20
  )
21
21
 
22
22
  type noRedundantTypeConstituents struct{}
23
23
 
24
24
  func (noRedundantTypeConstituents) Name() string {
25
- return "typescript/no-redundant-type-constituents"
25
+ return "typescript/no-redundant-type-constituents"
26
26
  }
27
27
  func (noRedundantTypeConstituents) Visits() []shimast.Kind {
28
- return []shimast.Kind{shimast.KindUnionType, shimast.KindIntersectionType}
28
+ return []shimast.Kind{shimast.KindUnionType, shimast.KindIntersectionType}
29
29
  }
30
30
  func (noRedundantTypeConstituents) Check(ctx *Context, node *shimast.Node) {
31
- types := unionOrIntersectionTypes(node)
32
- if len(types) < 2 {
33
- return
34
- }
35
- isUnion := node.Kind == shimast.KindUnionType
36
- hasAny := containsKeywordType(types, shimast.KindAnyKeyword)
37
- hasUnknown := containsKeywordType(types, shimast.KindUnknownKeyword)
38
- hasNever := containsKeywordType(types, shimast.KindNeverKeyword)
39
- label := "intersection"
40
- if isUnion {
41
- label = "union"
42
- }
43
- seen := map[string]bool{}
44
- for _, t := range types {
45
- if t == nil {
46
- continue
47
- }
48
- switch {
49
- case isUnion && (hasAny || hasUnknown) && t.Kind != shimast.KindAnyKeyword && t.Kind != shimast.KindUnknownKeyword:
50
- // `T | any` / `T | unknown` — every non-top constituent is
51
- // absorbed. `any` takes precedence in the message because
52
- // `any` also subsumes `unknown`.
53
- absorbing := "unknown"
54
- if hasAny {
55
- absorbing = "any"
56
- }
57
- ctx.Report(t, "Constituent is overridden by `"+absorbing+"` in the surrounding union.")
58
- case isUnion && hasNever && t.Kind == shimast.KindNeverKeyword:
59
- ctx.Report(t, "`never` is absorbed by the surrounding union.")
60
- case !isUnion && hasNever:
61
- // `T & never` collapses to `never` for every constituent.
62
- ctx.Report(t, "Intersection with `never` collapses to `never`.")
63
- case !isUnion && hasUnknown && t.Kind == shimast.KindUnknownKeyword:
64
- ctx.Report(t, "`unknown` is absorbed by the surrounding intersection.")
65
- }
66
- // Duplicate by textual identity — fire on the second occurrence
67
- // so the first declaration stays unblamed.
68
- key := strings.TrimSpace(nodeText(ctx.File, t))
69
- if key == "" {
70
- continue
71
- }
72
- if seen[key] {
73
- ctx.Report(t, "Duplicate constituent in "+label+".")
74
- continue
75
- }
76
- seen[key] = true
77
- }
31
+ types := unionOrIntersectionTypes(node)
32
+ if len(types) < 2 {
33
+ return
34
+ }
35
+ isUnion := node.Kind == shimast.KindUnionType
36
+ hasAny := containsKeywordType(types, shimast.KindAnyKeyword)
37
+ hasUnknown := containsKeywordType(types, shimast.KindUnknownKeyword)
38
+ hasNever := containsKeywordType(types, shimast.KindNeverKeyword)
39
+ label := "intersection"
40
+ if isUnion {
41
+ label = "union"
42
+ }
43
+ seen := map[string]bool{}
44
+ for _, t := range types {
45
+ if t == nil {
46
+ continue
47
+ }
48
+ switch {
49
+ case isUnion && (hasAny || hasUnknown) && t.Kind != shimast.KindAnyKeyword && t.Kind != shimast.KindUnknownKeyword:
50
+ // `T | any` / `T | unknown` — every non-top constituent is
51
+ // absorbed. `any` takes precedence in the message because
52
+ // `any` also subsumes `unknown`.
53
+ absorbing := "unknown"
54
+ if hasAny {
55
+ absorbing = "any"
56
+ }
57
+ ctx.Report(t, "Constituent is overridden by `"+absorbing+"` in the surrounding union.")
58
+ case isUnion && hasNever && t.Kind == shimast.KindNeverKeyword:
59
+ ctx.Report(t, "`never` is absorbed by the surrounding union.")
60
+ case !isUnion && hasNever:
61
+ // `T & never` collapses to `never` for every constituent.
62
+ ctx.Report(t, "Intersection with `never` collapses to `never`.")
63
+ case !isUnion && hasUnknown && t.Kind == shimast.KindUnknownKeyword:
64
+ ctx.Report(t, "`unknown` is absorbed by the surrounding intersection.")
65
+ }
66
+ // Duplicate by textual identity — fire on the second occurrence
67
+ // so the first declaration stays unblamed.
68
+ key := strings.TrimSpace(nodeText(ctx.File, t))
69
+ if key == "" {
70
+ continue
71
+ }
72
+ if seen[key] {
73
+ ctx.Report(t, "Duplicate constituent in "+label+".")
74
+ continue
75
+ }
76
+ seen[key] = true
77
+ }
78
78
  }
79
79
 
80
80
  // unionOrIntersectionTypes returns the constituent type nodes of a union
81
81
  // or intersection type node, or nil for other shapes.
82
82
  func unionOrIntersectionTypes(node *shimast.Node) []*shimast.Node {
83
- if node == nil {
84
- return nil
85
- }
86
- switch node.Kind {
87
- case shimast.KindUnionType:
88
- if u := node.AsUnionTypeNode(); u != nil && u.Types != nil {
89
- return u.Types.Nodes
90
- }
91
- case shimast.KindIntersectionType:
92
- if i := node.AsIntersectionTypeNode(); i != nil && i.Types != nil {
93
- return i.Types.Nodes
94
- }
95
- }
96
- return nil
83
+ if node == nil {
84
+ return nil
85
+ }
86
+ switch node.Kind {
87
+ case shimast.KindUnionType:
88
+ if u := node.AsUnionTypeNode(); u != nil && u.Types != nil {
89
+ return u.Types.Nodes
90
+ }
91
+ case shimast.KindIntersectionType:
92
+ if i := node.AsIntersectionTypeNode(); i != nil && i.Types != nil {
93
+ return i.Types.Nodes
94
+ }
95
+ }
96
+ return nil
97
97
  }
98
98
 
99
99
  // containsKeywordType reports whether `types` contains a direct keyword
100
100
  // type node of `kind` — `any`, `unknown`, or `never` in type position
101
101
  // parse as bare keyword nodes rather than identifiers.
102
102
  func containsKeywordType(types []*shimast.Node, kind shimast.Kind) bool {
103
- for _, t := range types {
104
- if t != nil && t.Kind == kind {
105
- return true
106
- }
107
- }
108
- return false
103
+ for _, t := range types {
104
+ if t != nil && t.Kind == kind {
105
+ return true
106
+ }
107
+ }
108
+ return false
109
109
  }
110
110
 
111
111
  func init() {
112
- Register(noRedundantTypeConstituents{})
112
+ Register(noRedundantTypeConstituents{})
113
113
  }
@@ -14,7 +14,7 @@
14
14
  package linthost
15
15
 
16
16
  import (
17
- shimast "github.com/microsoft/typescript-go/shim/ast"
17
+ shimast "github.com/microsoft/typescript-go/shim/ast"
18
18
  )
19
19
 
20
20
  type noRestrictedTypes struct{}
@@ -23,40 +23,40 @@ type noRestrictedTypes struct{}
23
23
  // when no config is supplied. Each entry pairs the banned identifier
24
24
  // with a short, actionable replacement hint.
25
25
  var noRestrictedTypesDefault = map[string]string{
26
- "Object": "Use `object` (any non-primitive) or a specific shape like `Record<string, unknown>` instead of `Object`.",
27
- "Function": "Declare the specific call signature instead of the unsafe `Function` type.",
28
- "Number": "Use the lowercase primitive `number` instead of the wrapper type `Number`.",
29
- "String": "Use the lowercase primitive `string` instead of the wrapper type `String`.",
30
- "Boolean": "Use the lowercase primitive `boolean` instead of the wrapper type `Boolean`.",
26
+ "Object": "Use `object` (any non-primitive) or a specific shape like `Record<string, unknown>` instead of `Object`.",
27
+ "Function": "Declare the specific call signature instead of the unsafe `Function` type.",
28
+ "Number": "Use the lowercase primitive `number` instead of the wrapper type `Number`.",
29
+ "String": "Use the lowercase primitive `string` instead of the wrapper type `String`.",
30
+ "Boolean": "Use the lowercase primitive `boolean` instead of the wrapper type `Boolean`.",
31
31
  }
32
32
 
33
33
  func (noRestrictedTypes) Name() string { return "typescript/no-restricted-types" }
34
34
  func (noRestrictedTypes) Visits() []shimast.Kind {
35
- return []shimast.Kind{shimast.KindTypeReference}
35
+ return []shimast.Kind{shimast.KindTypeReference}
36
36
  }
37
37
  func (noRestrictedTypes) Check(ctx *Context, node *shimast.Node) {
38
- ref := node.AsTypeReferenceNode()
39
- if ref == nil || ref.TypeName == nil {
40
- return
41
- }
42
- name := identifierText(ref.TypeName)
43
- if name == "" {
44
- return
45
- }
46
- message, banned := noRestrictedTypesDefault[name]
47
- if !banned {
48
- return
49
- }
50
- // Shadow guard: if the user has declared a same-named `type` /
51
- // `interface` / `class` at file scope, their identifier is NOT the
52
- // global wrapper. Re-use the wrapper-types helper so the two rules
53
- // stay consistent about what counts as a shadow.
54
- if fileShadowsWrapperName(ctx.File, name) {
55
- return
56
- }
57
- ctx.Report(node, message)
38
+ ref := node.AsTypeReferenceNode()
39
+ if ref == nil || ref.TypeName == nil {
40
+ return
41
+ }
42
+ name := identifierText(ref.TypeName)
43
+ if name == "" {
44
+ return
45
+ }
46
+ message, banned := noRestrictedTypesDefault[name]
47
+ if !banned {
48
+ return
49
+ }
50
+ // Shadow guard: if the user has declared a same-named `type` /
51
+ // `interface` / `class` at file scope, their identifier is NOT the
52
+ // global wrapper. Re-use the wrapper-types helper so the two rules
53
+ // stay consistent about what counts as a shadow.
54
+ if fileShadowsWrapperName(ctx.File, name) {
55
+ return
56
+ }
57
+ ctx.Report(node, message)
58
58
  }
59
59
 
60
60
  func init() {
61
- Register(noRestrictedTypes{})
61
+ Register(noRestrictedTypes{})
62
62
  }
@@ -12,81 +12,81 @@
12
12
  package linthost
13
13
 
14
14
  import (
15
- shimast "github.com/microsoft/typescript-go/shim/ast"
16
- shimchecker "github.com/microsoft/typescript-go/shim/checker"
15
+ shimast "github.com/microsoft/typescript-go/shim/ast"
16
+ shimchecker "github.com/microsoft/typescript-go/shim/checker"
17
17
  )
18
18
 
19
19
  type noUnnecessaryBooleanLiteralCompare struct{}
20
20
 
21
21
  func (noUnnecessaryBooleanLiteralCompare) Name() string {
22
- return "typescript/no-unnecessary-boolean-literal-compare"
22
+ return "typescript/no-unnecessary-boolean-literal-compare"
23
23
  }
24
24
  func (noUnnecessaryBooleanLiteralCompare) NeedsTypeChecker() bool {
25
- return true
25
+ return true
26
26
  }
27
27
  func (noUnnecessaryBooleanLiteralCompare) Visits() []shimast.Kind {
28
- return []shimast.Kind{shimast.KindBinaryExpression}
28
+ return []shimast.Kind{shimast.KindBinaryExpression}
29
29
  }
30
30
  func (noUnnecessaryBooleanLiteralCompare) Check(ctx *Context, node *shimast.Node) {
31
- if ctx.Checker == nil {
32
- return
33
- }
34
- bin := node.AsBinaryExpression()
35
- if bin == nil || bin.OperatorToken == nil || bin.Left == nil || bin.Right == nil {
36
- return
37
- }
38
- // Only equality / inequality operators are subject to the rewrite —
39
- // `<`, `>`, `&&`, etc. against `true` / `false` are not the same shape.
40
- switch bin.OperatorToken.Kind {
41
- case shimast.KindEqualsEqualsToken,
42
- shimast.KindEqualsEqualsEqualsToken,
43
- shimast.KindExclamationEqualsToken,
44
- shimast.KindExclamationEqualsEqualsToken:
45
- default:
46
- return
47
- }
48
- left := stripParens(bin.Left)
49
- right := stripParens(bin.Right)
50
- if left == nil || right == nil {
51
- return
52
- }
53
- // Identify which side is the literal and which side is the value.
54
- // `true === x` and `x === true` are both reported.
55
- var value *shimast.Node
56
- switch {
57
- case noUnnecessaryBooleanLiteralCompareIsBoolLiteral(left):
58
- value = right
59
- case noUnnecessaryBooleanLiteralCompareIsBoolLiteral(right):
60
- value = left
61
- default:
62
- return
63
- }
64
- // Skip when both sides are literals — that's a different code smell
65
- // (e.g. `true === false`) that other rules cover.
66
- if noUnnecessaryBooleanLiteralCompareIsBoolLiteral(value) {
67
- return
68
- }
69
- t := ctx.Checker.GetTypeAtLocation(value)
70
- if t == nil {
71
- return
72
- }
73
- // Only fire when the value side is pure boolean. A `boolean | null`
74
- // operand uses the literal compare to strip nullability — leaving
75
- // that intact is the explicit carve-out the rule documentation calls
76
- // out, so we refuse to flag it.
77
- if !noUnnecessaryBooleanLiteralCompareIsPureBoolean(t) {
78
- return
79
- }
80
- ctx.Report(node, "This comparison against a boolean literal is unnecessary; use the value (or its negation) directly.")
31
+ if ctx.Checker == nil {
32
+ return
33
+ }
34
+ bin := node.AsBinaryExpression()
35
+ if bin == nil || bin.OperatorToken == nil || bin.Left == nil || bin.Right == nil {
36
+ return
37
+ }
38
+ // Only equality / inequality operators are subject to the rewrite —
39
+ // `<`, `>`, `&&`, etc. against `true` / `false` are not the same shape.
40
+ switch bin.OperatorToken.Kind {
41
+ case shimast.KindEqualsEqualsToken,
42
+ shimast.KindEqualsEqualsEqualsToken,
43
+ shimast.KindExclamationEqualsToken,
44
+ shimast.KindExclamationEqualsEqualsToken:
45
+ default:
46
+ return
47
+ }
48
+ left := stripParens(bin.Left)
49
+ right := stripParens(bin.Right)
50
+ if left == nil || right == nil {
51
+ return
52
+ }
53
+ // Identify which side is the literal and which side is the value.
54
+ // `true === x` and `x === true` are both reported.
55
+ var value *shimast.Node
56
+ switch {
57
+ case noUnnecessaryBooleanLiteralCompareIsBoolLiteral(left):
58
+ value = right
59
+ case noUnnecessaryBooleanLiteralCompareIsBoolLiteral(right):
60
+ value = left
61
+ default:
62
+ return
63
+ }
64
+ // Skip when both sides are literals — that's a different code smell
65
+ // (e.g. `true === false`) that other rules cover.
66
+ if noUnnecessaryBooleanLiteralCompareIsBoolLiteral(value) {
67
+ return
68
+ }
69
+ t := ctx.Checker.GetTypeAtLocation(value)
70
+ if t == nil {
71
+ return
72
+ }
73
+ // Only fire when the value side is pure boolean. A `boolean | null`
74
+ // operand uses the literal compare to strip nullability — leaving
75
+ // that intact is the explicit carve-out the rule documentation calls
76
+ // out, so we refuse to flag it.
77
+ if !noUnnecessaryBooleanLiteralCompareIsPureBoolean(t) {
78
+ return
79
+ }
80
+ ctx.Report(node, "This comparison against a boolean literal is unnecessary; use the value (or its negation) directly.")
81
81
  }
82
82
 
83
83
  // noUnnecessaryBooleanLiteralCompareIsBoolLiteral reports whether node is
84
84
  // the literal `true` or `false` keyword.
85
85
  func noUnnecessaryBooleanLiteralCompareIsBoolLiteral(node *shimast.Node) bool {
86
- if node == nil {
87
- return false
88
- }
89
- return node.Kind == shimast.KindTrueKeyword || node.Kind == shimast.KindFalseKeyword
86
+ if node == nil {
87
+ return false
88
+ }
89
+ return node.Kind == shimast.KindTrueKeyword || node.Kind == shimast.KindFalseKeyword
90
90
  }
91
91
 
92
92
  // noUnnecessaryBooleanLiteralCompareIsPureBoolean reports whether t is a
@@ -95,35 +95,35 @@ func noUnnecessaryBooleanLiteralCompareIsBoolLiteral(node *shimast.Node) bool {
95
95
  // are explicitly excluded so the literal compare stays in place when it
96
96
  // is also stripping nullability or escaping an opaque value.
97
97
  func noUnnecessaryBooleanLiteralCompareIsPureBoolean(t *shimchecker.Type) bool {
98
- if t == nil {
99
- return false
100
- }
101
- flags := t.Flags()
102
- if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
103
- return false
104
- }
105
- if flags&shimchecker.TypeFlagsUnion != 0 {
106
- parts := t.Types()
107
- if len(parts) == 0 {
108
- return false
109
- }
110
- for _, part := range parts {
111
- if part == nil {
112
- return false
113
- }
114
- pf := part.Flags()
115
- if pf&(shimchecker.TypeFlagsNull|shimchecker.TypeFlagsUndefined) != 0 {
116
- return false
117
- }
118
- if pf&shimchecker.TypeFlagsBooleanLike == 0 {
119
- return false
120
- }
121
- }
122
- return true
123
- }
124
- return flags&shimchecker.TypeFlagsBooleanLike != 0
98
+ if t == nil {
99
+ return false
100
+ }
101
+ flags := t.Flags()
102
+ if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
103
+ return false
104
+ }
105
+ if flags&shimchecker.TypeFlagsUnion != 0 {
106
+ parts := t.Types()
107
+ if len(parts) == 0 {
108
+ return false
109
+ }
110
+ for _, part := range parts {
111
+ if part == nil {
112
+ return false
113
+ }
114
+ pf := part.Flags()
115
+ if pf&(shimchecker.TypeFlagsNull|shimchecker.TypeFlagsUndefined) != 0 {
116
+ return false
117
+ }
118
+ if pf&shimchecker.TypeFlagsBooleanLike == 0 {
119
+ return false
120
+ }
121
+ }
122
+ return true
123
+ }
124
+ return flags&shimchecker.TypeFlagsBooleanLike != 0
125
125
  }
126
126
 
127
127
  func init() {
128
- Register(noUnnecessaryBooleanLiteralCompare{})
128
+ Register(noUnnecessaryBooleanLiteralCompare{})
129
129
  }