@ttsc/lint 0.13.0 → 0.14.0-dev.20250530.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (498) hide show
  1. package/README.md +955 -85
  2. package/lib/defaultFormat.d.ts +15 -8
  3. package/lib/defaultFormat.js +15 -8
  4. package/lib/defaultFormat.js.map +1 -1
  5. package/lib/index.d.ts +46 -0
  6. package/lib/index.js +60 -37
  7. package/lib/index.js.map +1 -1
  8. package/lib/structures/ITtscLintConfig.d.ts +12 -6
  9. package/lib/structures/TtscLintRuleSetting.d.ts +49 -0
  10. package/lib/structures/{TtscLintRuleOptions.js → TtscLintRuleSetting.js} +1 -1
  11. package/lib/structures/TtscLintRuleSetting.js.map +1 -0
  12. package/lib/structures/format/ITtscLintFormat.d.ts +128 -0
  13. package/lib/structures/{TtscLintRuleMap.js → format/ITtscLintFormat.js} +1 -1
  14. package/lib/structures/format/ITtscLintFormat.js.map +1 -0
  15. package/lib/structures/format/ITtscLintFormatJsDoc.d.ts +17 -0
  16. package/lib/structures/{ITtscLintFormatConfig.js → format/ITtscLintFormatJsDoc.js} +1 -1
  17. package/lib/structures/format/ITtscLintFormatJsDoc.js.map +1 -0
  18. package/lib/structures/format/ITtscLintFormatSortImports.d.ts +54 -0
  19. package/lib/structures/format/ITtscLintFormatSortImports.js +3 -0
  20. package/lib/structures/format/ITtscLintFormatSortImports.js.map +1 -0
  21. package/lib/structures/format/index.d.ts +3 -0
  22. package/lib/structures/format/index.js +20 -0
  23. package/lib/structures/format/index.js.map +1 -0
  24. package/lib/structures/index.d.ts +3 -4
  25. package/lib/structures/index.js +3 -4
  26. package/lib/structures/index.js.map +1 -1
  27. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +95 -0
  28. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +13 -0
  29. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
  30. package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +75 -0
  31. package/lib/structures/rules/ITtscLintBoundariesRules.js +3 -0
  32. package/lib/structures/rules/ITtscLintBoundariesRules.js.map +1 -0
  33. package/lib/structures/rules/ITtscLintContributorRules.d.ts +16 -0
  34. package/lib/structures/rules/ITtscLintContributorRules.js +3 -0
  35. package/lib/structures/rules/ITtscLintContributorRules.js.map +1 -0
  36. package/lib/structures/rules/ITtscLintCoreRules.d.ts +1229 -0
  37. package/lib/structures/rules/ITtscLintCoreRules.js +3 -0
  38. package/lib/structures/rules/ITtscLintCoreRules.js.map +1 -0
  39. package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +17 -0
  40. package/lib/structures/rules/ITtscLintCypressRuleOptions.js +10 -0
  41. package/lib/structures/rules/ITtscLintCypressRuleOptions.js.map +1 -0
  42. package/lib/structures/rules/ITtscLintCypressRules.d.ts +125 -0
  43. package/lib/structures/rules/ITtscLintCypressRules.js +3 -0
  44. package/lib/structures/rules/ITtscLintCypressRules.js.map +1 -0
  45. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +154 -0
  46. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +13 -0
  47. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js.map +1 -0
  48. package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +162 -0
  49. package/lib/structures/rules/ITtscLintFunctionalRules.js +3 -0
  50. package/lib/structures/rules/ITtscLintFunctionalRules.js.map +1 -0
  51. package/lib/structures/rules/ITtscLintJestRules.d.ts +190 -0
  52. package/lib/structures/rules/ITtscLintJestRules.js +3 -0
  53. package/lib/structures/rules/ITtscLintJestRules.js.map +1 -0
  54. package/lib/structures/rules/ITtscLintJsdocRules.d.ts +133 -0
  55. package/lib/structures/rules/ITtscLintJsdocRules.js +3 -0
  56. package/lib/structures/rules/ITtscLintJsdocRules.js.map +1 -0
  57. package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +294 -0
  58. package/lib/structures/rules/ITtscLintJsxA11yRules.js +3 -0
  59. package/lib/structures/rules/ITtscLintJsxA11yRules.js.map +1 -0
  60. package/lib/structures/rules/ITtscLintNextjsRules.d.ts +180 -0
  61. package/lib/structures/rules/ITtscLintNextjsRules.js +3 -0
  62. package/lib/structures/rules/ITtscLintNextjsRules.js.map +1 -0
  63. package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +312 -0
  64. package/lib/structures/rules/ITtscLintPlaywrightRules.js +3 -0
  65. package/lib/structures/rules/ITtscLintPlaywrightRules.js.map +1 -0
  66. package/lib/structures/rules/ITtscLintPromiseRules.d.ts +179 -0
  67. package/lib/structures/rules/ITtscLintPromiseRules.js +3 -0
  68. package/lib/structures/rules/ITtscLintPromiseRules.js.map +1 -0
  69. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +18 -0
  70. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js +8 -0
  71. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js.map +1 -0
  72. package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +49 -0
  73. package/lib/structures/rules/ITtscLintReactPerfRules.js +3 -0
  74. package/lib/structures/rules/ITtscLintReactPerfRules.js.map +1 -0
  75. package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +37 -0
  76. package/lib/structures/rules/ITtscLintReactRuleOptions.js +11 -0
  77. package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
  78. package/lib/structures/rules/ITtscLintReactRules.d.ts +276 -0
  79. package/lib/structures/rules/ITtscLintReactRules.js +3 -0
  80. package/lib/structures/rules/ITtscLintReactRules.js.map +1 -0
  81. package/lib/structures/rules/ITtscLintRegexpRules.d.ts +182 -0
  82. package/lib/structures/rules/ITtscLintRegexpRules.js +3 -0
  83. package/lib/structures/rules/ITtscLintRegexpRules.js.map +1 -0
  84. package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +65 -0
  85. package/lib/structures/rules/ITtscLintRuleOptionsMap.js +3 -0
  86. package/lib/structures/rules/ITtscLintRuleOptionsMap.js.map +1 -0
  87. package/lib/structures/rules/ITtscLintRules.d.ts +55 -0
  88. package/lib/structures/{TtscLintRule.js → rules/ITtscLintRules.js} +1 -1
  89. package/lib/structures/rules/ITtscLintRules.js.map +1 -0
  90. package/lib/structures/rules/ITtscLintSecurityRules.d.ts +141 -0
  91. package/lib/structures/rules/ITtscLintSecurityRules.js +3 -0
  92. package/lib/structures/rules/ITtscLintSecurityRules.js.map +1 -0
  93. package/lib/structures/rules/ITtscLintSolidRules.d.ts +178 -0
  94. package/lib/structures/rules/ITtscLintSolidRules.js +3 -0
  95. package/lib/structures/rules/ITtscLintSolidRules.js.map +1 -0
  96. package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +20 -0
  97. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js +9 -0
  98. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js.map +1 -0
  99. package/lib/structures/rules/ITtscLintStorybookRules.d.ts +165 -0
  100. package/lib/structures/rules/ITtscLintStorybookRules.js +3 -0
  101. package/lib/structures/rules/ITtscLintStorybookRules.js.map +1 -0
  102. package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +88 -0
  103. package/lib/structures/rules/ITtscLintTanstackQueryRules.js +3 -0
  104. package/lib/structures/rules/ITtscLintTanstackQueryRules.js.map +1 -0
  105. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +21 -0
  106. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js +10 -0
  107. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js.map +1 -0
  108. package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +293 -0
  109. package/lib/structures/rules/ITtscLintTestingLibraryRules.js +3 -0
  110. package/lib/structures/rules/ITtscLintTestingLibraryRules.js.map +1 -0
  111. package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +1074 -0
  112. package/lib/structures/rules/ITtscLintTypeScriptRules.js +3 -0
  113. package/lib/structures/rules/ITtscLintTypeScriptRules.js.map +1 -0
  114. package/lib/structures/rules/ITtscLintUnicornRules.d.ts +997 -0
  115. package/lib/structures/rules/ITtscLintUnicornRules.js +3 -0
  116. package/lib/structures/rules/ITtscLintUnicornRules.js.map +1 -0
  117. package/lib/structures/rules/ITtscLintVitestRules.d.ts +133 -0
  118. package/lib/structures/rules/ITtscLintVitestRules.js +3 -0
  119. package/lib/structures/rules/ITtscLintVitestRules.js.map +1 -0
  120. package/lib/structures/rules/index.d.ts +31 -0
  121. package/lib/structures/rules/index.js +48 -0
  122. package/lib/structures/rules/index.js.map +1 -0
  123. package/linthost/ast_helpers.go +30 -5
  124. package/linthost/compile.go +33 -2
  125. package/linthost/config.go +118 -71
  126. package/linthost/config_format.go +270 -104
  127. package/linthost/directives.go +67 -25
  128. package/linthost/dispatch.go +14 -3
  129. package/linthost/engine.go +160 -40
  130. package/linthost/fix.go +10 -3
  131. package/linthost/flags_gen.go +17 -15
  132. package/linthost/format.go +222 -25
  133. package/linthost/format_editor_settings.go +262 -0
  134. package/linthost/host.go +40 -3
  135. package/linthost/lsp.go +898 -0
  136. package/linthost/print_dispatch.go +5 -2
  137. package/linthost/print_engine.go +5 -5
  138. package/linthost/print_nodes_call.go +149 -67
  139. package/linthost/print_nodes_function.go +27 -2
  140. package/linthost/print_nodes_list.go +40 -5
  141. package/linthost/print_nodes_object.go +1 -1
  142. package/linthost/print_nodes_ternary.go +86 -0
  143. package/linthost/rule_names.go +14 -0
  144. package/linthost/rules_arrays.go +2 -2
  145. package/linthost/rules_boundaries.go +532 -0
  146. package/linthost/rules_camelcase.go +133 -0
  147. package/linthost/rules_complexity.go +95 -0
  148. package/linthost/rules_consistent_return.go +130 -0
  149. package/linthost/rules_console.go +1 -1
  150. package/linthost/rules_core_extra.go +739 -0
  151. package/linthost/rules_curly.go +70 -0
  152. package/linthost/rules_cypress.go +608 -0
  153. package/linthost/rules_debugger.go +2 -2
  154. package/linthost/rules_default_case.go +39 -0
  155. package/linthost/rules_default_case_last.go +46 -0
  156. package/linthost/rules_dupes.go +3 -3
  157. package/linthost/rules_empty.go +3 -3
  158. package/linthost/rules_escape.go +44 -24
  159. package/linthost/rules_eval.go +2 -2
  160. package/linthost/rules_finally.go +2 -2
  161. package/linthost/rules_format_arrow_parens.go +167 -0
  162. package/linthost/rules_format_bracket_spacing.go +117 -0
  163. package/linthost/rules_format_clause_join.go +172 -0
  164. package/linthost/rules_format_declaration_header.go +595 -0
  165. package/linthost/rules_format_indent.go +372 -0
  166. package/linthost/rules_format_jsdoc.go +5 -5
  167. package/linthost/rules_format_orphan_semi.go +106 -0
  168. package/linthost/rules_format_parameter_properties.go +175 -0
  169. package/linthost/rules_format_print_width.go +66 -55
  170. package/linthost/rules_format_quote_props.go +169 -0
  171. package/linthost/rules_format_quotes.go +76 -30
  172. package/linthost/rules_format_semi.go +186 -11
  173. package/linthost/rules_format_sort_imports.go +437 -118
  174. package/linthost/rules_format_statement_split.go +343 -0
  175. package/linthost/rules_format_ternary_nullish_parens.go +77 -0
  176. package/linthost/rules_format_trailing_comma.go +22 -3
  177. package/linthost/rules_format_whitespace.go +336 -0
  178. package/linthost/rules_functional.go +967 -0
  179. package/linthost/rules_gap.go +24 -45
  180. package/linthost/rules_grouped_accessor_pairs.go +87 -0
  181. package/linthost/rules_guard_for_in.go +198 -0
  182. package/linthost/rules_id_length.go +77 -0
  183. package/linthost/rules_imports.go +70 -2
  184. package/linthost/rules_init_declarations.go +53 -0
  185. package/linthost/rules_jest.go +618 -0
  186. package/linthost/rules_jsdoc.go +502 -0
  187. package/linthost/rules_jsx_a11y.go +1264 -0
  188. package/linthost/rules_logic.go +12 -12
  189. package/linthost/rules_loops.go +1 -1
  190. package/linthost/rules_max_classes_per_file.go +58 -0
  191. package/linthost/rules_max_depth.go +83 -0
  192. package/linthost/rules_max_lines.go +101 -0
  193. package/linthost/rules_max_lines_per_function.go +57 -0
  194. package/linthost/rules_max_nested_callbacks.go +61 -0
  195. package/linthost/rules_max_params.go +49 -0
  196. package/linthost/rules_max_statements.go +59 -0
  197. package/linthost/rules_misc.go +1 -1
  198. package/linthost/rules_nextjs.go +697 -0
  199. package/linthost/rules_no_else_return.go +75 -0
  200. package/linthost/rules_no_empty_named_blocks.go +91 -0
  201. package/linthost/rules_no_extend_native.go +51 -0
  202. package/linthost/rules_no_import_assign.go +140 -0
  203. package/linthost/rules_no_invalid_this.go +52 -0
  204. package/linthost/rules_no_loop_func.go +85 -0
  205. package/linthost/rules_no_magic_numbers.go +123 -0
  206. package/linthost/rules_no_mixed_operators.go +80 -0
  207. package/linthost/rules_no_param_reassign.go +98 -0
  208. package/linthost/rules_no_redeclare.go +270 -0
  209. package/linthost/rules_no_restricted_imports.go +105 -0
  210. package/linthost/rules_no_restricted_syntax.go +49 -0
  211. package/linthost/rules_no_shadow.go +147 -0
  212. package/linthost/rules_no_unreachable.go +77 -0
  213. package/linthost/rules_no_useless_assignment.go +120 -0
  214. package/linthost/rules_no_useless_constructor.go +245 -0
  215. package/linthost/rules_no_useless_return.go +51 -0
  216. package/linthost/rules_params.go +1 -1
  217. package/linthost/rules_playwright.go +788 -0
  218. package/linthost/rules_prefer_arrow_callback.go +124 -0
  219. package/linthost/rules_prefer_destructuring.go +98 -0
  220. package/linthost/rules_prefer_named_capture_group.go +129 -0
  221. package/linthost/rules_prefer_rest_params.go +94 -0
  222. package/linthost/rules_problems.go +41 -30
  223. package/linthost/rules_promise.go +1057 -2
  224. package/linthost/rules_protos.go +2 -2
  225. package/linthost/rules_react.go +773 -0
  226. package/linthost/rules_react_extras.go +227 -0
  227. package/linthost/rules_react_hooks.go +848 -0
  228. package/linthost/rules_react_perf.go +293 -0
  229. package/linthost/rules_react_refresh.go +583 -0
  230. package/linthost/rules_regexp.go +410 -0
  231. package/linthost/rules_security.go +830 -0
  232. package/linthost/rules_self.go +2 -2
  233. package/linthost/rules_solid.go +1073 -0
  234. package/linthost/rules_sort_imports.go +69 -0
  235. package/linthost/rules_sort_keys.go +134 -0
  236. package/linthost/rules_storybook.go +1176 -0
  237. package/linthost/rules_strings.go +4 -4
  238. package/linthost/rules_suggestions.go +38 -38
  239. package/linthost/rules_tanstack_query.go +844 -0
  240. package/linthost/rules_testing_library.go +1204 -0
  241. package/linthost/rules_throw.go +1 -1
  242. package/linthost/rules_ts.go +19 -19
  243. package/linthost/rules_ts_async.go +399 -0
  244. package/linthost/rules_ts_class_literal_property_style.go +115 -0
  245. package/linthost/rules_ts_consistent_type_exports.go +256 -0
  246. package/linthost/rules_ts_explicit_function_return_type.go +67 -0
  247. package/linthost/rules_ts_extra.go +159 -36
  248. package/linthost/rules_ts_no_base_to_string.go +218 -0
  249. package/linthost/rules_ts_no_confusing_void.go +72 -0
  250. package/linthost/rules_ts_no_deprecated.go +195 -0
  251. package/linthost/rules_ts_no_for_in_array.go +84 -0
  252. package/linthost/rules_ts_no_magic_numbers.go +124 -0
  253. package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
  254. package/linthost/rules_ts_no_misused_spread.go +104 -0
  255. package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
  256. package/linthost/rules_ts_no_restricted_types.go +62 -0
  257. package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
  258. package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
  259. package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
  260. package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
  261. package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
  262. package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
  263. package/linthost/rules_ts_no_unsafe_argument.go +82 -0
  264. package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
  265. package/linthost/rules_ts_no_unsafe_call.go +82 -0
  266. package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
  267. package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
  268. package/linthost/rules_ts_no_unsafe_return.go +126 -0
  269. package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
  270. package/linthost/rules_ts_no_useless_constructor.go +52 -0
  271. package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
  272. package/linthost/rules_ts_parameter_properties.go +38 -0
  273. package/linthost/rules_ts_prefer_find.go +178 -0
  274. package/linthost/rules_ts_prefer_includes.go +255 -0
  275. package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
  276. package/linthost/rules_ts_prefer_optional_chain.go +228 -0
  277. package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
  278. package/linthost/rules_ts_prefer_readonly.go +73 -0
  279. package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
  280. package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
  281. package/linthost/rules_ts_prefer_return_this_type.go +135 -0
  282. package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
  283. package/linthost/rules_ts_promise_function_async.go +77 -0
  284. package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
  285. package/linthost/rules_ts_require_array_sort_compare.go +96 -0
  286. package/linthost/rules_ts_restrict_plus_operands.go +127 -0
  287. package/linthost/rules_ts_restrict_template_expressions.go +95 -0
  288. package/linthost/rules_ts_simple.go +387 -0
  289. package/linthost/rules_ts_sort_type_constituents.go +144 -0
  290. package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
  291. package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
  292. package/linthost/rules_ts_unbound_method.go +126 -0
  293. package/linthost/rules_tsdoc.go +136 -0
  294. package/linthost/rules_unicorn_better_regex.go +27 -0
  295. package/linthost/rules_unicorn_catch_error_name.go +46 -0
  296. package/linthost/rules_unicorn_consistent_assert.go +47 -0
  297. package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
  298. package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
  299. package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
  300. package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
  301. package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
  302. package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
  303. package/linthost/rules_unicorn_custom_error_definition.go +138 -0
  304. package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
  305. package/linthost/rules_unicorn_error_message.go +64 -0
  306. package/linthost/rules_unicorn_escape_case.go +51 -0
  307. package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
  308. package/linthost/rules_unicorn_explicit_length_check.go +88 -0
  309. package/linthost/rules_unicorn_filename_case.go +29 -0
  310. package/linthost/rules_unicorn_import_style.go +28 -0
  311. package/linthost/rules_unicorn_isolated_functions.go +29 -0
  312. package/linthost/rules_unicorn_new_for_builtins.go +87 -0
  313. package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
  314. package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
  315. package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
  316. package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
  317. package/linthost/rules_unicorn_no_array_for_each.go +40 -0
  318. package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
  319. package/linthost/rules_unicorn_no_array_reduce.go +41 -0
  320. package/linthost/rules_unicorn_no_array_reverse.go +44 -0
  321. package/linthost/rules_unicorn_no_array_sort.go +43 -0
  322. package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
  323. package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
  324. package/linthost/rules_unicorn_no_console_spaces.go +61 -0
  325. package/linthost/rules_unicorn_no_document_cookie.go +41 -0
  326. package/linthost/rules_unicorn_no_empty_file.go +44 -0
  327. package/linthost/rules_unicorn_no_for_loop.go +102 -0
  328. package/linthost/rules_unicorn_no_hex_escape.go +42 -0
  329. package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
  330. package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
  331. package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
  332. package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
  333. package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
  334. package/linthost/rules_unicorn_no_lonely_if.go +44 -0
  335. package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
  336. package/linthost/rules_unicorn_no_named_default.go +54 -0
  337. package/linthost/rules_unicorn_no_negated_condition.go +85 -0
  338. package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
  339. package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
  340. package/linthost/rules_unicorn_no_new_array.go +30 -0
  341. package/linthost/rules_unicorn_no_new_buffer.go +31 -0
  342. package/linthost/rules_unicorn_no_null.go +24 -0
  343. package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
  344. package/linthost/rules_unicorn_no_process_exit.go +43 -0
  345. package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
  346. package/linthost/rules_unicorn_no_static_only_class.go +56 -0
  347. package/linthost/rules_unicorn_no_thenable.go +74 -0
  348. package/linthost/rules_unicorn_no_this_assignment.go +35 -0
  349. package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
  350. package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
  351. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
  352. package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
  353. package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
  354. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
  355. package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
  356. package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
  357. package/linthost/rules_unicorn_no_unused_properties.go +30 -0
  358. package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
  359. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
  360. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
  361. package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
  362. package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
  363. package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
  364. package/linthost/rules_unicorn_no_useless_spread.go +67 -0
  365. package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
  366. package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
  367. package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
  368. package/linthost/rules_unicorn_number_literal_case.go +69 -0
  369. package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
  370. package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
  371. package/linthost/rules_unicorn_prefer_array_find.go +51 -0
  372. package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
  373. package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
  374. package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
  375. package/linthost/rules_unicorn_prefer_array_some.go +67 -0
  376. package/linthost/rules_unicorn_prefer_at.go +77 -0
  377. package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
  378. package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
  379. package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
  380. package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
  381. package/linthost/rules_unicorn_prefer_code_point.go +49 -0
  382. package/linthost/rules_unicorn_prefer_date_now.go +78 -0
  383. package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
  384. package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
  385. package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
  386. package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
  387. package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
  388. package/linthost/rules_unicorn_prefer_event_target.go +36 -0
  389. package/linthost/rules_unicorn_prefer_export_from.go +129 -0
  390. package/linthost/rules_unicorn_prefer_global_this.go +127 -0
  391. package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
  392. package/linthost/rules_unicorn_prefer_includes.go +149 -0
  393. package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
  394. package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
  395. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
  396. package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
  397. package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
  398. package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
  399. package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
  400. package/linthost/rules_unicorn_prefer_module.go +50 -0
  401. package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
  402. package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
  403. package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
  404. package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
  405. package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
  406. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
  407. package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
  408. package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
  409. package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
  410. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
  411. package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
  412. package/linthost/rules_unicorn_prefer_set_has.go +42 -0
  413. package/linthost/rules_unicorn_prefer_set_size.go +48 -0
  414. package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
  415. package/linthost/rules_unicorn_prefer_single_call.go +96 -0
  416. package/linthost/rules_unicorn_prefer_spread.go +51 -0
  417. package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
  418. package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
  419. package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
  420. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
  421. package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
  422. package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
  423. package/linthost/rules_unicorn_prefer_switch.go +103 -0
  424. package/linthost/rules_unicorn_prefer_ternary.go +71 -0
  425. package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
  426. package/linthost/rules_unicorn_prefer_type_error.go +127 -0
  427. package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
  428. package/linthost/rules_unicorn_relative_url_style.go +49 -0
  429. package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
  430. package/linthost/rules_unicorn_require_module_attributes.go +54 -0
  431. package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
  432. package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
  433. package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
  434. package/linthost/rules_unicorn_string_content.go +27 -0
  435. package/linthost/rules_unicorn_switch_case_braces.go +42 -0
  436. package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
  437. package/linthost/rules_unicorn_template_indent.go +28 -0
  438. package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
  439. package/linthost/rules_unicorn_throw_new_error.go +61 -0
  440. package/linthost/rules_var.go +10 -4
  441. package/linthost/rules_vitest.go +568 -0
  442. package/package.json +3 -3
  443. package/plugin/main.go +49 -3
  444. package/rule/astutil/astutil.go +10 -3
  445. package/rule/rule.go +12 -10
  446. package/src/defaultFormat.ts +17 -10
  447. package/src/index.ts +65 -43
  448. package/src/structures/ITtscLintConfig.ts +14 -8
  449. package/src/structures/TtscLintRuleSetting.ts +55 -0
  450. package/src/structures/format/ITtscLintFormat.ts +141 -0
  451. package/src/structures/format/ITtscLintFormatJsDoc.ts +18 -0
  452. package/src/structures/format/ITtscLintFormatSortImports.ts +62 -0
  453. package/src/structures/format/index.ts +3 -0
  454. package/src/structures/index.ts +3 -4
  455. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +117 -0
  456. package/src/structures/rules/ITtscLintBoundariesRules.ts +91 -0
  457. package/src/structures/rules/ITtscLintContributorRules.ts +20 -0
  458. package/src/structures/rules/ITtscLintCoreRules.ts +1378 -0
  459. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
  460. package/src/structures/rules/ITtscLintCypressRules.ts +141 -0
  461. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +200 -0
  462. package/src/structures/rules/ITtscLintFunctionalRules.ts +197 -0
  463. package/src/structures/rules/ITtscLintJestRules.ts +209 -0
  464. package/src/structures/rules/ITtscLintJsdocRules.ts +146 -0
  465. package/src/structures/rules/ITtscLintJsxA11yRules.ts +331 -0
  466. package/src/structures/rules/ITtscLintNextjsRules.ts +201 -0
  467. package/src/structures/rules/ITtscLintPlaywrightRules.ts +343 -0
  468. package/src/structures/rules/ITtscLintPromiseRules.ts +196 -0
  469. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
  470. package/src/structures/rules/ITtscLintReactPerfRules.ts +53 -0
  471. package/src/structures/rules/ITtscLintReactRuleOptions.ts +41 -0
  472. package/src/structures/rules/ITtscLintReactRules.ts +308 -0
  473. package/src/structures/rules/ITtscLintRegexpRules.ts +204 -0
  474. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +88 -0
  475. package/src/structures/rules/ITtscLintRules.ts +77 -0
  476. package/src/structures/rules/ITtscLintSecurityRules.ts +155 -0
  477. package/src/structures/rules/ITtscLintSolidRules.ts +199 -0
  478. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +22 -0
  479. package/src/structures/rules/ITtscLintStorybookRules.ts +184 -0
  480. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +96 -0
  481. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +23 -0
  482. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +325 -0
  483. package/src/structures/rules/ITtscLintTypeScriptRules.ts +1172 -0
  484. package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
  485. package/src/structures/rules/ITtscLintVitestRules.ts +146 -0
  486. package/src/structures/rules/index.ts +31 -0
  487. package/lib/structures/ITtscLintFormatConfig.d.ts +0 -153
  488. package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
  489. package/lib/structures/TtscLintRule.d.ts +0 -17
  490. package/lib/structures/TtscLintRule.js.map +0 -1
  491. package/lib/structures/TtscLintRuleMap.d.ts +0 -46
  492. package/lib/structures/TtscLintRuleMap.js.map +0 -1
  493. package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
  494. package/lib/structures/TtscLintRuleOptions.js.map +0 -1
  495. package/src/structures/ITtscLintFormatConfig.ts +0 -168
  496. package/src/structures/TtscLintRule.ts +0 -160
  497. package/src/structures/TtscLintRuleMap.ts +0 -55
  498. package/src/structures/TtscLintRuleOptions.ts +0 -151
package/rule/rule.go CHANGED
@@ -110,17 +110,19 @@ type Reporter interface {
110
110
  }
111
111
 
112
112
  // FixReporter is the optional extension a host implements to receive
113
- // autofix edits alongside a finding. The public `rule.Context` type-asserts
114
- // against this shape so any host whose reporter exposes both methods opts
115
- // into fix support without depending on a private interface name.
113
+ // autofix edits alongside a finding. The public `rule.Context`
114
+ // type-asserts against this shape so any host whose reporter exposes
115
+ // both methods opts into fix support without depending on a private
116
+ // interface name.
116
117
  //
117
- // Contributor rules do NOT implement this interface — it is the host-side
118
- // counterpart to `Context.ReportFix` / `Context.ReportRangeFix`. A
119
- // contributor authoring a fake reporter for unit tests can declare
120
- // `var _ rule.FixReporter = &myReporter{}` to compile-check that the fake
121
- // satisfies the fix surface. Go interface satisfaction is all-or-nothing:
122
- // a fake that wants the fix path must implement BOTH `ReportFix` and
123
- // `ReportRangeFix`.
118
+ // Rule production code does NOT touch FixReporter directly — call
119
+ // `ctx.ReportFix` / `ctx.ReportRangeFix`, and the host's reporter
120
+ // receives the edits. The only place a contributor sees this interface
121
+ // is in test code that fakes the reporter: such a fake must implement
122
+ // BOTH `Reporter` (`Report` + `ReportRange`) AND `FixReporter`
123
+ // (`ReportFix` + `ReportRangeFix`), because Go interface satisfaction
124
+ // is all-or-nothing. Declaring `var _ rule.FixReporter = &myFake{}`
125
+ // compile-checks the fake covers the fix surface.
124
126
  type FixReporter interface {
125
127
  ReportFix(node *shimast.Node, message string, edits ...TextEdit)
126
128
  ReportRangeFix(pos, end int, message string, edits ...TextEdit)
@@ -1,32 +1,39 @@
1
- import type { ITtscLintFormatConfig } from "./structures/ITtscLintFormatConfig";
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
- * Import { defaultFormat, type ITtscLintConfig } from "@ttsc/lint";
11
+ * ```ts
12
+ * import { type ITtscLintConfig, defaultFormat } from "@ttsc/lint";
11
13
  *
12
- * Export default { format: { ...defaultFormat, printWidth: 100 }, } satisfies
13
- * ITtscLintConfig;
14
+ * export default {
15
+ * format: { ...defaultFormat, printWidth: 100 },
16
+ * } satisfies ITtscLintConfig;
17
+ * ```
14
18
  *
15
19
  * The values mirror Prettier 1:1 except for the documented `endOfLine`
16
20
  * narrowing (no `"cr"` / `"auto"`).
17
21
  *
18
- * Notably absent: `importOrder` and `jsdoc`. `format/sort-imports` and
19
- * `format/jsdoc` are opt-in by setting their corresponding fields; the defaults
20
- * const only seeds the rules that turn on unconditionally with a non-empty
21
- * `format` block.
22
+ * Notably absent: `importOrder`. `format/sort-imports` is opt-in by setting
23
+ * `importOrder`; `format/jsdoc` is always-on (set `jsDoc: false` to opt out).
24
+ * This const documents only the rules that turn on unconditionally with a
25
+ * non-empty `format` block, the Go host owns runtime activation.
22
26
  */
23
27
  export const defaultFormat = Object.freeze({
24
28
  severity: "off",
25
29
  semi: true,
26
30
  singleQuote: false,
31
+ arrowParens: "always",
32
+ bracketSpacing: true,
33
+ quoteProps: "as-needed",
27
34
  trailingComma: "all",
28
35
  printWidth: 80,
29
36
  tabWidth: 2,
30
37
  useTabs: false,
31
38
  endOfLine: "lf",
32
- } satisfies ITtscLintFormatConfig);
39
+ } satisfies ITtscLintFormat);
package/src/index.ts CHANGED
@@ -18,7 +18,11 @@ type TtscPluginContributor = {
18
18
 
19
19
  /** Descriptor shape returned to ttsc's plugin builder by the factory. */
20
20
  type TtscPluginDescriptor = {
21
- capabilities?: { threadingArgs?: boolean };
21
+ capabilities?: {
22
+ diagnosticsTiming?: boolean;
23
+ lsp?: boolean;
24
+ threadingArgs?: boolean;
25
+ };
22
26
  contributors?: TtscPluginContributor[];
23
27
  name: string;
24
28
  reportsTypeScriptDiagnostics?: boolean;
@@ -98,11 +102,10 @@ const FRAMEWORK_KEYS = new Set<string>([
98
102
  * upward from the tsconfig directory.
99
103
  *
100
104
  * The factory locates the config file, evaluates it (via ttsx for TS / ESM
101
- * sources, `require` for CommonJS, `JSON.parse` for JSON), reads its `plugins`
102
- * map, and forwards each contributor's Go source directory to ttsc's plugin
103
- * builder via the descriptor's `contributors` field.
104
- *
105
- * @internal
105
+ * sources, `require` for CommonJS, `JSON.parse` for JSON), reads every
106
+ * `plugins` map (top-level and inside array-form flat configs), and forwards
107
+ * each contributor's Go source directory to ttsc's plugin builder via the
108
+ * descriptor's `contributors` field.
106
109
  */
107
110
  export default function createTtscPlugin(
108
111
  context: TtscPluginFactoryContext<ITtscLintPluginConfig>,
@@ -113,7 +116,7 @@ export default function createTtscPlugin(
113
116
  // declared, so consumers (and the existing key-shape regression
114
117
  // tests) see the same surface as before this feature shipped.
115
118
  const descriptor: TtscPluginDescriptor = {
116
- capabilities: { threadingArgs: true },
119
+ capabilities: { diagnosticsTiming: true, lsp: true, threadingArgs: true },
117
120
  name: "@ttsc/lint",
118
121
  reportsTypeScriptDiagnostics: true,
119
122
  source: path.resolve(__dirname, "..", "plugin"),
@@ -255,14 +258,24 @@ function findLintConfigFile(
255
258
  // as ambiguous and skipped (the Go side raises a hard error on the
256
259
  // duplicate; here we leave it to the binary's own discovery to surface
257
260
  // the issue once with one canonical message).
261
+ const candidateSet = new Set<string>(LINT_CONFIG_FILENAMES);
258
262
  let dir = tsconfigBaseDir(context);
259
263
  while (true) {
260
- const matches = LINT_CONFIG_FILENAMES.map((name) =>
261
- path.join(dir, name),
262
- ).filter(
263
- (candidate) =>
264
- fs.existsSync(candidate) && fs.statSync(candidate).isFile(),
265
- );
264
+ // One `readdirSync` per directory level beats 14 `existsSync`+
265
+ // `statSync` pairs (= 28 stat syscalls) per level; intersect the
266
+ // listing with the candidate set instead.
267
+ let entries: fs.Dirent[];
268
+ try {
269
+ entries = fs.readdirSync(dir, { withFileTypes: true });
270
+ } catch {
271
+ entries = [];
272
+ }
273
+ const matches: string[] = [];
274
+ for (const entry of entries) {
275
+ if (!candidateSet.has(entry.name)) continue;
276
+ if (!entry.isFile() && !entry.isSymbolicLink()) continue;
277
+ matches.push(path.join(dir, entry.name));
278
+ }
266
279
  if (matches.length === 1) {
267
280
  return matches[0];
268
281
  }
@@ -376,7 +389,6 @@ function readCjsConfigPlugins(configPath: string): ConfigPluginEntry[] {
376
389
  const TTSX_EXTRACTOR_SCRIPT = `import * as importedConfig from %CONFIG_IMPORT%;
377
390
 
378
391
  declare const process: {
379
- argv: string[];
380
392
  cwd(): string;
381
393
  stdout: { write(value: string): void };
382
394
  stderr: { write(value: string): void };
@@ -444,7 +456,10 @@ function extractPluginSource(value: unknown): string | undefined {
444
456
  // contributors authored as plain \`module.exports = plugin\` both
445
457
  // resolve identically.
446
458
  let current: Record<string, unknown> = value;
447
- for (let i = 0; i < 4; i++) {
459
+ // 8 hops to match the outer-process unwrapDefault helper; previously
460
+ // 4, which silently misrouted deeply re-exported plugins while
461
+ // unwrapDefault would have unwrapped them.
462
+ for (let i = 0; i < 8; i++) {
448
463
  if (typeof current.source === "string") break;
449
464
  const next = current.default;
450
465
  if (!isObject(next)) break;
@@ -456,14 +471,14 @@ function extractPluginSource(value: unknown): string | undefined {
456
471
  `;
457
472
 
458
473
  /**
459
- * Resolves the contributor plugin entries declared in a .ts/.mjs lint
460
- * config, memoized through the shared on-disk config cache.
474
+ * Resolves the contributor plugin entries declared in a .ts/.mjs lint config,
475
+ * memoized through the shared on-disk config cache.
461
476
  *
462
- * Evaluating such a config spawns a full `ttsx` subprocess. A monorepo
463
- * build runs one `ttsc` process per package, and each would otherwise
464
- * re-spawn `ttsx` for the same shared config; the cache collapses that to
465
- * a single evaluation. The cache is keyed by the config file's path and
466
- * exact contents (see `configCacheKey`), so an edit re-evaluates cleanly.
477
+ * Evaluating such a config spawns a full `ttsx` subprocess. A monorepo build
478
+ * runs one `ttsc` process per package, and each would otherwise re-spawn `ttsx`
479
+ * for the same shared config; the cache collapses that to a single evaluation.
480
+ * The cache is keyed by the config file's path and exact contents (see
481
+ * `configCacheKey`), so an edit re-evaluates cleanly.
467
482
  */
468
483
  function readTtsxConfigPlugins(
469
484
  configPath: string,
@@ -485,9 +500,9 @@ function readTtsxConfigPlugins(
485
500
 
486
501
  /**
487
502
  * Reports whether a cached plugin entry is still usable: a well-formed
488
- * namespace and an absolute `source` that still points at a directory.
489
- * Pure predicate — never throws — so a malformed cache entry simply
490
- * triggers re-evaluation instead of aborting plugin discovery.
503
+ * namespace and an absolute `source` that still points at a directory. Pure
504
+ * predicate — never throws — so a malformed cache entry simply triggers
505
+ * re-evaluation instead of aborting plugin discovery.
491
506
  */
492
507
  function isValidConfigPluginEntry(entry: unknown): entry is ConfigPluginEntry {
493
508
  if (
@@ -655,15 +670,15 @@ function evaluateTtsxConfigPlugins(
655
670
  // ────────────────────────────────────────────────────────────────────────────
656
671
 
657
672
  /**
658
- * Namespaces the on-disk config cache. Kept in lockstep with the Go
659
- * sidecar's `configCacheVersion`; bump both when the cached shape changes.
673
+ * Namespaces the on-disk config cache. Kept in lockstep with the Go sidecar's
674
+ * `configCacheVersion`; bump both when the cached shape changes.
660
675
  */
661
676
  const CONFIG_CACHE_VERSION = "v1";
662
677
 
663
678
  /**
664
- * Directory shared by this factory and the Go sidecar for cached lint
665
- * configs. The two write different files (the `kind` segment of the cache
666
- * key keeps their namespaces apart), so they coexist without collision.
679
+ * Directory shared by this factory and the Go sidecar for cached lint configs.
680
+ * The two write different files (the `kind` segment of the cache key keeps
681
+ * their namespaces apart), so they coexist without collision.
667
682
  */
668
683
  function configCacheDir(): string {
669
684
  return path.join(os.tmpdir(), "ttsc-lint-config-cache");
@@ -675,10 +690,10 @@ function configCacheDisabled(): boolean {
675
690
  }
676
691
 
677
692
  /**
678
- * Content-addressed cache key for a lint config file. Mirrors the Go
679
- * sidecar's `configCacheKey`: a version tag, a namespace `kind`, the
680
- * config's absolute path, and its exact bytes. Returns "" — a "do not
681
- * cache" signal — when the file cannot be read or the env opt-out is set.
693
+ * Content-addressed cache key for a lint config file. Mirrors the Go sidecar's
694
+ * `configCacheKey`: a version tag, a namespace `kind`, the config's absolute
695
+ * path, and its exact bytes. Returns "" — a "do not cache" signal — when the
696
+ * file cannot be read or the env opt-out is set.
682
697
  */
683
698
  function configCacheKey(kind: string, configPath: string): string {
684
699
  if (configCacheDisabled()) return "";
@@ -700,9 +715,9 @@ function configCacheKey(kind: string, configPath: string): string {
700
715
  }
701
716
 
702
717
  /**
703
- * Returns the cached plugin-entry list for `cacheKey`, or undefined on any
704
- * miss — a missing file, an unreadable file, or content that is not a JSON
705
- * array. Every failure is a soft miss: the caller re-evaluates.
718
+ * Returns the cached plugin-entry list for `cacheKey`, or undefined on any miss
719
+ * — a missing file, an unreadable file, or content that is not a JSON array.
720
+ * Every failure is a soft miss: the caller re-evaluates.
706
721
  */
707
722
  function readConfigPluginCache(
708
723
  cacheKey: string,
@@ -718,9 +733,7 @@ function readConfigPluginCache(
718
733
  }
719
734
  try {
720
735
  const parsed: unknown = JSON.parse(body);
721
- return Array.isArray(parsed)
722
- ? (parsed as ConfigPluginEntry[])
723
- : undefined;
736
+ return Array.isArray(parsed) ? (parsed as ConfigPluginEntry[]) : undefined;
724
737
  } catch {
725
738
  return undefined;
726
739
  }
@@ -729,8 +742,8 @@ function readConfigPluginCache(
729
742
  /**
730
743
  * Writes `entries` to the config cache under `cacheKey`. Best-effort: any
731
744
  * failure leaves the cache cold rather than aborting plugin discovery. The
732
- * temp-file + rename keeps a concurrent reader in a sibling `ttsc` process
733
- * from observing a half-written file.
745
+ * temp-file + rename keeps a concurrent reader in a sibling `ttsc` process from
746
+ * observing a half-written file.
734
747
  */
735
748
  function writeConfigPluginCache(
736
749
  cacheKey: string,
@@ -800,7 +813,16 @@ function normalizePluginValue(
800
813
  }`,
801
814
  );
802
815
  }
803
- const mod = requireFromConfig(resolved);
816
+ let mod: unknown;
817
+ try {
818
+ mod = requireFromConfig(resolved);
819
+ } catch (error) {
820
+ throw new Error(
821
+ `@ttsc/lint: lint config ${configPath} plugin ${JSON.stringify(namespace)} failed to load from ${resolved}: ${
822
+ error instanceof Error ? error.message : String(error)
823
+ }`,
824
+ );
825
+ }
804
826
  const plugin = validatePluginShape(unwrapDefault(mod), namespace, resolved);
805
827
  return { namespace, source: plugin.source };
806
828
  }
@@ -1,6 +1,6 @@
1
- import type { ITtscLintFormatConfig } from "./ITtscLintFormatConfig";
1
+ import type { ITtscLintFormat } from "./format/ITtscLintFormat";
2
2
  import type { ITtscLintPlugin } from "./ITtscLintPlugin";
3
- import type { TtscLintRuleMap } from "./TtscLintRuleMap";
3
+ import type { ITtscLintRules } from "./rules/ITtscLintRules";
4
4
 
5
5
  /**
6
6
  * Top-level object accepted by `@ttsc/lint` config files.
@@ -22,12 +22,18 @@ 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
- /** Rule-name to severity map. Supports severity tuples with options. */
29
- rules?: TtscLintRuleMap;
28
+ /**
29
+ * Kebab-case built-in rule severities plus namespaced contributor rules.
30
+ *
31
+ * Built-in rules are concrete interface properties for autocomplete and typo
32
+ * checking. Namespaced families and contributor rules use the familiar slash
33
+ * form such as `react/jsx-key` or `demo/no-demo`.
34
+ */
35
+ rules?: ITtscLintRules;
30
36
 
31
- /** Prettier-style flat configuration for the `format/*` rules. */
32
- format?: ITtscLintFormatConfig;
37
+ /** Contributor plugin objects keyed by namespace. */
38
+ plugins?: Record<string, ITtscLintPlugin>;
33
39
  }
@@ -0,0 +1,55 @@
1
+ import type { TtscLintSeverity } from "./TtscLintSeverity";
2
+
3
+ /**
4
+ * Per-rule severity setting used by every rule entry in
5
+ * `ITtscLintConfig.rules`.
6
+ *
7
+ * A rule may be configured either as a bare severity string (`"error"`,
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 that
10
+ * severity-only rules and options-bearing rules look uniform when read
11
+ * top-to-bottom in a `ttsc.lint.config.ts` file.
12
+ *
13
+ * Use {@link TtscLintRuleOptionsSetting} when the rule accepts a typed options
14
+ * object.
15
+ *
16
+ * @example
17
+ * const config: ITtscLintConfig = {
18
+ * rules: {
19
+ * eqeqeq: "error",
20
+ * "no-console": ["warning"],
21
+ * "no-debugger": "off",
22
+ * },
23
+ * };
24
+ */
25
+ export type TtscLintRuleSetting =
26
+ | TtscLintSeverity
27
+ | readonly [TtscLintSeverity];
28
+
29
+ /**
30
+ * Per-rule severity-plus-options setting for rules that accept a typed options
31
+ * object.
32
+ *
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".
38
+ *
39
+ * @example
40
+ * const config: ITtscLintConfig = {
41
+ * rules: {
42
+ * "boundaries/element-types": [
43
+ * "error",
44
+ * { default: "disallow", rules: [...] },
45
+ * ],
46
+ * },
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
+ */
53
+ export type TtscLintRuleOptionsSetting<TOptions> =
54
+ | TtscLintRuleSetting
55
+ | readonly [TtscLintSeverity, TOptions];
@@ -0,0 +1,141 @@
1
+ import type { ITtscLintFormatJsDoc } from "./ITtscLintFormatJsDoc";
2
+ import type { ITtscLintFormatSortImports } from "./ITtscLintFormatSortImports";
3
+ import type { TtscLintSeverity } from "../TtscLintSeverity";
4
+
5
+ /**
6
+ * Prettier-style flat configuration for the format rules.
7
+ *
8
+ * The `format` block is the recommended way to enable formatting in
9
+ * `@ttsc/lint`. Each key mirrors a Prettier option of the same name, users
10
+ * coming from a `.prettierrc` can copy their config almost verbatim. The block
11
+ * is opt-in by presence: a `lint.config.ts` with no `format` field keeps every
12
+ * format rule off, exactly as before.
13
+ *
14
+ * Once present, the block configures a curated set of format rules at
15
+ * Prettier-aligned defaults. `ttsc format` uses these rules to rewrite source.
16
+ * `ttsc check` does not report format findings unless `severity` is set to a
17
+ * non-off value. Individual rules can be overridden or disabled through the
18
+ * `rules` map (the `rules` entry wins on conflict).
19
+ */
20
+ export interface ITtscLintFormat {
21
+ /**
22
+ * Check-time severity for format findings generated from this block.
23
+ *
24
+ * The default is `"off"` so formatting policy does not affect compilation
25
+ * unless the project opts into that behavior. `ttsc format` can still use the
26
+ * rest of this block to rewrite files.
27
+ *
28
+ * @default "off"
29
+ */
30
+ severity?: TtscLintSeverity;
31
+
32
+ /**
33
+ * Insert trailing semicolons on ASI-terminated statements. Mirrors Prettier's
34
+ * `semi`. `false` flips the rule to require _no_ trailing semicolon (rare;
35
+ * matches prettier's `semi: false`).
36
+ *
37
+ * @default true
38
+ */
39
+ semi?: boolean;
40
+
41
+ /**
42
+ * Prefer single-quoted strings. Mirrors Prettier's `singleQuote`. `false`
43
+ * means double quotes (Prettier's default).
44
+ *
45
+ * @default false
46
+ */
47
+ singleQuote?: boolean;
48
+
49
+ /**
50
+ * Parenthesize a single arrow-function parameter. Mirrors Prettier's
51
+ * `arrowParens`. `"always"` (the default) keeps `(x) => x`; `"avoid"` strips
52
+ * the parentheses of a single bare-identifier parameter, giving `x => x`. A
53
+ * typed, destructured, rest, optional, defaulted, or multi-parameter list
54
+ * keeps its parentheses in both modes.
55
+ *
56
+ * @default "always"
57
+ */
58
+ arrowParens?: "always" | "avoid";
59
+
60
+ /**
61
+ * Pad the inside of single-line braces with one space. Mirrors Prettier's
62
+ * `bracketSpacing`. `true` (the default) gives `{ x: 1 }`, `import { foo }`;
63
+ * `false` gives `{x: 1}`, `import {foo}`. Applies to object literals, object
64
+ * destructuring patterns, named imports/exports, and type literals; block,
65
+ * class, interface, and enum braces are unaffected.
66
+ *
67
+ * @default true
68
+ */
69
+ bracketSpacing?: boolean;
70
+
71
+ /**
72
+ * Quoting policy for object-literal property keys. Mirrors Prettier's
73
+ * `quoteProps`. `"as-needed"` (the default) removes quotes from a key that
74
+ * is a valid identifier (`{ "foo": 1 }` becomes `{ foo: 1 }`), keeping them
75
+ * on non-identifier or numeric keys (`"bar-baz"`, `"123"`). `"consistent"`
76
+ * keeps every key quoted when any one of them requires quotes. `"preserve"`
77
+ * never changes quoting.
78
+ *
79
+ * @default "as-needed"
80
+ */
81
+ quoteProps?: "as-needed" | "consistent" | "preserve";
82
+
83
+ /**
84
+ * Trailing-comma policy. Mirrors Prettier's `trailingComma`. The `"none"`
85
+ * mode disables the rule's edits.
86
+ *
87
+ * @default "all"
88
+ */
89
+ trailingComma?: "all" | "es5" | "none";
90
+
91
+ /**
92
+ * Maximum column width before broken-form layout is chosen. Mirrors
93
+ * Prettier's `printWidth`.
94
+ *
95
+ * @default 80
96
+ */
97
+ printWidth?: number;
98
+
99
+ /**
100
+ * Indentation increment in columns. Mirrors Prettier's `tabWidth`.
101
+ *
102
+ * @default 2
103
+ */
104
+ tabWidth?: number;
105
+
106
+ /**
107
+ * Emit indentation as tab characters. Mirrors Prettier's `useTabs`.
108
+ *
109
+ * @default false
110
+ */
111
+ useTabs?: boolean;
112
+
113
+ /**
114
+ * Line terminator the printer emits on reflow. `@ttsc/lint` supports `"lf"`
115
+ * and `"crlf"`. Prettier's `"cr"` and `"auto"` are intentionally unsupported
116
+ * because the printer does not auto-detect line endings.
117
+ *
118
+ * @default "lf"
119
+ */
120
+ endOfLine?: "lf" | "crlf";
121
+
122
+ /**
123
+ * Import sorting & merging. Off unless present; `true` enables it with
124
+ * defaults, an object customizes.
125
+ *
126
+ * @default false
127
+ */
128
+ sortImports?: boolean | ITtscLintFormatSortImports;
129
+
130
+ /**
131
+ * JSDoc tag normalization. On by default like the rest of the format set;
132
+ * pass `false` to disable, or an object to customize.
133
+ *
134
+ * Today it only rewrites tag synonyms (`@return` → `@returns`, `@arg` →
135
+ * `@param`, ...); tag sorting, `@param` column alignment, and description
136
+ * wrapping are on the roadmap.
137
+ *
138
+ * @default true
139
+ */
140
+ jsDoc?: boolean | ITtscLintFormatJsDoc;
141
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Object form of {@link ITtscLintFormat.jsDoc}.
3
+ */
4
+ export interface ITtscLintFormatJsDoc {
5
+ /**
6
+ * Extra `from → to` tag rewrites layered on the built-in synonym table
7
+ * (`@return` → `@returns`, `@arg` → `@param`, ...).
8
+ */
9
+ tagSynonyms?: Record<string, string>;
10
+
11
+ /**
12
+ * Sort JSDoc tags into canonical order. Reserved; the current MVP only
13
+ * rewrites tag names.
14
+ *
15
+ * @default false
16
+ */
17
+ sortTags?: boolean;
18
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Object form of {@link ITtscLintFormat.sortImports}.
3
+ *
4
+ * The declarative {@link order} array expresses group order, blank-line
5
+ * separation, and special groups all by position. Multiple imports of the same
6
+ * module are always merged into one declaration; merging a value import with a
7
+ * type-only import additionally requires {@link combineTypeAndValue}.
8
+ */
9
+ export interface ITtscLintFormatSortImports {
10
+ /**
11
+ * Group order. Each entry is a regular expression matched against a
12
+ * declaration's module specifier, or one of these placeholders:
13
+ *
14
+ * - `<BUILTIN_MODULES>` — Node built-in modules (`fs`, `node:path`, ...).
15
+ * - `<THIRD_PARTY_MODULES>` — catch-all for specifiers that match no other
16
+ * group. Injected implicitly at the front when omitted.
17
+ * - `<TYPES>` — `import type` declarations. Combine with a regex to scope it,
18
+ * e.g. `<TYPES>^[.]` groups type-only relative imports.
19
+ * - `""` (empty string) — emit one blank line at this position. An array with
20
+ * no `""` entry produces no blank lines between groups.
21
+ *
22
+ * Named specifiers inside each declaration are always sorted. Omit for the
23
+ * default grouping. Example:
24
+ *
25
+ * ```ts
26
+ * order: [
27
+ * "<BUILTIN_MODULES>",
28
+ * "",
29
+ * "<THIRD_PARTY_MODULES>",
30
+ * "",
31
+ * "<TYPES>^[.]",
32
+ * "^[.]",
33
+ * ]
34
+ * ```
35
+ */
36
+ order?: readonly (
37
+ | "<BUILTIN_MODULES>"
38
+ | "<THIRD_PARTY_MODULES>"
39
+ | "<TYPES>"
40
+ | ""
41
+ | (string & {})
42
+ )[];
43
+
44
+ /**
45
+ * Case-sensitive comparison. `false` (the default) sorts case-insensitively,
46
+ * so `React` and `react` order together; `true` uses raw ASCII order
47
+ * (uppercase before lowercase).
48
+ *
49
+ * @default false
50
+ */
51
+ caseSensitive?: boolean;
52
+
53
+ /**
54
+ * Merge a value import and a type-only import of the same module into one
55
+ * declaration with inline `type` specifiers: `import { foo } from "m"` plus
56
+ * `import type { Bar } from "m"` collapse to
57
+ * `import { foo, type Bar } from "m"`.
58
+ *
59
+ * @default false
60
+ */
61
+ combineTypeAndValue?: boolean;
62
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./ITtscLintFormat";
2
+ export * from "./ITtscLintFormatJsDoc";
3
+ export * from "./ITtscLintFormatSortImports";
@@ -1,9 +1,8 @@
1
1
  export * from "./ITtscLintConfig";
2
- export * from "./ITtscLintFormatConfig";
2
+ export * from "./format";
3
3
  export * from "./ITtscLintPlugin";
4
4
  export * from "./ITtscLintPluginConfig";
5
5
  export * from "./ITtscLintPluginMeta";
6
- export * from "./TtscLintRule";
7
- export * from "./TtscLintRuleMap";
8
- export * from "./TtscLintRuleOptions";
6
+ export * from "./TtscLintRuleSetting";
9
7
  export * from "./TtscLintSeverity";
8
+ export * from "./rules";