@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
@@ -14,9 +14,9 @@
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 unicornTextEncodingIdentifierCase struct{}
@@ -25,48 +25,48 @@ type unicornTextEncodingIdentifierCase struct{}
25
25
  // spelling. Authors who already wrote the canonical form pass; anything
26
26
  // else with the same lowercased label fires.
27
27
  var unicornCanonicalTextEncodings = map[string]string{
28
- "utf-8": "utf-8",
29
- "utf-16le": "utf-16le",
30
- "utf-16be": "utf-16be",
31
- "ascii": "ascii",
32
- "latin1": "latin1",
33
- "iso-8859-1": "iso-8859-1",
34
- "windows-1252": "windows-1252",
28
+ "utf-8": "utf-8",
29
+ "utf-16le": "utf-16le",
30
+ "utf-16be": "utf-16be",
31
+ "ascii": "ascii",
32
+ "latin1": "latin1",
33
+ "iso-8859-1": "iso-8859-1",
34
+ "windows-1252": "windows-1252",
35
35
  }
36
36
 
37
37
  func (unicornTextEncodingIdentifierCase) Name() string {
38
- return "unicorn/text-encoding-identifier-case"
38
+ return "unicorn/text-encoding-identifier-case"
39
39
  }
40
40
  func (unicornTextEncodingIdentifierCase) Visits() []shimast.Kind {
41
- return []shimast.Kind{shimast.KindStringLiteral, shimast.KindNoSubstitutionTemplateLiteral}
41
+ return []shimast.Kind{shimast.KindStringLiteral, shimast.KindNoSubstitutionTemplateLiteral}
42
42
  }
43
43
  func (unicornTextEncodingIdentifierCase) Check(ctx *Context, node *shimast.Node) {
44
- text := stringLiteralText(node)
45
- if text == "" {
46
- return
47
- }
48
- lower := strings.ToLower(text)
49
- canonical, ok := unicornCanonicalTextEncodings[lower]
50
- if !ok {
51
- // `utf8`/`UTF8` share a canonical form with `utf-8` but lowercase
52
- // differently — handle the hyphen-stripped aliases explicitly.
53
- switch lower {
54
- case "utf8":
55
- canonical = "utf-8"
56
- case "utf16le":
57
- canonical = "utf-16le"
58
- case "utf16be":
59
- canonical = "utf-16be"
60
- default:
61
- return
62
- }
63
- }
64
- if text == canonical {
65
- return
66
- }
67
- ctx.Report(node, "Use the canonical lowercase form for text-encoding identifiers (e.g. `utf-8`).")
44
+ text := stringLiteralText(node)
45
+ if text == "" {
46
+ return
47
+ }
48
+ lower := strings.ToLower(text)
49
+ canonical, ok := unicornCanonicalTextEncodings[lower]
50
+ if !ok {
51
+ // `utf8`/`UTF8` share a canonical form with `utf-8` but lowercase
52
+ // differently — handle the hyphen-stripped aliases explicitly.
53
+ switch lower {
54
+ case "utf8":
55
+ canonical = "utf-8"
56
+ case "utf16le":
57
+ canonical = "utf-16le"
58
+ case "utf16be":
59
+ canonical = "utf-16be"
60
+ default:
61
+ return
62
+ }
63
+ }
64
+ if text == canonical {
65
+ return
66
+ }
67
+ ctx.Report(node, "Use the canonical lowercase form for text-encoding identifiers (e.g. `utf-8`).")
68
68
  }
69
69
 
70
70
  func init() {
71
- Register(unicornTextEncodingIdentifierCase{})
71
+ Register(unicornTextEncodingIdentifierCase{})
72
72
  }
@@ -17,45 +17,45 @@ package linthost
17
17
  import shimast "github.com/microsoft/typescript-go/shim/ast"
18
18
 
19
19
  var unicornThrowNewErrorBuiltinNames = map[string]struct{}{
20
- "Error": {},
21
- "TypeError": {},
22
- "RangeError": {},
23
- "SyntaxError": {},
24
- "ReferenceError": {},
25
- "EvalError": {},
26
- "URIError": {},
27
- "AggregateError": {},
20
+ "Error": {},
21
+ "TypeError": {},
22
+ "RangeError": {},
23
+ "SyntaxError": {},
24
+ "ReferenceError": {},
25
+ "EvalError": {},
26
+ "URIError": {},
27
+ "AggregateError": {},
28
28
  }
29
29
 
30
30
  type unicornThrowNewError struct{}
31
31
 
32
32
  func (unicornThrowNewError) Name() string { return "unicorn/throw-new-error" }
33
33
  func (unicornThrowNewError) Visits() []shimast.Kind {
34
- return []shimast.Kind{shimast.KindThrowStatement}
34
+ return []shimast.Kind{shimast.KindThrowStatement}
35
35
  }
36
36
  func (unicornThrowNewError) Check(ctx *Context, node *shimast.Node) {
37
- throw := node.AsThrowStatement()
38
- if throw == nil {
39
- return
40
- }
41
- expr := stripParens(throw.Expression)
42
- if expr == nil || expr.Kind != shimast.KindCallExpression {
43
- return
44
- }
45
- call := expr.AsCallExpression()
46
- if call == nil {
47
- return
48
- }
49
- name := identifierText(call.Expression)
50
- if name == "" {
51
- return
52
- }
53
- if _, ok := unicornThrowNewErrorBuiltinNames[name]; !ok {
54
- return
55
- }
56
- ctx.Report(expr, "Use `new` when throwing an error.")
37
+ throw := node.AsThrowStatement()
38
+ if throw == nil {
39
+ return
40
+ }
41
+ expr := stripParens(throw.Expression)
42
+ if expr == nil || expr.Kind != shimast.KindCallExpression {
43
+ return
44
+ }
45
+ call := expr.AsCallExpression()
46
+ if call == nil {
47
+ return
48
+ }
49
+ name := identifierText(call.Expression)
50
+ if name == "" {
51
+ return
52
+ }
53
+ if _, ok := unicornThrowNewErrorBuiltinNames[name]; !ok {
54
+ return
55
+ }
56
+ ctx.Report(expr, "Use `new` when throwing an error.")
57
57
  }
58
58
 
59
59
  func init() {
60
- Register(unicornThrowNewError{})
60
+ Register(unicornThrowNewError{})
61
61
  }
@@ -20,20 +20,272 @@ func (noVar) Check(ctx *Context, node *shimast.Node) {
20
20
  return
21
21
  }
22
22
  if shimast.IsVar(stmt.DeclarationList) {
23
+ const message = "Unexpected var, use let or const instead."
23
24
  start := keywordStart(ctx.File, stmt.DeclarationList, "var")
24
- if start >= 0 {
25
+ if start >= 0 && isNoVarAutoFixSafe(ctx, node) {
25
26
  ctx.ReportRangeFix(
26
27
  start,
27
28
  start+len("var"),
28
- "Unexpected var, use let or const instead.",
29
+ message,
29
30
  TextEdit{Pos: start, End: start + len("var"), Text: "let"},
30
31
  )
31
32
  return
32
33
  }
33
- ctx.Report(node, "Unexpected var, use let or const instead.")
34
+ ctx.Report(node, message)
34
35
  }
35
36
  }
36
37
 
38
+ // isNoVarAutoFixSafe reports whether rewriting a `var` statement's keyword to
39
+ // `let` is safe using only AST-local information (no scope/data-flow engine).
40
+ // It mirrors the conservative posture of isEqeqeqAutoFixSafe: over-declining
41
+ // is fine, corrupting source is not. Blindly turning every `var` into `let`
42
+ // breaks two real shapes that `var` hoisting tolerates but `let` does not:
43
+ // - redeclaration (`var x=1; var x=2;`) → two `let x` is a SyntaxError;
44
+ // - use-before-declaration (a binding referenced above its own line) →
45
+ // `let` makes that reference a TDZ ReferenceError.
46
+ //
47
+ // Five corruption holes were patched piecemeal here before (var-vs-var,
48
+ // for-header var, function/class redeclaration, mixed destructuring sibling,
49
+ // object-literal shorthand, use-before-declaration). That whack-a-mole is
50
+ // replaced by one conservative rule with two preconditions; the fix is
51
+ // emitted only if BOTH hold:
52
+ //
53
+ // 1. Single binding in the whole file. The declared name is introduced by
54
+ // EXACTLY ONE binding position anywhere in the source — counting every
55
+ // binding-introducing slot of that identifier: variable declarations and
56
+ // destructuring leaves, function/class/enum/module declarations,
57
+ // parameters and catch bindings, and import bindings. More than one such
58
+ // position → decline. This single count subsumes every prior
59
+ // redeclaration arm (var-vs-var, var-vs-param, var-vs-function, mixed
60
+ // destructure siblings, for-header var, …). It over-declines harmless
61
+ // cross-scope same-name bindings, which never corrupts.
62
+ // 2. No use-before-declaration / TDZ. The declared name is not referenced as
63
+ // a VALUE before the statement's Pos(). A non-reference occurrence of the
64
+ // same text — a member name (`o.x`), an object-literal key (`{x:1}`), a
65
+ // statement label (`x:`), or a type reference (`: x`) — binds no value and
66
+ // must not force a decline; isValueReferenceIdentifier classifies these.
67
+ //
68
+ // The var statement being fixed must itself be a single plain identifier
69
+ // declarator so the keyword rewrite has a simple `let x` rename target; a
70
+ // destructuring var (`var {a}=o`) or a multi-binding list is declined here
71
+ // even though its names might each bind only once.
72
+ func isNoVarAutoFixSafe(ctx *Context, node *shimast.Node) bool {
73
+ if ctx == nil || ctx.File == nil {
74
+ return false
75
+ }
76
+ // Precondition: the var being fixed is a single plain identifier declarator.
77
+ // variableStatementBindingNames returns plain identifier names only, so a
78
+ // destructuring declarator yields zero names; requiring exactly one name AND
79
+ // exactly one VariableDeclaration node rejects both multi-binding lists and
80
+ // any destructured (or destructured-sibling) declarator.
81
+ names := variableStatementBindingNames(node)
82
+ if len(names) != 1 {
83
+ return false
84
+ }
85
+ if list := node.AsVariableStatement().DeclarationList.AsVariableDeclarationList(); list == nil ||
86
+ list.Declarations == nil || len(list.Declarations.Nodes) != 1 {
87
+ return false
88
+ }
89
+ target := names[0]
90
+
91
+ declPos := node.Pos()
92
+ // The single declarator's initializer subtree. A value reference to `target`
93
+ // inside this range is a self-reference that runs while `target` is still in
94
+ // its temporal dead zone under `let` (`var x = typeof x;`, `var x = x;`,
95
+ // `var x = (() => x)();`), so it must also force a decline even though its
96
+ // Pos() is AFTER the statement's start. initStart/initEnd are -1 when the
97
+ // declarator has no initializer, which disables the range check.
98
+ initStart, initEnd := -1, -1
99
+ if list := node.AsVariableStatement().DeclarationList.AsVariableDeclarationList(); list != nil &&
100
+ list.Declarations != nil && len(list.Declarations.Nodes) == 1 {
101
+ if decl := list.Declarations.Nodes[0].AsVariableDeclaration(); decl != nil && decl.Initializer != nil {
102
+ initStart, initEnd = decl.Initializer.Pos(), decl.Initializer.End()
103
+ }
104
+ }
105
+ bindingCount := 0
106
+ referencedBefore := false
107
+ walkDescendants(ctx.File.AsNode(), func(child *shimast.Node) {
108
+ // Binding count: every position that introduces the name `target` as a
109
+ // binding (a declaration), not a value reference. Two or more positions
110
+ // anywhere in the file decline the fix.
111
+ for _, name := range bindingNamesIntroducedBy(child) {
112
+ if name == target {
113
+ bindingCount++
114
+ }
115
+ }
116
+ // TDZ: a value reference to `target` turns into a ReferenceError under
117
+ // `let` when it executes while `target` is still in its temporal dead
118
+ // zone. Two cases decline:
119
+ // - a reference BEFORE the var's own position (`log(x); var x = 1;`);
120
+ // - a self-reference WITHIN the declarator's own initializer range
121
+ // (`var x = typeof x;`). Conservatively, any value reference inside
122
+ // the initializer declines — including a deferred read in a nested
123
+ // closure (`var f = () => f;`) that is actually safe — because the
124
+ // AST-local gate does not track whether that closure runs during
125
+ // initialization. Over-declining never corrupts source.
126
+ if child.Kind == shimast.KindIdentifier && identifierText(child) == target &&
127
+ isValueReferenceIdentifier(child) {
128
+ pos := child.Pos()
129
+ if pos < declPos || (initStart >= 0 && pos >= initStart && pos < initEnd) {
130
+ referencedBefore = true
131
+ }
132
+ }
133
+ })
134
+ if referencedBefore {
135
+ return false
136
+ }
137
+ return bindingCount == 1
138
+ }
139
+
140
+ // bindingNamesIntroducedBy returns every plain identifier name that `node`
141
+ // introduces as a binding in its OWN slot — never the names bound by its
142
+ // descendants, which the file-wide walk visits independently. The classifier
143
+ // is by AST kind and slot so a value reference, member name, object-literal
144
+ // key, label, or type reference of the same text is excluded; only genuine
145
+ // declarations contribute.
146
+ //
147
+ // A destructuring declarator (`var { a } = o`, `function f([a]) {}`) is NOT
148
+ // flattened here: its leaf names belong to the BindingElement descendants,
149
+ // which the walk visits on their own, so each leaf is counted exactly once at
150
+ // its own position. Declaration nodes therefore contribute only when their
151
+ // own name slot is a plain identifier.
152
+ //
153
+ // Returns nil for any node that introduces no binding in its own slot. Type
154
+ // aliases and interfaces are intentionally absent: they live in the type
155
+ // namespace and merge with a same-name value binding without a `let`
156
+ // duplicate-declaration error.
157
+ func bindingNamesIntroducedBy(node *shimast.Node) []string {
158
+ if node == nil {
159
+ return nil
160
+ }
161
+ switch node.Kind {
162
+ case shimast.KindVariableDeclaration:
163
+ if decl := node.AsVariableDeclaration(); decl != nil {
164
+ if name := identifierText(decl.Name()); name != "" {
165
+ return []string{name}
166
+ }
167
+ }
168
+ case shimast.KindParameter:
169
+ if decl := node.AsParameterDeclaration(); decl != nil {
170
+ if name := identifierText(decl.Name()); name != "" {
171
+ return []string{name}
172
+ }
173
+ }
174
+ case shimast.KindBindingElement:
175
+ // A leaf of a destructuring pattern (`{ a }`, `[a]`, `{ k: a }`,
176
+ // `...rest`). Only the element's own bound name counts; nested patterns
177
+ // are their own BindingElement descendants, and the default-value
178
+ // initializer is a value reference, not a binding.
179
+ if elem := node.AsBindingElement(); elem != nil {
180
+ if name := identifierText(elem.Name()); name != "" {
181
+ return []string{name}
182
+ }
183
+ }
184
+ case shimast.KindFunctionDeclaration:
185
+ if decl := node.AsFunctionDeclaration(); decl != nil && decl.Body != nil {
186
+ if name := identifierText(decl.Name()); name != "" {
187
+ return []string{name}
188
+ }
189
+ }
190
+ case shimast.KindClassDeclaration:
191
+ if name := identifierText(node.Name()); name != "" {
192
+ return []string{name}
193
+ }
194
+ case shimast.KindEnumDeclaration, shimast.KindModuleDeclaration:
195
+ if name := identifierText(node.Name()); name != "" {
196
+ return []string{name}
197
+ }
198
+ case shimast.KindCatchClause:
199
+ // `catch (e)` — the catch binding. A destructured catch binding
200
+ // (`catch ({ e })`) has its leaves counted via the BindingElement
201
+ // descendants, so only a plain identifier binding counts here.
202
+ if catch := node.AsCatchClause(); catch != nil && catch.VariableDeclaration != nil {
203
+ if name := identifierText(catch.VariableDeclaration.Name()); name != "" {
204
+ return []string{name}
205
+ }
206
+ }
207
+ case shimast.KindImportClause:
208
+ // `import foo from "m"` — the default import binding. Named and
209
+ // namespace bindings are their own ImportSpecifier / NamespaceImport
210
+ // descendants, visited separately.
211
+ if name := identifierText(node.Name()); name != "" {
212
+ return []string{name}
213
+ }
214
+ case shimast.KindNamespaceImport:
215
+ // `import * as ns from "m"`.
216
+ if name := identifierText(node.Name()); name != "" {
217
+ return []string{name}
218
+ }
219
+ case shimast.KindImportSpecifier:
220
+ // `import { a } from "m"` / `import { a as b } from "m"` — the local
221
+ // binding is the specifier's Name(), not the PropertyName.
222
+ if name := identifierText(node.Name()); name != "" {
223
+ return []string{name}
224
+ }
225
+ case shimast.KindImportEqualsDeclaration:
226
+ // `import x = require("m")` / `import x = A.B`.
227
+ if name := identifierText(node.Name()); name != "" {
228
+ return []string{name}
229
+ }
230
+ }
231
+ return nil
232
+ }
233
+
234
+ // isValueReferenceIdentifier reports whether an Identifier node occupies a
235
+ // value-reference position rather than a non-reference role that merely
236
+ // reuses the same text. The use-before-declaration gate in
237
+ // isNoVarAutoFixSafe matches identifiers by text alone, so it would
238
+ // otherwise decline on positions that bind no value:
239
+ //
240
+ // - the `name` of a property access (`o.x`) or qualified name (`A.x`);
241
+ // - an object-literal property key (`{ x: 1 }`) or shorthand key;
242
+ // - a statement label (`x:` / `break x`);
243
+ // - a type reference (`: x`) whose `TypeName` is the identifier.
244
+ //
245
+ // Classification is by the identifier's parent node kind and slot, never
246
+ // by text. Any unrecognized parent is treated as a value reference
247
+ // (safety first: an unclassified position keeps declining).
248
+ func isValueReferenceIdentifier(node *shimast.Node) bool {
249
+ parent := node.Parent
250
+ if parent == nil {
251
+ return true
252
+ }
253
+ switch parent.Kind {
254
+ case shimast.KindPropertyAccessExpression:
255
+ // `o.x`: only the object expression is a reference; the member name
256
+ // is a property, not a binding.
257
+ access := parent.AsPropertyAccessExpression()
258
+ return access == nil || access.Name() != node
259
+ case shimast.KindQualifiedName:
260
+ // `A.x` in type position: the right side is a property name.
261
+ qn := parent.AsQualifiedName()
262
+ return qn == nil || qn.Right != node
263
+ case shimast.KindPropertyAssignment:
264
+ // `{ x: target }`: the key is not a reference; the value is.
265
+ assign := parent.AsPropertyAssignment()
266
+ return assign == nil || assign.Name() != node
267
+ // `{ x }`: an object-literal shorthand is a VALUE READ of binding `x`
268
+ // (object destructuring parses as KindBindingElement and is handled
269
+ // elsewhere). It falls through to the default `true` so the
270
+ // use-before-declaration gate sees the forward reference and declines.
271
+ case shimast.KindLabeledStatement:
272
+ // `x:` label — a statement label shares no namespace with values.
273
+ lbl := parent.AsLabeledStatement()
274
+ return lbl == nil || lbl.Label != node
275
+ case shimast.KindBreakStatement:
276
+ brk := parent.AsBreakStatement()
277
+ return brk == nil || brk.Label != node
278
+ case shimast.KindContinueStatement:
279
+ cont := parent.AsContinueStatement()
280
+ return cont == nil || cont.Label != node
281
+ case shimast.KindTypeReference:
282
+ // `: x` — a type reference lives in the type namespace.
283
+ ref := parent.AsTypeReferenceNode()
284
+ return ref == nil || ref.TypeName != node
285
+ }
286
+ return true
287
+ }
288
+
37
289
  // preferConst: flag `let` declarations whose binding is never reassigned.
38
290
  // This follows ESLint's core rule for the common AST-local cases. It is
39
291
  // intentionally conservative: destructuring and declaration-only `let`
@@ -100,6 +352,24 @@ func (preferConst) Check(ctx *Context, node *shimast.Node) {
100
352
  assigned[name] = true
101
353
  }
102
354
  }
355
+ case shimast.KindForOfStatement, shimast.KindForInStatement:
356
+ // `for (x of …)` / `for (x in …)` reassigns the existing binding `x`
357
+ // on every iteration. When the initializer IS a
358
+ // VariableDeclarationList (`for (const y of …)`) it declares a fresh
359
+ // binding instead, so only a non-declaration initializer counts as a
360
+ // reassignment target. Missing this lets a pre-existing `let` be
361
+ // rewritten to `const` that the loop then assigns to — a TS error and
362
+ // runtime TypeError.
363
+ stmt := child.AsForInOrOfStatement()
364
+ if stmt == nil || stmt.Initializer == nil {
365
+ return
366
+ }
367
+ if stmt.Initializer.Kind == shimast.KindVariableDeclarationList {
368
+ return
369
+ }
370
+ for _, name := range assignmentTargetNames(stmt.Initializer) {
371
+ assigned[name] = true
372
+ }
103
373
  }
104
374
  })
105
375
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttsc/lint",
3
- "version": "0.14.0-dev.20260529.2",
3
+ "version": "0.14.0",
4
4
  "description": "Reference ttsc plugin: ESLint-style lint rules hosted in the same Program/Checker as the type-check pass.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -33,10 +33,10 @@
33
33
  "src"
34
34
  ],
35
35
  "devDependencies": {
36
- "@typescript/native-preview": "7.0.0-dev.20260527.2",
36
+ "@typescript/native-preview": "7.0.0-dev.20260519.1",
37
37
  "@types/node": "^25.3.0",
38
38
  "rimraf": "^6.1.2",
39
- "ttsc": "0.14.0-dev.20260529.2"
39
+ "ttsc": "0.14.0"
40
40
  },
41
41
  "repository": {
42
42
  "type": "git",
@@ -1,14 +1,15 @@
1
- import type { ITtscLintFormat } from "./structures/ITtscLintFormat";
1
+ import type { ITtscLintFormat } from "./structures/format/ITtscLintFormat";
2
2
 
3
3
  /**
4
4
  * Documented defaults for the `format` block's _always-on_ rules
5
- * (`format/semi`, `format/quotes`, `format/trailing-comma`,
5
+ * (`format/semi`, `format/quotes`, `format/arrow-parens`,
6
+ * `format/bracket-spacing`, `format/quote-props`, `format/trailing-comma`,
6
7
  * `format/print-width`).
7
8
  *
8
9
  * Exported so users can spread defaults next to overrides:
9
10
  *
10
11
  * ```ts
11
- * import { defaultFormat, type ITtscLintConfig } from "@ttsc/lint";
12
+ * import { type ITtscLintConfig, defaultFormat } from "@ttsc/lint";
12
13
  *
13
14
  * export default {
14
15
  * format: { ...defaultFormat, printWidth: 100 },
@@ -18,15 +19,18 @@ import type { ITtscLintFormat } from "./structures/ITtscLintFormat";
18
19
  * The values mirror Prettier 1:1 except for the documented `endOfLine`
19
20
  * narrowing (no `"cr"` / `"auto"`).
20
21
  *
21
- * Notably absent: `importOrder` and `jsdoc`. `format/sort-imports` and
22
- * `format/jsdoc` are opt-in by setting their corresponding fields; this
23
- * const documents only the rules that turn on unconditionally with a
24
- * non-empty `format` block the Go host owns runtime activation.
22
+ * Notably absent: `sortImports`. Import sorting is opt-in by setting
23
+ * `sortImports`; JSDoc normalization is always on (set `jsDoc: false` to opt
24
+ * out). This const documents only the keys that turn on unconditionally with a
25
+ * non-empty `format` block; the Go host owns runtime activation.
25
26
  */
26
27
  export const defaultFormat = Object.freeze({
27
28
  severity: "off",
28
29
  semi: true,
29
30
  singleQuote: false,
31
+ arrowParens: "always",
32
+ bracketSpacing: true,
33
+ quoteProps: "as-needed",
30
34
  trailingComma: "all",
31
35
  printWidth: 80,
32
36
  tabWidth: 2,
@@ -1,5 +1,5 @@
1
- import type { ITtscLintFormat } from "./ITtscLintFormat";
2
1
  import type { ITtscLintPlugin } from "./ITtscLintPlugin";
2
+ import type { ITtscLintFormat } from "./format/ITtscLintFormat";
3
3
  import type { ITtscLintRules } from "./rules/ITtscLintRules";
4
4
 
5
5
  /**
@@ -22,8 +22,8 @@ export interface ITtscLintConfig {
22
22
  */
23
23
  extends?: string;
24
24
 
25
- /** Contributor plugin objects keyed by namespace. */
26
- plugins?: Record<string, ITtscLintPlugin>;
25
+ /** Prettier-style flat configuration for the format rules. */
26
+ format?: ITtscLintFormat;
27
27
 
28
28
  /**
29
29
  * Kebab-case built-in rule severities plus namespaced contributor rules.
@@ -34,6 +34,6 @@ export interface ITtscLintConfig {
34
34
  */
35
35
  rules?: ITtscLintRules;
36
36
 
37
- /** Prettier-style flat configuration for the format rules. */
38
- format?: ITtscLintFormat;
37
+ /** Contributor plugin objects keyed by namespace. */
38
+ plugins?: Record<string, ITtscLintPlugin>;
39
39
  }
@@ -6,12 +6,12 @@ import type { TtscLintSeverity } from "./TtscLintSeverity";
6
6
  *
7
7
  * A rule may be configured either as a bare severity string (`"error"`,
8
8
  * `"warning"`, `"off"`) or as a single-element tuple containing the same
9
- * severity. Both forms are equivalent at runtime; the tuple form exists so
10
- * that severity-only rules and options-bearing rules look uniform when read
9
+ * severity. Both forms are equivalent at runtime; the tuple form exists so that
10
+ * severity-only rules and options-bearing rules look uniform when read
11
11
  * top-to-bottom in a `ttsc.lint.config.ts` file.
12
12
  *
13
- * Use {@link TtscLintRuleOptionsSetting} when the rule accepts a typed
14
- * options object.
13
+ * Use {@link TtscLintRuleOptionsSetting} when the rule accepts a typed options
14
+ * object.
15
15
  *
16
16
  * @example
17
17
  * const config: ITtscLintConfig = {
@@ -30,25 +30,25 @@ export type TtscLintRuleSetting =
30
30
  * Per-rule severity-plus-options setting for rules that accept a typed options
31
31
  * object.
32
32
  *
33
- * This is the tuple form ESLint users know — `[severity, options]` —
34
- * kept strongly typed by way of the rule's dedicated options interface
35
- * (see `TtscLintRuleOptions.ts`). The bare {@link TtscLintRuleSetting}
36
- * forms remain accepted; omitting the options object means "use the
37
- * rule's default options".
38
- *
39
- * @typeParam TOptions - The rule's options shape. Each rule supplies its
40
- * own interface from `TtscLintRuleOptions.ts` (for example
41
- * `ITtscLintBoundariesElementTypesRuleOptions`).
33
+ * This is the tuple form ESLint users know — `[severity, options]` — kept
34
+ * strongly typed by way of the rule's dedicated options interface (see
35
+ * `TtscLintRuleOptions.ts`). The bare {@link TtscLintRuleSetting} forms remain
36
+ * accepted; omitting the options object means "use the rule's default
37
+ * options".
42
38
  *
43
39
  * @example
44
40
  * const config: ITtscLintConfig = {
45
- * rules: {
46
- * "boundaries/element-types": [
47
- * "error",
48
- * { default: "disallow", rules: [...] },
49
- * ],
50
- * },
41
+ * rules: {
42
+ * "boundaries/element-types": [
43
+ * "error",
44
+ * { default: "disallow", rules: [...] },
45
+ * ],
46
+ * },
51
47
  * };
48
+ *
49
+ * @typeParam TOptions - The rule's options shape. Each rule supplies its own
50
+ * interface from `TtscLintRuleOptions.ts` (for example
51
+ * `ITtscLintBoundariesElementTypesRuleOptions`).
52
52
  */
53
53
  export type TtscLintRuleOptionsSetting<TOptions> =
54
54
  | TtscLintRuleSetting