@ttsc/lint 0.14.0-dev.20260529.2 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/README.md +23 -25
  2. package/lib/defaultFormat.d.ts +10 -6
  3. package/lib/defaultFormat.js +10 -6
  4. package/lib/defaultFormat.js.map +1 -1
  5. package/lib/structures/ITtscLintConfig.d.ts +5 -5
  6. package/lib/structures/TtscLintRuleSetting.d.ts +19 -19
  7. package/lib/structures/{ITtscLintFormat.d.ts → format/ITtscLintFormat.d.ts} +45 -70
  8. package/lib/structures/format/ITtscLintFormat.js.map +1 -0
  9. package/lib/structures/format/ITtscLintFormatJsDoc.d.ts +15 -0
  10. package/lib/structures/format/ITtscLintFormatJsDoc.js +3 -0
  11. package/lib/structures/format/ITtscLintFormatJsDoc.js.map +1 -0
  12. package/lib/structures/format/ITtscLintFormatSortImports.d.ts +54 -0
  13. package/lib/structures/format/ITtscLintFormatSortImports.js +3 -0
  14. package/lib/structures/format/ITtscLintFormatSortImports.js.map +1 -0
  15. package/lib/structures/format/index.d.ts +3 -0
  16. package/lib/structures/format/index.js +20 -0
  17. package/lib/structures/format/index.js.map +1 -0
  18. package/lib/structures/index.d.ts +1 -1
  19. package/lib/structures/index.js +1 -1
  20. package/lib/structures/index.js.map +1 -1
  21. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +18 -27
  22. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +4 -5
  23. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -1
  24. package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +29 -33
  25. package/lib/structures/rules/ITtscLintContributorRules.d.ts +6 -7
  26. package/lib/structures/rules/ITtscLintCoreRules.d.ts +380 -408
  27. package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +5 -5
  28. package/lib/structures/rules/ITtscLintCypressRuleOptions.js +2 -2
  29. package/lib/structures/rules/ITtscLintCypressRules.d.ts +34 -38
  30. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +21 -24
  31. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +2 -2
  32. package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +51 -56
  33. package/lib/structures/rules/ITtscLintJestRules.d.ts +63 -74
  34. package/lib/structures/rules/ITtscLintJsdocRules.d.ts +47 -54
  35. package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +94 -102
  36. package/lib/structures/rules/ITtscLintNextjsRules.d.ts +50 -55
  37. package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +104 -122
  38. package/lib/structures/rules/ITtscLintPromiseRules.d.ts +62 -71
  39. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +4 -4
  40. package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +17 -19
  41. package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +8 -10
  42. package/lib/structures/rules/ITtscLintReactRuleOptions.js +1 -2
  43. package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -1
  44. package/lib/structures/rules/ITtscLintReactRules.d.ts +91 -104
  45. package/lib/structures/rules/ITtscLintRegexpRules.d.ts +46 -54
  46. package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +7 -8
  47. package/lib/structures/rules/ITtscLintSecurityRules.d.ts +45 -52
  48. package/lib/structures/rules/ITtscLintSolidRules.d.ts +53 -56
  49. package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +3 -4
  50. package/lib/structures/rules/ITtscLintStorybookRules.d.ts +60 -69
  51. package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +31 -37
  52. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +2 -3
  53. package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +102 -119
  54. package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +460 -518
  55. package/lib/structures/rules/ITtscLintVitestRules.d.ts +43 -51
  56. package/linthost/config.go +89 -72
  57. package/linthost/config_format.go +265 -99
  58. package/linthost/directives.go +5 -1
  59. package/linthost/display_width.go +72 -0
  60. package/linthost/fix.go +26 -1
  61. package/linthost/format.go +222 -25
  62. package/linthost/format_editor_settings.go +262 -0
  63. package/linthost/lsp.go +8 -4
  64. package/linthost/print_dispatch.go +3 -0
  65. package/linthost/print_doc.go +13 -0
  66. package/linthost/print_engine.go +68 -11
  67. package/linthost/print_nodes_array.go +167 -5
  68. package/linthost/print_nodes_call.go +786 -77
  69. package/linthost/print_nodes_function.go +43 -0
  70. package/linthost/print_nodes_imports.go +64 -14
  71. package/linthost/print_nodes_list.go +214 -8
  72. package/linthost/print_nodes_object.go +14 -6
  73. package/linthost/print_nodes_ternary.go +147 -0
  74. package/linthost/rules_boundaries.go +400 -400
  75. package/linthost/rules_camelcase.go +81 -81
  76. package/linthost/rules_complexity.go +52 -51
  77. package/linthost/rules_consistent_return.go +81 -81
  78. package/linthost/rules_core_extra.go +472 -472
  79. package/linthost/rules_curly.go +43 -43
  80. package/linthost/rules_default_case.go +15 -15
  81. package/linthost/rules_default_case_last.go +22 -22
  82. package/linthost/rules_format_arrow_parens.go +213 -0
  83. package/linthost/rules_format_bracket_spacing.go +117 -0
  84. package/linthost/rules_format_clause_join.go +179 -0
  85. package/linthost/rules_format_declaration_header.go +664 -0
  86. package/linthost/rules_format_indent.go +616 -0
  87. package/linthost/rules_format_jsdoc.go +4 -4
  88. package/linthost/rules_format_orphan_semi.go +106 -0
  89. package/linthost/rules_format_parameter_properties.go +175 -0
  90. package/linthost/rules_format_print_width.go +180 -69
  91. package/linthost/rules_format_quote_props.go +169 -0
  92. package/linthost/rules_format_quotes.go +75 -29
  93. package/linthost/rules_format_semi.go +185 -10
  94. package/linthost/rules_format_sort_imports.go +517 -121
  95. package/linthost/rules_format_statement_split.go +368 -0
  96. package/linthost/rules_format_ternary_nullish_parens.go +77 -0
  97. package/linthost/rules_format_trailing_comma.go +21 -2
  98. package/linthost/rules_format_whitespace.go +336 -0
  99. package/linthost/rules_functional.go +688 -688
  100. package/linthost/rules_gap.go +146 -11
  101. package/linthost/rules_grouped_accessor_pairs.go +60 -60
  102. package/linthost/rules_guard_for_in.go +122 -122
  103. package/linthost/rules_id_length.go +44 -44
  104. package/linthost/rules_imports.go +11 -3
  105. package/linthost/rules_init_declarations.go +25 -25
  106. package/linthost/rules_jsx_a11y.go +844 -844
  107. package/linthost/rules_max_classes_per_file.go +24 -24
  108. package/linthost/rules_max_depth.go +43 -43
  109. package/linthost/rules_max_lines.go +53 -53
  110. package/linthost/rules_max_lines_per_function.go +28 -28
  111. package/linthost/rules_max_nested_callbacks.go +26 -26
  112. package/linthost/rules_max_params.go +20 -20
  113. package/linthost/rules_max_statements.go +29 -29
  114. package/linthost/rules_nextjs.go +5 -5
  115. package/linthost/rules_no_else_return.go +38 -38
  116. package/linthost/rules_no_empty_named_blocks.go +45 -45
  117. package/linthost/rules_no_import_assign.go +96 -96
  118. package/linthost/rules_no_invalid_this.go +19 -19
  119. package/linthost/rules_no_loop_func.go +43 -43
  120. package/linthost/rules_no_magic_numbers.go +60 -60
  121. package/linthost/rules_no_mixed_operators.go +44 -44
  122. package/linthost/rules_no_param_reassign.go +64 -64
  123. package/linthost/rules_no_restricted_imports.go +45 -45
  124. package/linthost/rules_no_restricted_syntax.go +17 -17
  125. package/linthost/rules_no_shadow.go +112 -112
  126. package/linthost/rules_no_unreachable.go +36 -36
  127. package/linthost/rules_no_useless_assignment.go +79 -79
  128. package/linthost/rules_no_useless_constructor.go +167 -167
  129. package/linthost/rules_no_useless_return.go +28 -28
  130. package/linthost/rules_prefer_arrow_callback.go +74 -74
  131. package/linthost/rules_prefer_destructuring.go +61 -61
  132. package/linthost/rules_prefer_named_capture_group.go +87 -87
  133. package/linthost/rules_prefer_rest_params.go +61 -61
  134. package/linthost/rules_promise.go +800 -800
  135. package/linthost/rules_react.go +600 -600
  136. package/linthost/rules_react_extras.go +162 -162
  137. package/linthost/rules_react_hooks.go +2 -2
  138. package/linthost/rules_react_perf.go +231 -231
  139. package/linthost/rules_regexp.go +293 -293
  140. package/linthost/rules_security.go +613 -613
  141. package/linthost/rules_sort_imports.go +37 -37
  142. package/linthost/rules_sort_keys.go +88 -88
  143. package/linthost/rules_suggestions.go +13 -0
  144. package/linthost/rules_ts.go +2 -2
  145. package/linthost/rules_ts_async.go +247 -247
  146. package/linthost/rules_ts_class_literal_property_style.go +64 -64
  147. package/linthost/rules_ts_consistent_type_exports.go +209 -209
  148. package/linthost/rules_ts_explicit_function_return_type.go +35 -35
  149. package/linthost/rules_ts_extra.go +6 -2
  150. package/linthost/rules_ts_no_base_to_string.go +140 -140
  151. package/linthost/rules_ts_no_confusing_void.go +28 -28
  152. package/linthost/rules_ts_no_deprecated.go +110 -110
  153. package/linthost/rules_ts_no_for_in_array.go +45 -45
  154. package/linthost/rules_ts_no_magic_numbers.go +67 -67
  155. package/linthost/rules_ts_no_meaningless_void_operator.go +44 -44
  156. package/linthost/rules_ts_no_misused_spread.go +64 -64
  157. package/linthost/rules_ts_no_redundant_type_constituents.go +72 -72
  158. package/linthost/rules_ts_no_restricted_types.go +28 -28
  159. package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +87 -87
  160. package/linthost/rules_ts_no_unnecessary_condition.go +184 -184
  161. package/linthost/rules_ts_no_unnecessary_qualifier.go +72 -72
  162. package/linthost/rules_ts_no_unnecessary_template_expression.go +120 -120
  163. package/linthost/rules_ts_no_unnecessary_type_arguments.go +171 -171
  164. package/linthost/rules_ts_no_unnecessary_type_assertion.go +90 -90
  165. package/linthost/rules_ts_no_unsafe_argument.go +50 -50
  166. package/linthost/rules_ts_no_unsafe_assignment.go +60 -60
  167. package/linthost/rules_ts_no_unsafe_call.go +40 -40
  168. package/linthost/rules_ts_no_unsafe_enum_comparison.go +147 -147
  169. package/linthost/rules_ts_no_unsafe_member_access.go +29 -29
  170. package/linthost/rules_ts_no_unsafe_return.go +64 -64
  171. package/linthost/rules_ts_no_unsafe_unary_minus.go +42 -42
  172. package/linthost/rules_ts_no_useless_constructor.go +20 -20
  173. package/linthost/rules_ts_non_nullable_type_assertion_style.go +60 -60
  174. package/linthost/rules_ts_parameter_properties.go +10 -10
  175. package/linthost/rules_ts_prefer_find.go +116 -116
  176. package/linthost/rules_ts_prefer_includes.go +173 -173
  177. package/linthost/rules_ts_prefer_nullish_coalescing.go +54 -54
  178. package/linthost/rules_ts_prefer_optional_chain.go +156 -156
  179. package/linthost/rules_ts_prefer_promise_reject_errors.go +104 -104
  180. package/linthost/rules_ts_prefer_readonly.go +31 -31
  181. package/linthost/rules_ts_prefer_reduce_type_parameter.go +74 -74
  182. package/linthost/rules_ts_prefer_regexp_exec.go +69 -69
  183. package/linthost/rules_ts_prefer_return_this_type.go +79 -79
  184. package/linthost/rules_ts_prefer_string_starts_ends_with.go +237 -237
  185. package/linthost/rules_ts_promise_function_async.go +41 -41
  186. package/linthost/rules_ts_related_getter_setter_pairs.go +61 -61
  187. package/linthost/rules_ts_require_array_sort_compare.go +58 -58
  188. package/linthost/rules_ts_restrict_plus_operands.go +82 -82
  189. package/linthost/rules_ts_restrict_template_expressions.go +50 -50
  190. package/linthost/rules_ts_simple.go +249 -249
  191. package/linthost/rules_ts_sort_type_constituents.go +88 -88
  192. package/linthost/rules_ts_strict_boolean_expressions.go +103 -103
  193. package/linthost/rules_ts_switch_exhaustiveness_check.go +90 -90
  194. package/linthost/rules_ts_unbound_method.go +65 -65
  195. package/linthost/rules_tsdoc.go +88 -88
  196. package/linthost/rules_unicorn_better_regex.go +1 -1
  197. package/linthost/rules_unicorn_catch_error_name.go +19 -19
  198. package/linthost/rules_unicorn_consistent_assert.go +20 -20
  199. package/linthost/rules_unicorn_consistent_date_clone.go +27 -27
  200. package/linthost/rules_unicorn_consistent_destructuring.go +3 -3
  201. package/linthost/rules_unicorn_consistent_empty_array_spread.go +34 -34
  202. package/linthost/rules_unicorn_consistent_existence_index_check.go +42 -42
  203. package/linthost/rules_unicorn_consistent_function_scoping.go +3 -3
  204. package/linthost/rules_unicorn_consistent_template_literal_escape.go +3 -3
  205. package/linthost/rules_unicorn_custom_error_definition.go +92 -92
  206. package/linthost/rules_unicorn_empty_brace_spaces.go +47 -47
  207. package/linthost/rules_unicorn_error_message.go +34 -34
  208. package/linthost/rules_unicorn_escape_case.go +14 -14
  209. package/linthost/rules_unicorn_expiring_todo_comments.go +36 -36
  210. package/linthost/rules_unicorn_explicit_length_check.go +51 -51
  211. package/linthost/rules_unicorn_filename_case.go +1 -1
  212. package/linthost/rules_unicorn_import_style.go +1 -1
  213. package/linthost/rules_unicorn_isolated_functions.go +2 -2
  214. package/linthost/rules_unicorn_new_for_builtins.go +49 -49
  215. package/linthost/rules_unicorn_no_abusive_eslint_disable.go +31 -31
  216. package/linthost/rules_unicorn_no_accessor_recursion.go +69 -69
  217. package/linthost/rules_unicorn_no_anonymous_default_export.go +40 -40
  218. package/linthost/rules_unicorn_no_array_callback_reference.go +33 -33
  219. package/linthost/rules_unicorn_no_array_for_each.go +14 -14
  220. package/linthost/rules_unicorn_no_array_method_this_argument.go +29 -29
  221. package/linthost/rules_unicorn_no_array_reduce.go +15 -15
  222. package/linthost/rules_unicorn_no_array_reverse.go +17 -17
  223. package/linthost/rules_unicorn_no_array_sort.go +17 -17
  224. package/linthost/rules_unicorn_no_await_expression_member.go +12 -12
  225. package/linthost/rules_unicorn_no_await_in_promise_methods.go +38 -38
  226. package/linthost/rules_unicorn_no_console_spaces.go +30 -30
  227. package/linthost/rules_unicorn_no_document_cookie.go +13 -13
  228. package/linthost/rules_unicorn_no_empty_file.go +16 -16
  229. package/linthost/rules_unicorn_no_for_loop.go +58 -58
  230. package/linthost/rules_unicorn_no_hex_escape.go +11 -11
  231. package/linthost/rules_unicorn_no_immediate_mutation.go +55 -55
  232. package/linthost/rules_unicorn_no_instanceof_builtins.go +34 -34
  233. package/linthost/rules_unicorn_no_invalid_fetch_options.go +52 -52
  234. package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +25 -25
  235. package/linthost/rules_unicorn_no_keyword_prefix.go +56 -56
  236. package/linthost/rules_unicorn_no_lonely_if.go +21 -21
  237. package/linthost/rules_unicorn_no_magic_array_flat_depth.go +22 -22
  238. package/linthost/rules_unicorn_no_named_default.go +25 -25
  239. package/linthost/rules_unicorn_no_negated_condition.go +54 -54
  240. package/linthost/rules_unicorn_no_negation_in_equality_check.go +23 -23
  241. package/linthost/rules_unicorn_no_nested_ternary.go +15 -15
  242. package/linthost/rules_unicorn_no_new_array.go +5 -5
  243. package/linthost/rules_unicorn_no_new_buffer.go +5 -5
  244. package/linthost/rules_unicorn_no_null.go +2 -2
  245. package/linthost/rules_unicorn_no_object_as_default_parameter.go +19 -19
  246. package/linthost/rules_unicorn_no_process_exit.go +17 -17
  247. package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +29 -29
  248. package/linthost/rules_unicorn_no_static_only_class.go +27 -27
  249. package/linthost/rules_unicorn_no_thenable.go +47 -47
  250. package/linthost/rules_unicorn_no_this_assignment.go +10 -10
  251. package/linthost/rules_unicorn_no_typeof_undefined.go +31 -31
  252. package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +23 -23
  253. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +37 -37
  254. package/linthost/rules_unicorn_no_unnecessary_await.go +24 -24
  255. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +22 -22
  256. package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +67 -67
  257. package/linthost/rules_unicorn_no_unreadable_iife.go +22 -22
  258. package/linthost/rules_unicorn_no_useless_collection_argument.go +34 -34
  259. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +18 -18
  260. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +49 -49
  261. package/linthost/rules_unicorn_no_useless_iterator_to_array.go +41 -41
  262. package/linthost/rules_unicorn_no_useless_length_check.go +82 -82
  263. package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +42 -42
  264. package/linthost/rules_unicorn_no_useless_spread.go +38 -38
  265. package/linthost/rules_unicorn_no_useless_switch_case.go +29 -29
  266. package/linthost/rules_unicorn_no_useless_undefined.go +25 -25
  267. package/linthost/rules_unicorn_no_zero_fractions.go +17 -17
  268. package/linthost/rules_unicorn_number_literal_case.go +33 -33
  269. package/linthost/rules_unicorn_numeric_separators_style.go +36 -36
  270. package/linthost/rules_unicorn_prefer_add_event_listener.go +30 -30
  271. package/linthost/rules_unicorn_prefer_array_find.go +27 -27
  272. package/linthost/rules_unicorn_prefer_array_flat.go +25 -25
  273. package/linthost/rules_unicorn_prefer_array_flat_map.go +37 -37
  274. package/linthost/rules_unicorn_prefer_array_index_of.go +108 -108
  275. package/linthost/rules_unicorn_prefer_array_some.go +43 -43
  276. package/linthost/rules_unicorn_prefer_at.go +42 -42
  277. package/linthost/rules_unicorn_prefer_bigint_literals.go +42 -42
  278. package/linthost/rules_unicorn_prefer_blob_reading_methods.go +15 -15
  279. package/linthost/rules_unicorn_prefer_class_fields.go +57 -57
  280. package/linthost/rules_unicorn_prefer_classlist_toggle.go +76 -76
  281. package/linthost/rules_unicorn_prefer_code_point.go +21 -21
  282. package/linthost/rules_unicorn_prefer_date_now.go +47 -47
  283. package/linthost/rules_unicorn_prefer_default_parameters.go +96 -96
  284. package/linthost/rules_unicorn_prefer_dom_node_append.go +14 -14
  285. package/linthost/rules_unicorn_prefer_dom_node_dataset.go +27 -27
  286. package/linthost/rules_unicorn_prefer_dom_node_remove.go +17 -17
  287. package/linthost/rules_unicorn_prefer_dom_node_text_content.go +11 -11
  288. package/linthost/rules_unicorn_prefer_event_target.go +10 -10
  289. package/linthost/rules_unicorn_prefer_export_from.go +99 -99
  290. package/linthost/rules_unicorn_prefer_global_this.go +91 -91
  291. package/linthost/rules_unicorn_prefer_import_meta_properties.go +38 -38
  292. package/linthost/rules_unicorn_prefer_includes.go +108 -108
  293. package/linthost/rules_unicorn_prefer_json_parse_buffer.go +37 -37
  294. package/linthost/rules_unicorn_prefer_keyboard_event_key.go +10 -10
  295. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +20 -20
  296. package/linthost/rules_unicorn_prefer_math_min_max.go +33 -33
  297. package/linthost/rules_unicorn_prefer_math_trunc.go +32 -32
  298. package/linthost/rules_unicorn_prefer_modern_dom_apis.go +18 -18
  299. package/linthost/rules_unicorn_prefer_modern_math_apis.go +38 -38
  300. package/linthost/rules_unicorn_prefer_module.go +22 -22
  301. package/linthost/rules_unicorn_prefer_native_coercion_functions.go +73 -73
  302. package/linthost/rules_unicorn_prefer_negative_index.go +46 -46
  303. package/linthost/rules_unicorn_prefer_node_protocol.go +90 -90
  304. package/linthost/rules_unicorn_prefer_number_properties.go +57 -57
  305. package/linthost/rules_unicorn_prefer_object_from_entries.go +26 -26
  306. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +24 -24
  307. package/linthost/rules_unicorn_prefer_prototype_methods.go +25 -25
  308. package/linthost/rules_unicorn_prefer_query_selector.go +25 -25
  309. package/linthost/rules_unicorn_prefer_reflect_apply.go +10 -10
  310. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +47 -47
  311. package/linthost/rules_unicorn_prefer_response_static_json.go +26 -26
  312. package/linthost/rules_unicorn_prefer_set_has.go +16 -16
  313. package/linthost/rules_unicorn_prefer_set_size.go +22 -22
  314. package/linthost/rules_unicorn_prefer_simple_condition_first.go +3 -3
  315. package/linthost/rules_unicorn_prefer_single_call.go +59 -59
  316. package/linthost/rules_unicorn_prefer_spread.go +24 -24
  317. package/linthost/rules_unicorn_prefer_string_raw.go +12 -12
  318. package/linthost/rules_unicorn_prefer_string_replace_all.go +46 -46
  319. package/linthost/rules_unicorn_prefer_string_slice.go +17 -17
  320. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +104 -104
  321. package/linthost/rules_unicorn_prefer_string_trim_start_end.go +21 -21
  322. package/linthost/rules_unicorn_prefer_structured_clone.go +36 -36
  323. package/linthost/rules_unicorn_prefer_switch.go +65 -65
  324. package/linthost/rules_unicorn_prefer_ternary.go +35 -35
  325. package/linthost/rules_unicorn_prefer_top_level_await.go +34 -34
  326. package/linthost/rules_unicorn_prefer_type_error.go +84 -84
  327. package/linthost/rules_unicorn_prevent_abbreviations.go +68 -68
  328. package/linthost/rules_unicorn_relative_url_style.go +19 -19
  329. package/linthost/rules_unicorn_require_array_join_separator.go +18 -18
  330. package/linthost/rules_unicorn_require_module_attributes.go +25 -25
  331. package/linthost/rules_unicorn_require_module_specifiers.go +28 -28
  332. package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +18 -18
  333. package/linthost/rules_unicorn_require_post_message_target_origin.go +18 -18
  334. package/linthost/rules_unicorn_string_content.go +1 -1
  335. package/linthost/rules_unicorn_switch_case_braces.go +16 -16
  336. package/linthost/rules_unicorn_switch_case_break_position.go +3 -3
  337. package/linthost/rules_unicorn_template_indent.go +1 -1
  338. package/linthost/rules_unicorn_text_encoding_identifier_case.go +36 -36
  339. package/linthost/rules_unicorn_throw_new_error.go +30 -30
  340. package/linthost/rules_var.go +273 -3
  341. package/package.json +3 -3
  342. package/src/defaultFormat.ts +11 -7
  343. package/src/structures/ITtscLintConfig.ts +5 -5
  344. package/src/structures/TtscLintRuleSetting.ts +19 -19
  345. package/src/structures/{ITtscLintFormat.ts → format/ITtscLintFormat.ts} +48 -75
  346. package/src/structures/format/ITtscLintFormatJsDoc.ts +16 -0
  347. package/src/structures/format/ITtscLintFormatSortImports.ts +62 -0
  348. package/src/structures/format/index.ts +3 -0
  349. package/src/structures/index.ts +1 -1
  350. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +20 -31
  351. package/src/structures/rules/ITtscLintBoundariesRules.ts +32 -36
  352. package/src/structures/rules/ITtscLintContributorRules.ts +6 -7
  353. package/src/structures/rules/ITtscLintCoreRules.ts +380 -408
  354. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +5 -5
  355. package/src/structures/rules/ITtscLintCypressRules.ts +34 -38
  356. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +28 -41
  357. package/src/structures/rules/ITtscLintFunctionalRules.ts +51 -56
  358. package/src/structures/rules/ITtscLintJestRules.ts +63 -74
  359. package/src/structures/rules/ITtscLintJsdocRules.ts +47 -54
  360. package/src/structures/rules/ITtscLintJsxA11yRules.ts +94 -102
  361. package/src/structures/rules/ITtscLintNextjsRules.ts +50 -55
  362. package/src/structures/rules/ITtscLintPlaywrightRules.ts +104 -122
  363. package/src/structures/rules/ITtscLintPromiseRules.ts +62 -71
  364. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +4 -4
  365. package/src/structures/rules/ITtscLintReactPerfRules.ts +17 -19
  366. package/src/structures/rules/ITtscLintReactRuleOptions.ts +8 -10
  367. package/src/structures/rules/ITtscLintReactRules.ts +91 -104
  368. package/src/structures/rules/ITtscLintRegexpRules.ts +46 -54
  369. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +7 -8
  370. package/src/structures/rules/ITtscLintSecurityRules.ts +45 -52
  371. package/src/structures/rules/ITtscLintSolidRules.ts +53 -56
  372. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +3 -4
  373. package/src/structures/rules/ITtscLintStorybookRules.ts +60 -69
  374. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +31 -37
  375. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +2 -3
  376. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +102 -119
  377. package/src/structures/rules/ITtscLintTypeScriptRules.ts +460 -518
  378. package/src/structures/rules/ITtscLintVitestRules.ts +43 -51
  379. package/lib/structures/ITtscLintFormat.js.map +0 -1
  380. /package/lib/structures/{ITtscLintFormat.js → format/ITtscLintFormat.js} +0 -0
@@ -1,15 +1,15 @@
1
1
  package linthost
2
2
 
3
3
  import (
4
- "encoding/json"
5
- "fmt"
6
- "os"
7
- "path/filepath"
8
- "regexp"
9
- "sort"
10
- "strings"
11
-
12
- shimast "github.com/microsoft/typescript-go/shim/ast"
4
+ "encoding/json"
5
+ "fmt"
6
+ "os"
7
+ "path/filepath"
8
+ "regexp"
9
+ "sort"
10
+ "strings"
11
+
12
+ shimast "github.com/microsoft/typescript-go/shim/ast"
13
13
  )
14
14
 
15
15
  type boundariesElementTypes struct{}
@@ -49,484 +49,484 @@ func (boundariesDependencies) Visits() []shimast.Kind { return []shimast.Kind{sh
49
49
  // findings. Replace this body when the unified direction validation
50
50
  // lands.
51
51
  func (boundariesDependencies) Check(ctx *Context, node *shimast.Node) {
52
- _ = decodeBoundariesOptions(ctx)
52
+ _ = decodeBoundariesOptions(ctx)
53
53
  }
54
54
 
55
55
  func (boundariesElementTypes) Check(ctx *Context, node *shimast.Node) {
56
- opts := decodeBoundariesOptions(ctx)
57
- if len(opts.Elements) == 0 {
58
- return
59
- }
60
- source := classifyBoundaryFile(ctx.File.FileName(), opts.Elements)
61
- if source == nil {
62
- return
63
- }
64
- for _, dep := range collectBoundaryDependencies(node) {
65
- if !dep.relative {
66
- continue
67
- }
68
- targetPath, ok := resolveBoundaryImport(ctx.File.FileName(), dep.specifier)
69
- if !ok {
70
- continue
71
- }
72
- target := classifyBoundaryFile(targetPath, opts.Elements)
73
- if target == nil {
74
- continue
75
- }
76
- policy, rule := evaluateBoundaryPolicy(opts, source.Type, target.Type)
77
- if policy != "disallow" {
78
- continue
79
- }
80
- message := fmt.Sprintf("Import from boundary element %q is not allowed in %q.", target.Type, source.Type)
81
- if rule != nil && rule.Message != "" {
82
- message = rule.Message
83
- }
84
- reportBoundaryDependency(ctx, dep, message)
85
- }
56
+ opts := decodeBoundariesOptions(ctx)
57
+ if len(opts.Elements) == 0 {
58
+ return
59
+ }
60
+ source := classifyBoundaryFile(ctx.File.FileName(), opts.Elements)
61
+ if source == nil {
62
+ return
63
+ }
64
+ for _, dep := range collectBoundaryDependencies(node) {
65
+ if !dep.relative {
66
+ continue
67
+ }
68
+ targetPath, ok := resolveBoundaryImport(ctx.File.FileName(), dep.specifier)
69
+ if !ok {
70
+ continue
71
+ }
72
+ target := classifyBoundaryFile(targetPath, opts.Elements)
73
+ if target == nil {
74
+ continue
75
+ }
76
+ policy, rule := evaluateBoundaryPolicy(opts, source.Type, target.Type)
77
+ if policy != "disallow" {
78
+ continue
79
+ }
80
+ message := fmt.Sprintf("Import from boundary element %q is not allowed in %q.", target.Type, source.Type)
81
+ if rule != nil && rule.Message != "" {
82
+ message = rule.Message
83
+ }
84
+ reportBoundaryDependency(ctx, dep, message)
85
+ }
86
86
  }
87
87
 
88
88
  func (boundariesExternal) Check(ctx *Context, node *shimast.Node) {
89
- opts := decodeBoundariesOptions(ctx)
90
- for _, dep := range collectBoundaryDependencies(node) {
91
- if dep.relative {
92
- continue
93
- }
94
- name := boundaryPackageName(dep.specifier)
95
- disallowed := matchAnyBoundaryPattern(opts.Disallow, dep.specifier, name)
96
- allowed := len(opts.Allow) == 0 || matchAnyBoundaryPattern(opts.Allow, dep.specifier, name)
97
- if !disallowed && allowed {
98
- continue
99
- }
100
- message := fmt.Sprintf("External dependency %q is not allowed.", dep.specifier)
101
- if opts.Message != "" {
102
- message = opts.Message
103
- }
104
- reportBoundaryDependency(ctx, dep, message)
105
- }
89
+ opts := decodeBoundariesOptions(ctx)
90
+ for _, dep := range collectBoundaryDependencies(node) {
91
+ if dep.relative {
92
+ continue
93
+ }
94
+ name := boundaryPackageName(dep.specifier)
95
+ disallowed := matchAnyBoundaryPattern(opts.Disallow, dep.specifier, name)
96
+ allowed := len(opts.Allow) == 0 || matchAnyBoundaryPattern(opts.Allow, dep.specifier, name)
97
+ if !disallowed && allowed {
98
+ continue
99
+ }
100
+ message := fmt.Sprintf("External dependency %q is not allowed.", dep.specifier)
101
+ if opts.Message != "" {
102
+ message = opts.Message
103
+ }
104
+ reportBoundaryDependency(ctx, dep, message)
105
+ }
106
106
  }
107
107
 
108
108
  func (boundariesEntryPoint) Check(ctx *Context, node *shimast.Node) {
109
- opts := decodeBoundariesOptions(ctx)
110
- if len(opts.Elements) == 0 {
111
- return
112
- }
113
- source := classifyBoundaryFile(ctx.File.FileName(), opts.Elements)
114
- for _, dep := range collectBoundaryDependencies(node) {
115
- if !dep.relative {
116
- continue
117
- }
118
- targetPath, ok := resolveBoundaryImport(ctx.File.FileName(), dep.specifier)
119
- if !ok {
120
- continue
121
- }
122
- target := classifyBoundaryFile(targetPath, opts.Elements)
123
- if target == nil || len(target.Entry) == 0 {
124
- continue
125
- }
126
- if source != nil && source.RootPath == target.RootPath {
127
- continue
128
- }
129
- if matchBoundaryElementLocalPattern(target.Entry, target) {
130
- continue
131
- }
132
- reportBoundaryDependency(ctx, dep, fmt.Sprintf("Import %q through an allowed boundary entry point.", target.RelativePath))
133
- }
109
+ opts := decodeBoundariesOptions(ctx)
110
+ if len(opts.Elements) == 0 {
111
+ return
112
+ }
113
+ source := classifyBoundaryFile(ctx.File.FileName(), opts.Elements)
114
+ for _, dep := range collectBoundaryDependencies(node) {
115
+ if !dep.relative {
116
+ continue
117
+ }
118
+ targetPath, ok := resolveBoundaryImport(ctx.File.FileName(), dep.specifier)
119
+ if !ok {
120
+ continue
121
+ }
122
+ target := classifyBoundaryFile(targetPath, opts.Elements)
123
+ if target == nil || len(target.Entry) == 0 {
124
+ continue
125
+ }
126
+ if source != nil && source.RootPath == target.RootPath {
127
+ continue
128
+ }
129
+ if matchBoundaryElementLocalPattern(target.Entry, target) {
130
+ continue
131
+ }
132
+ reportBoundaryDependency(ctx, dep, fmt.Sprintf("Import %q through an allowed boundary entry point.", target.RelativePath))
133
+ }
134
134
  }
135
135
 
136
136
  func (boundariesNoPrivate) Check(ctx *Context, node *shimast.Node) {
137
- opts := decodeBoundariesOptions(ctx)
138
- if len(opts.Elements) == 0 {
139
- return
140
- }
141
- source := classifyBoundaryFile(ctx.File.FileName(), opts.Elements)
142
- if source == nil {
143
- return
144
- }
145
- for _, dep := range collectBoundaryDependencies(node) {
146
- if !dep.relative {
147
- continue
148
- }
149
- targetPath, ok := resolveBoundaryImport(ctx.File.FileName(), dep.specifier)
150
- if !ok {
151
- continue
152
- }
153
- target := classifyBoundaryFile(targetPath, opts.Elements)
154
- if target == nil || len(target.Private) == 0 {
155
- continue
156
- }
157
- if source.RootPath == target.RootPath || !matchBoundaryElementLocalPattern(target.Private, target) {
158
- continue
159
- }
160
- reportBoundaryDependency(ctx, dep, fmt.Sprintf("Do not import private boundary file %q from another element.", target.RelativePath))
161
- }
137
+ opts := decodeBoundariesOptions(ctx)
138
+ if len(opts.Elements) == 0 {
139
+ return
140
+ }
141
+ source := classifyBoundaryFile(ctx.File.FileName(), opts.Elements)
142
+ if source == nil {
143
+ return
144
+ }
145
+ for _, dep := range collectBoundaryDependencies(node) {
146
+ if !dep.relative {
147
+ continue
148
+ }
149
+ targetPath, ok := resolveBoundaryImport(ctx.File.FileName(), dep.specifier)
150
+ if !ok {
151
+ continue
152
+ }
153
+ target := classifyBoundaryFile(targetPath, opts.Elements)
154
+ if target == nil || len(target.Private) == 0 {
155
+ continue
156
+ }
157
+ if source.RootPath == target.RootPath || !matchBoundaryElementLocalPattern(target.Private, target) {
158
+ continue
159
+ }
160
+ reportBoundaryDependency(ctx, dep, fmt.Sprintf("Do not import private boundary file %q from another element.", target.RelativePath))
161
+ }
162
162
  }
163
163
 
164
164
  func (boundariesNoUnknown) Check(ctx *Context, node *shimast.Node) {
165
- opts := decodeBoundariesOptions(ctx)
166
- if len(opts.Elements) == 0 {
167
- return
168
- }
169
- for _, dep := range collectBoundaryDependencies(node) {
170
- if !dep.relative {
171
- continue
172
- }
173
- targetPath, ok := resolveBoundaryImport(ctx.File.FileName(), dep.specifier)
174
- if !ok {
175
- continue
176
- }
177
- if classifyBoundaryFile(targetPath, opts.Elements) != nil {
178
- continue
179
- }
180
- reportBoundaryDependency(ctx, dep, fmt.Sprintf("Imported file %q does not match any configured boundary element.", boundaryDisplayPath(targetPath)))
181
- }
165
+ opts := decodeBoundariesOptions(ctx)
166
+ if len(opts.Elements) == 0 {
167
+ return
168
+ }
169
+ for _, dep := range collectBoundaryDependencies(node) {
170
+ if !dep.relative {
171
+ continue
172
+ }
173
+ targetPath, ok := resolveBoundaryImport(ctx.File.FileName(), dep.specifier)
174
+ if !ok {
175
+ continue
176
+ }
177
+ if classifyBoundaryFile(targetPath, opts.Elements) != nil {
178
+ continue
179
+ }
180
+ reportBoundaryDependency(ctx, dep, fmt.Sprintf("Imported file %q does not match any configured boundary element.", boundaryDisplayPath(targetPath)))
181
+ }
182
182
  }
183
183
 
184
184
  type boundaryStringList []string
185
185
 
186
186
  func (l *boundaryStringList) UnmarshalJSON(data []byte) error {
187
- if string(data) == "null" {
188
- *l = nil
189
- return nil
190
- }
191
- var single string
192
- if err := json.Unmarshal(data, &single); err == nil {
193
- *l = boundaryStringList{single}
194
- return nil
195
- }
196
- var many []string
197
- if err := json.Unmarshal(data, &many); err != nil {
198
- return err
199
- }
200
- *l = boundaryStringList(many)
201
- return nil
187
+ if string(data) == "null" {
188
+ *l = nil
189
+ return nil
190
+ }
191
+ var single string
192
+ if err := json.Unmarshal(data, &single); err == nil {
193
+ *l = boundaryStringList{single}
194
+ return nil
195
+ }
196
+ var many []string
197
+ if err := json.Unmarshal(data, &many); err != nil {
198
+ return err
199
+ }
200
+ *l = boundaryStringList(many)
201
+ return nil
202
202
  }
203
203
 
204
204
  type boundariesOptions struct {
205
- Elements []boundaryElement `json:"elements"`
206
- Rules []boundaryPolicyRule `json:"rules"`
207
- Default string `json:"default"`
208
- Allow boundaryStringList `json:"allow"`
209
- Disallow boundaryStringList `json:"disallow"`
210
- Message string `json:"message"`
205
+ Elements []boundaryElement `json:"elements"`
206
+ Rules []boundaryPolicyRule `json:"rules"`
207
+ Default string `json:"default"`
208
+ Allow boundaryStringList `json:"allow"`
209
+ Disallow boundaryStringList `json:"disallow"`
210
+ Message string `json:"message"`
211
211
  }
212
212
 
213
213
  type boundaryElement struct {
214
- Type string `json:"type"`
215
- Pattern string `json:"pattern"`
216
- Entry boundaryStringList `json:"entry"`
217
- Private boundaryStringList `json:"private"`
214
+ Type string `json:"type"`
215
+ Pattern string `json:"pattern"`
216
+ Entry boundaryStringList `json:"entry"`
217
+ Private boundaryStringList `json:"private"`
218
218
  }
219
219
 
220
220
  type boundaryPolicyRule struct {
221
- From boundaryStringList `json:"from"`
222
- Allow boundaryStringList `json:"allow"`
223
- Disallow boundaryStringList `json:"disallow"`
224
- Message string `json:"message"`
221
+ From boundaryStringList `json:"from"`
222
+ Allow boundaryStringList `json:"allow"`
223
+ Disallow boundaryStringList `json:"disallow"`
224
+ Message string `json:"message"`
225
225
  }
226
226
 
227
227
  type boundaryFile struct {
228
- Element boundaryElement
229
- Type string
230
- Path string
231
- RelativePath string
232
- RootPath string
233
- LocalPath string
234
- Entry boundaryStringList
235
- Private boundaryStringList
228
+ Element boundaryElement
229
+ Type string
230
+ Path string
231
+ RelativePath string
232
+ RootPath string
233
+ LocalPath string
234
+ Entry boundaryStringList
235
+ Private boundaryStringList
236
236
  }
237
237
 
238
238
  type boundaryDependency struct {
239
- node *shimast.Node
240
- specifier string
241
- relative bool
239
+ node *shimast.Node
240
+ specifier string
241
+ relative bool
242
242
  }
243
243
 
244
244
  func decodeBoundariesOptions(ctx *Context) boundariesOptions {
245
- var opts boundariesOptions
246
- if ctx != nil {
247
- _ = ctx.DecodeOptions(&opts)
248
- }
249
- return opts
245
+ var opts boundariesOptions
246
+ if ctx != nil {
247
+ _ = ctx.DecodeOptions(&opts)
248
+ }
249
+ return opts
250
250
  }
251
251
 
252
252
  func collectBoundaryDependencies(node *shimast.Node) []boundaryDependency {
253
- out := []boundaryDependency{}
254
- var walk func(*shimast.Node)
255
- walk = func(n *shimast.Node) {
256
- if n == nil {
257
- return
258
- }
259
- switch n.Kind {
260
- case shimast.KindImportDeclaration:
261
- if imp := n.AsImportDeclaration(); imp != nil && imp.ModuleSpecifier != nil {
262
- specifier := stringLiteralText(imp.ModuleSpecifier)
263
- if specifier != "" {
264
- out = append(out, boundaryDependency{
265
- node: imp.ModuleSpecifier,
266
- specifier: specifier,
267
- relative: isRelativeBoundarySpecifier(specifier),
268
- })
269
- }
270
- }
271
- case shimast.KindExportDeclaration:
272
- if exp := n.AsExportDeclaration(); exp != nil && exp.ModuleSpecifier != nil {
273
- specifier := stringLiteralText(exp.ModuleSpecifier)
274
- if specifier != "" {
275
- out = append(out, boundaryDependency{
276
- node: exp.ModuleSpecifier,
277
- specifier: specifier,
278
- relative: isRelativeBoundarySpecifier(specifier),
279
- })
280
- }
281
- }
282
- }
283
- n.ForEachChild(func(child *shimast.Node) bool {
284
- walk(child)
285
- return false
286
- })
287
- }
288
- walk(node)
289
- return out
253
+ out := []boundaryDependency{}
254
+ var walk func(*shimast.Node)
255
+ walk = func(n *shimast.Node) {
256
+ if n == nil {
257
+ return
258
+ }
259
+ switch n.Kind {
260
+ case shimast.KindImportDeclaration:
261
+ if imp := n.AsImportDeclaration(); imp != nil && imp.ModuleSpecifier != nil {
262
+ specifier := stringLiteralText(imp.ModuleSpecifier)
263
+ if specifier != "" {
264
+ out = append(out, boundaryDependency{
265
+ node: imp.ModuleSpecifier,
266
+ specifier: specifier,
267
+ relative: isRelativeBoundarySpecifier(specifier),
268
+ })
269
+ }
270
+ }
271
+ case shimast.KindExportDeclaration:
272
+ if exp := n.AsExportDeclaration(); exp != nil && exp.ModuleSpecifier != nil {
273
+ specifier := stringLiteralText(exp.ModuleSpecifier)
274
+ if specifier != "" {
275
+ out = append(out, boundaryDependency{
276
+ node: exp.ModuleSpecifier,
277
+ specifier: specifier,
278
+ relative: isRelativeBoundarySpecifier(specifier),
279
+ })
280
+ }
281
+ }
282
+ }
283
+ n.ForEachChild(func(child *shimast.Node) bool {
284
+ walk(child)
285
+ return false
286
+ })
287
+ }
288
+ walk(node)
289
+ return out
290
290
  }
291
291
 
292
292
  func classifyBoundaryFile(fileName string, elements []boundaryElement) *boundaryFile {
293
- normalized := normalizeBoundaryPath(fileName)
294
- matches := []boundaryFile{}
295
- for _, elem := range elements {
296
- if elem.Type == "" || elem.Pattern == "" {
297
- continue
298
- }
299
- rel, ok := boundaryRelativeMatch(elem.Pattern, normalized)
300
- if !ok {
301
- continue
302
- }
303
- root := boundaryElementRoot(elem.Pattern, rel)
304
- local := rel
305
- if root != "" {
306
- local = strings.TrimPrefix(rel, root)
307
- local = strings.TrimPrefix(local, "/")
308
- }
309
- matches = append(matches, boundaryFile{
310
- Element: elem,
311
- Type: elem.Type,
312
- Path: normalized,
313
- RelativePath: rel,
314
- RootPath: root,
315
- LocalPath: local,
316
- Entry: elem.Entry,
317
- Private: elem.Private,
318
- })
319
- }
320
- if len(matches) == 0 {
321
- return nil
322
- }
323
- sort.Slice(matches, func(i, j int) bool {
324
- return len(matches[i].RootPath) > len(matches[j].RootPath)
325
- })
326
- return &matches[0]
293
+ normalized := normalizeBoundaryPath(fileName)
294
+ matches := []boundaryFile{}
295
+ for _, elem := range elements {
296
+ if elem.Type == "" || elem.Pattern == "" {
297
+ continue
298
+ }
299
+ rel, ok := boundaryRelativeMatch(elem.Pattern, normalized)
300
+ if !ok {
301
+ continue
302
+ }
303
+ root := boundaryElementRoot(elem.Pattern, rel)
304
+ local := rel
305
+ if root != "" {
306
+ local = strings.TrimPrefix(rel, root)
307
+ local = strings.TrimPrefix(local, "/")
308
+ }
309
+ matches = append(matches, boundaryFile{
310
+ Element: elem,
311
+ Type: elem.Type,
312
+ Path: normalized,
313
+ RelativePath: rel,
314
+ RootPath: root,
315
+ LocalPath: local,
316
+ Entry: elem.Entry,
317
+ Private: elem.Private,
318
+ })
319
+ }
320
+ if len(matches) == 0 {
321
+ return nil
322
+ }
323
+ sort.Slice(matches, func(i, j int) bool {
324
+ return len(matches[i].RootPath) > len(matches[j].RootPath)
325
+ })
326
+ return &matches[0]
327
327
  }
328
328
 
329
329
  func evaluateBoundaryPolicy(opts boundariesOptions, fromType, targetType string) (string, *boundaryPolicyRule) {
330
- defaultPolicy := opts.Default
331
- if defaultPolicy == "" {
332
- defaultPolicy = "allow"
333
- }
334
- for i := range opts.Rules {
335
- rule := &opts.Rules[i]
336
- if len(rule.From) > 0 && !matchAnyBoundaryPattern(rule.From, fromType) {
337
- continue
338
- }
339
- if len(rule.Disallow) > 0 && matchAnyBoundaryPattern(rule.Disallow, targetType) {
340
- return "disallow", rule
341
- }
342
- if len(rule.Allow) > 0 {
343
- if matchAnyBoundaryPattern(rule.Allow, targetType) {
344
- return "allow", rule
345
- }
346
- return "disallow", rule
347
- }
348
- }
349
- return defaultPolicy, nil
330
+ defaultPolicy := opts.Default
331
+ if defaultPolicy == "" {
332
+ defaultPolicy = "allow"
333
+ }
334
+ for i := range opts.Rules {
335
+ rule := &opts.Rules[i]
336
+ if len(rule.From) > 0 && !matchAnyBoundaryPattern(rule.From, fromType) {
337
+ continue
338
+ }
339
+ if len(rule.Disallow) > 0 && matchAnyBoundaryPattern(rule.Disallow, targetType) {
340
+ return "disallow", rule
341
+ }
342
+ if len(rule.Allow) > 0 {
343
+ if matchAnyBoundaryPattern(rule.Allow, targetType) {
344
+ return "allow", rule
345
+ }
346
+ return "disallow", rule
347
+ }
348
+ }
349
+ return defaultPolicy, nil
350
350
  }
351
351
 
352
352
  func resolveBoundaryImport(sourceFileName, specifier string) (string, bool) {
353
- if !isRelativeBoundarySpecifier(specifier) {
354
- return "", false
355
- }
356
- base := filepath.Dir(sourceFileName)
357
- target := filepath.Clean(filepath.Join(base, filepath.FromSlash(specifier)))
358
- candidates := []string{target}
359
- if filepath.Ext(target) == "" {
360
- for _, ext := range []string{".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"} {
361
- candidates = append(candidates, target+ext)
362
- }
363
- for _, ext := range []string{".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"} {
364
- candidates = append(candidates, filepath.Join(target, "index"+ext))
365
- }
366
- }
367
- for _, candidate := range candidates {
368
- if info, err := os.Stat(candidate); err == nil && !info.IsDir() {
369
- abs, err := filepath.Abs(candidate)
370
- if err == nil {
371
- return abs, true
372
- }
373
- return candidate, true
374
- }
375
- }
376
- return "", false
353
+ if !isRelativeBoundarySpecifier(specifier) {
354
+ return "", false
355
+ }
356
+ base := filepath.Dir(sourceFileName)
357
+ target := filepath.Clean(filepath.Join(base, filepath.FromSlash(specifier)))
358
+ candidates := []string{target}
359
+ if filepath.Ext(target) == "" {
360
+ for _, ext := range []string{".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"} {
361
+ candidates = append(candidates, target+ext)
362
+ }
363
+ for _, ext := range []string{".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"} {
364
+ candidates = append(candidates, filepath.Join(target, "index"+ext))
365
+ }
366
+ }
367
+ for _, candidate := range candidates {
368
+ if info, err := os.Stat(candidate); err == nil && !info.IsDir() {
369
+ abs, err := filepath.Abs(candidate)
370
+ if err == nil {
371
+ return abs, true
372
+ }
373
+ return candidate, true
374
+ }
375
+ }
376
+ return "", false
377
377
  }
378
378
 
379
379
  func reportBoundaryDependency(ctx *Context, dep boundaryDependency, message string) {
380
- if dep.node != nil {
381
- ctx.Report(dep.node, message)
382
- return
383
- }
384
- ctx.ReportRange(0, 1, message)
380
+ if dep.node != nil {
381
+ ctx.Report(dep.node, message)
382
+ return
383
+ }
384
+ ctx.ReportRange(0, 1, message)
385
385
  }
386
386
 
387
387
  func matchBoundaryElementLocalPattern(patterns boundaryStringList, file *boundaryFile) bool {
388
- if file == nil {
389
- return false
390
- }
391
- for _, pattern := range patterns {
392
- if boundaryPatternMatch(pattern, file.LocalPath) || boundaryPatternMatch(pattern, filepath.Base(file.LocalPath)) || boundaryPatternMatch(pattern, file.RelativePath) {
393
- return true
394
- }
395
- }
396
- return false
388
+ if file == nil {
389
+ return false
390
+ }
391
+ for _, pattern := range patterns {
392
+ if boundaryPatternMatch(pattern, file.LocalPath) || boundaryPatternMatch(pattern, filepath.Base(file.LocalPath)) || boundaryPatternMatch(pattern, file.RelativePath) {
393
+ return true
394
+ }
395
+ }
396
+ return false
397
397
  }
398
398
 
399
399
  func matchAnyBoundaryPattern(patterns boundaryStringList, candidates ...string) bool {
400
- for _, pattern := range patterns {
401
- for _, candidate := range candidates {
402
- if boundaryPatternMatch(pattern, candidate) {
403
- return true
404
- }
405
- }
406
- }
407
- return false
400
+ for _, pattern := range patterns {
401
+ for _, candidate := range candidates {
402
+ if boundaryPatternMatch(pattern, candidate) {
403
+ return true
404
+ }
405
+ }
406
+ }
407
+ return false
408
408
  }
409
409
 
410
410
  func boundaryRelativeMatch(pattern, fileName string) (string, bool) {
411
- for _, candidate := range boundaryPathCandidates(fileName) {
412
- if boundaryPatternMatch(pattern, candidate) {
413
- return candidate, true
414
- }
415
- }
416
- return "", false
411
+ for _, candidate := range boundaryPathCandidates(fileName) {
412
+ if boundaryPatternMatch(pattern, candidate) {
413
+ return candidate, true
414
+ }
415
+ }
416
+ return "", false
417
417
  }
418
418
 
419
419
  func boundaryPatternMatch(pattern, candidate string) bool {
420
- pattern = strings.TrimPrefix(normalizeBoundaryPath(pattern), "./")
421
- candidate = strings.TrimPrefix(normalizeBoundaryPath(candidate), "./")
422
- if pattern == "" || candidate == "" {
423
- return false
424
- }
425
- re, err := regexp.Compile("^" + regexp.QuoteMeta(pattern) + "$")
426
- if err != nil {
427
- return false
428
- }
429
- expr := re.String()
430
- expr = strings.ReplaceAll(expr, `\*\*`, ".*")
431
- expr = strings.ReplaceAll(expr, `\*`, `[^/]*`)
432
- expr = strings.ReplaceAll(expr, `\?`, `[^/]`)
433
- re, err = regexp.Compile(expr)
434
- if err != nil {
435
- return false
436
- }
437
- return re.MatchString(candidate)
420
+ pattern = strings.TrimPrefix(normalizeBoundaryPath(pattern), "./")
421
+ candidate = strings.TrimPrefix(normalizeBoundaryPath(candidate), "./")
422
+ if pattern == "" || candidate == "" {
423
+ return false
424
+ }
425
+ re, err := regexp.Compile("^" + regexp.QuoteMeta(pattern) + "$")
426
+ if err != nil {
427
+ return false
428
+ }
429
+ expr := re.String()
430
+ expr = strings.ReplaceAll(expr, `\*\*`, ".*")
431
+ expr = strings.ReplaceAll(expr, `\*`, `[^/]*`)
432
+ expr = strings.ReplaceAll(expr, `\?`, `[^/]`)
433
+ re, err = regexp.Compile(expr)
434
+ if err != nil {
435
+ return false
436
+ }
437
+ return re.MatchString(candidate)
438
438
  }
439
439
 
440
440
  func boundaryPathCandidates(path string) []string {
441
- normalized := strings.TrimPrefix(normalizeBoundaryPath(path), "/")
442
- candidates := []string{normalized}
443
- if cwd, err := os.Getwd(); err == nil {
444
- if rel, err := filepath.Rel(cwd, path); err == nil && !strings.HasPrefix(rel, "..") {
445
- candidates = append(candidates, normalizeBoundaryPath(rel))
446
- }
447
- }
448
- parts := strings.Split(normalized, "/")
449
- for i := 1; i < len(parts); i++ {
450
- candidates = append(candidates, strings.Join(parts[i:], "/"))
451
- }
452
- return uniqueBoundaryStrings(candidates)
441
+ normalized := strings.TrimPrefix(normalizeBoundaryPath(path), "/")
442
+ candidates := []string{normalized}
443
+ if cwd, err := os.Getwd(); err == nil {
444
+ if rel, err := filepath.Rel(cwd, path); err == nil && !strings.HasPrefix(rel, "..") {
445
+ candidates = append(candidates, normalizeBoundaryPath(rel))
446
+ }
447
+ }
448
+ parts := strings.Split(normalized, "/")
449
+ for i := 1; i < len(parts); i++ {
450
+ candidates = append(candidates, strings.Join(parts[i:], "/"))
451
+ }
452
+ return uniqueBoundaryStrings(candidates)
453
453
  }
454
454
 
455
455
  func boundaryElementRoot(pattern, matched string) string {
456
- pattern = strings.TrimPrefix(normalizeBoundaryPath(pattern), "./")
457
- wildcard := len(pattern)
458
- for _, token := range []string{"*", "?"} {
459
- if idx := strings.Index(pattern, token); idx >= 0 && idx < wildcard {
460
- wildcard = idx
461
- }
462
- }
463
- root := strings.TrimSuffix(pattern[:wildcard], "/")
464
- if root == pattern {
465
- root = filepath.ToSlash(filepath.Dir(root))
466
- if root == "." {
467
- root = ""
468
- }
469
- }
470
- if root != "" {
471
- return root
472
- }
473
- if slash := strings.LastIndex(matched, "/"); slash >= 0 {
474
- return matched[:slash]
475
- }
476
- return ""
456
+ pattern = strings.TrimPrefix(normalizeBoundaryPath(pattern), "./")
457
+ wildcard := len(pattern)
458
+ for _, token := range []string{"*", "?"} {
459
+ if idx := strings.Index(pattern, token); idx >= 0 && idx < wildcard {
460
+ wildcard = idx
461
+ }
462
+ }
463
+ root := strings.TrimSuffix(pattern[:wildcard], "/")
464
+ if root == pattern {
465
+ root = filepath.ToSlash(filepath.Dir(root))
466
+ if root == "." {
467
+ root = ""
468
+ }
469
+ }
470
+ if root != "" {
471
+ return root
472
+ }
473
+ if slash := strings.LastIndex(matched, "/"); slash >= 0 {
474
+ return matched[:slash]
475
+ }
476
+ return ""
477
477
  }
478
478
 
479
479
  func boundaryPackageName(specifier string) string {
480
- if strings.HasPrefix(specifier, "@") {
481
- parts := strings.Split(specifier, "/")
482
- if len(parts) >= 2 {
483
- return parts[0] + "/" + parts[1]
484
- }
485
- return specifier
486
- }
487
- if idx := strings.Index(specifier, "/"); idx >= 0 {
488
- return specifier[:idx]
489
- }
490
- return specifier
480
+ if strings.HasPrefix(specifier, "@") {
481
+ parts := strings.Split(specifier, "/")
482
+ if len(parts) >= 2 {
483
+ return parts[0] + "/" + parts[1]
484
+ }
485
+ return specifier
486
+ }
487
+ if idx := strings.Index(specifier, "/"); idx >= 0 {
488
+ return specifier[:idx]
489
+ }
490
+ return specifier
491
491
  }
492
492
 
493
493
  func boundaryDisplayPath(path string) string {
494
- candidates := boundaryPathCandidates(path)
495
- if len(candidates) == 0 {
496
- return normalizeBoundaryPath(path)
497
- }
498
- return candidates[0]
494
+ candidates := boundaryPathCandidates(path)
495
+ if len(candidates) == 0 {
496
+ return normalizeBoundaryPath(path)
497
+ }
498
+ return candidates[0]
499
499
  }
500
500
 
501
501
  func normalizeBoundaryPath(path string) string {
502
- return filepath.ToSlash(filepath.Clean(path))
502
+ return filepath.ToSlash(filepath.Clean(path))
503
503
  }
504
504
 
505
505
  func isRelativeBoundarySpecifier(specifier string) bool {
506
- return specifier == "." || specifier == ".." || strings.HasPrefix(specifier, "./") || strings.HasPrefix(specifier, "../")
506
+ return specifier == "." || specifier == ".." || strings.HasPrefix(specifier, "./") || strings.HasPrefix(specifier, "../")
507
507
  }
508
508
 
509
509
  func uniqueBoundaryStrings(values []string) []string {
510
- seen := map[string]struct{}{}
511
- out := []string{}
512
- for _, value := range values {
513
- if value == "" {
514
- continue
515
- }
516
- if _, ok := seen[value]; ok {
517
- continue
518
- }
519
- seen[value] = struct{}{}
520
- out = append(out, value)
521
- }
522
- return out
510
+ seen := map[string]struct{}{}
511
+ out := []string{}
512
+ for _, value := range values {
513
+ if value == "" {
514
+ continue
515
+ }
516
+ if _, ok := seen[value]; ok {
517
+ continue
518
+ }
519
+ seen[value] = struct{}{}
520
+ out = append(out, value)
521
+ }
522
+ return out
523
523
  }
524
524
 
525
525
  func init() {
526
- Register(boundariesElementTypes{})
527
- Register(boundariesExternal{})
528
- Register(boundariesEntryPoint{})
529
- Register(boundariesNoPrivate{})
530
- Register(boundariesNoUnknown{})
531
- Register(boundariesDependencies{})
526
+ Register(boundariesElementTypes{})
527
+ Register(boundariesExternal{})
528
+ Register(boundariesEntryPoint{})
529
+ Register(boundariesNoPrivate{})
530
+ Register(boundariesNoUnknown{})
531
+ Register(boundariesDependencies{})
532
532
  }