@ttsc/lint 0.30.4 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2520) hide show
  1. package/README.md +753 -741
  2. package/go.mod +7 -5
  3. package/internal/rulecode/rule_code_allocator_is_order_independent_and_append_only_test.go +119 -0
  4. package/internal/rulecode/rule_code_allocator_rejects_invalid_or_exhausted_ledgers_test.go +60 -0
  5. package/internal/rulecode/rulecode.go +18 -0
  6. package/lib/createTtscPlugin.d.ts +84 -0
  7. package/lib/createTtscPlugin.js +2704 -0
  8. package/lib/createTtscPlugin.js.map +1 -0
  9. package/lib/index.d.ts +1 -74
  10. package/lib/index.js +4 -2644
  11. package/lib/index.js.map +1 -1
  12. package/lib/internal/configEvaluatorFailure.d.ts +17 -9
  13. package/lib/internal/configEvaluatorFailure.js +17 -9
  14. package/lib/internal/configEvaluatorFailure.js.map +1 -1
  15. package/lib/internal/lintTrace.d.ts +18 -0
  16. package/lib/internal/lintTrace.js +99 -0
  17. package/lib/internal/lintTrace.js.map +1 -0
  18. package/lib/internal/normalizeContributors.d.ts +25 -0
  19. package/lib/internal/normalizeContributors.js +65 -0
  20. package/lib/internal/normalizeContributors.js.map +1 -0
  21. package/lib/structures/ITtscLintConfig.d.ts +25 -8
  22. package/lib/structures/ITtscLintPlugin.d.ts +13 -8
  23. package/lib/structures/ITtscLintPluginConfig.d.ts +18 -7
  24. package/lib/structures/ITtscLintPluginMeta.d.ts +10 -7
  25. package/lib/structures/TtscLintRuleSetting.d.ts +18 -13
  26. package/lib/structures/TtscLintSeverity.d.ts +5 -0
  27. package/lib/structures/format/ITtscLintFormat.d.ts +14 -8
  28. package/lib/structures/format/ITtscLintFormatJsDoc.d.ts +8 -1
  29. package/lib/structures/format/ITtscLintFormatSortImports.d.ts +14 -8
  30. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +133 -25
  31. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +3 -3
  32. package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +10 -5
  33. package/lib/structures/rules/ITtscLintContributorRules.d.ts +20 -13
  34. package/lib/structures/rules/ITtscLintCoreRuleOptions.d.ts +212 -24
  35. package/lib/structures/rules/ITtscLintCoreRules.d.ts +92 -72
  36. package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +8 -1
  37. package/lib/structures/rules/ITtscLintCypressRules.d.ts +24 -21
  38. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +140 -24
  39. package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +20 -12
  40. package/lib/structures/rules/ITtscLintJestRules.d.ts +22 -16
  41. package/lib/structures/rules/ITtscLintJsdocRules.d.ts +5 -0
  42. package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +24 -21
  43. package/lib/structures/rules/ITtscLintNextjsRules.d.ts +40 -42
  44. package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +24 -14
  45. package/lib/structures/rules/ITtscLintPromiseRules.d.ts +23 -14
  46. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +8 -1
  47. package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +18 -15
  48. package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +14 -4
  49. package/lib/structures/rules/ITtscLintReactRules.d.ts +33 -27
  50. package/lib/structures/rules/ITtscLintRegexpRules.d.ts +18 -4
  51. package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +88 -15
  52. package/lib/structures/rules/ITtscLintRules.d.ts +13 -9
  53. package/lib/structures/rules/ITtscLintSecurityRules.d.ts +33 -23
  54. package/lib/structures/rules/ITtscLintSolidRules.d.ts +57 -47
  55. package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +10 -2
  56. package/lib/structures/rules/ITtscLintStorybookRules.d.ts +52 -62
  57. package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +34 -30
  58. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +12 -3
  59. package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +20 -15
  60. package/lib/structures/rules/ITtscLintTypeScriptRuleOptions.d.ts +105 -16
  61. package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +62 -51
  62. package/lib/structures/rules/ITtscLintUnicornRuleOptions.d.ts +234 -46
  63. package/lib/structures/rules/ITtscLintUnicornRules.d.ts +97 -44
  64. package/lib/structures/rules/ITtscLintVitestRules.d.ts +19 -11
  65. package/lib/structures/rules/TtscLintContributorOverlay.d.ts +34 -0
  66. package/lib/structures/rules/TtscLintContributorOverlay.js +3 -0
  67. package/lib/structures/rules/TtscLintContributorOverlay.js.map +1 -0
  68. package/lib/structures/rules/index.d.ts +1 -0
  69. package/lib/structures/rules/index.js +1 -0
  70. package/lib/structures/rules/index.js.map +1 -1
  71. package/linthost/all_rule_names_returns_sorted_caller_owned_enumeration_test.go +72 -0
  72. package/linthost/as_bool_rejects_non_boolean_value_test.go +39 -0
  73. package/linthost/as_int_accepts_all_integer_types_and_rejects_fractional_test.go +77 -0
  74. package/linthost/as_string_rejects_non_string_value_test.go +35 -0
  75. package/linthost/as_string_slice_rejects_non_array_and_non_string_elements_test.go +45 -0
  76. package/linthost/ast_helpers.go +28 -89
  77. package/linthost/ast_helpers_destructuring_target_rejects_reads_inside_member_and_call_test.go +61 -0
  78. package/linthost/ast_selector_expression_class_excludes_type_literals_test.go +32 -0
  79. package/linthost/ast_selector_matcher.go +5 -0
  80. package/linthost/ast_selector_parser.go +5 -0
  81. package/linthost/astutil_find_keyword_is_identifier_aware_test.go +89 -0
  82. package/linthost/astutil_keyword_start_locates_leading_keyword_test.go +79 -0
  83. package/linthost/astutil_node_text_strips_leading_trivia_test.go +48 -0
  84. package/linthost/astutil_token_range_strips_leading_trivia_test.go +58 -0
  85. package/linthost/async_query_event_and_util_promises_test.go +55 -0
  86. package/linthost/await_thenable_await_expression_offers_exact_suggestion_test.go +40 -0
  87. package/linthost/await_thenable_await_union_with_promise_allows_test.go +42 -0
  88. package/linthost/await_thenable_await_using_async_disposable_allows_test.go +65 -0
  89. package/linthost/await_thenable_await_using_async_method_under_dispose_symbol_reports_test.go +57 -0
  90. package/linthost/await_thenable_await_using_helpers_test.go +44 -0
  91. package/linthost/await_thenable_await_using_multi_declarator_reports_only_sync_resource_test.go +65 -0
  92. package/linthost/await_thenable_await_using_protocol_abstractions_allows_test.go +67 -0
  93. package/linthost/await_thenable_await_using_protocol_abstractions_reports_test.go +75 -0
  94. package/linthost/await_thenable_await_using_sync_disposable_reports_test.go +62 -0
  95. package/linthost/await_thenable_await_using_sync_only_union_reports_test.go +64 -0
  96. package/linthost/await_thenable_await_using_union_with_async_disposable_allows_test.go +56 -0
  97. package/linthost/await_thenable_awaitability_type_parameter_boundaries_test.go +51 -0
  98. package/linthost/await_thenable_for_await_of_async_iterable_allows_test.go +63 -0
  99. package/linthost/await_thenable_for_await_of_protocol_abstractions_allows_test.go +67 -0
  100. package/linthost/await_thenable_for_await_of_protocol_abstractions_reports_test.go +75 -0
  101. package/linthost/await_thenable_for_await_of_sync_iterable_reports_test.go +65 -0
  102. package/linthost/await_thenable_for_await_of_sync_only_union_reports_test.go +55 -0
  103. package/linthost/await_thenable_preserves_migrated_all_family_contexts_test.go +20 -0
  104. package/linthost/await_thenable_promise_aggregator_awaitable_inputs_allow_test.go +50 -0
  105. package/linthost/await_thenable_promise_aggregator_container_shapes_report_test.go +53 -0
  106. package/linthost/await_thenable_promise_aggregator_generic_constraint_reports_test.go +45 -0
  107. package/linthost/await_thenable_promise_aggregator_iteration_yields_allow_test.go +50 -0
  108. package/linthost/await_thenable_promise_aggregator_iteration_yields_report_test.go +64 -0
  109. package/linthost/await_thenable_promise_aggregator_literal_members_report_test.go +56 -0
  110. package/linthost/await_thenable_promise_aggregator_native_identity_test.go +60 -0
  111. package/linthost/await_thenable_promise_aggregator_native_methods_report_test.go +50 -0
  112. package/linthost/await_thenable_promise_aggregator_noniterable_boundaries_allow_test.go +39 -0
  113. package/linthost/await_thenable_protocol_members_must_be_callable_test.go +70 -0
  114. package/linthost/await_thenable_structural_thenable_signature_boundary_test.go +53 -0
  115. package/linthost/ban_ts_comment_block_comment_ignores_directive_before_last_line_test.go +32 -0
  116. package/linthost/ban_ts_comment_block_comment_reports_directive_on_last_line_test.go +57 -0
  117. package/linthost/ban_ts_comment_block_comment_splits_last_line_on_all_line_terminators_test.go +55 -0
  118. package/linthost/ban_ts_comment_default_allows_described_expect_error_test.go +27 -0
  119. package/linthost/ban_ts_comment_default_allows_ts_check_test.go +26 -0
  120. package/linthost/ban_ts_comment_default_allows_ts_nocheck_after_first_statement_test.go +32 -0
  121. package/linthost/ban_ts_comment_default_does_not_fix_ts_ignore_test.go +25 -0
  122. package/linthost/ban_ts_comment_default_reports_ignore_with_upgrade_message_test.go +56 -0
  123. package/linthost/ban_ts_comment_default_reports_indented_ignore_with_position_test.go +39 -0
  124. package/linthost/ban_ts_comment_default_reports_ts_nocheck_before_code_test.go +44 -0
  125. package/linthost/ban_ts_comment_default_reports_ts_nocheck_without_statements_test.go +34 -0
  126. package/linthost/ban_ts_comment_default_requires_description_for_bare_expect_error_test.go +51 -0
  127. package/linthost/ban_ts_comment_description_length_counts_grapheme_clusters_test.go +58 -0
  128. package/linthost/ban_ts_comment_description_length_follows_unicode_16_graphemes_test.go +91 -0
  129. package/linthost/ban_ts_comment_follows_regex_in_nested_template_test.go +39 -0
  130. package/linthost/ban_ts_comment_ignores_directive_text_inside_strings_and_templates_test.go +48 -0
  131. package/linthost/ban_ts_comment_ignores_prose_and_near_miss_comments_test.go +34 -0
  132. package/linthost/ban_ts_comment_option_description_format_accepts_matching_description_test.go +36 -0
  133. package/linthost/ban_ts_comment_option_description_format_checks_length_first_test.go +49 -0
  134. package/linthost/ban_ts_comment_option_description_format_reports_mismatch_test.go +46 -0
  135. package/linthost/ban_ts_comment_option_empty_object_directive_allows_directive_test.go +26 -0
  136. package/linthost/ban_ts_comment_option_expect_error_false_allows_directive_test.go +28 -0
  137. package/linthost/ban_ts_comment_option_expect_error_true_reports_despite_description_test.go +41 -0
  138. package/linthost/ban_ts_comment_option_invalid_description_format_keeps_length_gate_test.go +52 -0
  139. package/linthost/ban_ts_comment_option_minimum_description_length_boundary_test.go +67 -0
  140. package/linthost/ban_ts_comment_option_ts_check_true_reports_pragma_anywhere_test.go +50 -0
  141. package/linthost/ban_ts_comment_option_ts_ignore_allow_with_description_test.go +57 -0
  142. package/linthost/ban_ts_comment_option_ts_nocheck_allow_with_description_test.go +57 -0
  143. package/linthost/ban_ts_comment_option_ts_nocheck_false_allows_directive_test.go +27 -0
  144. package/linthost/ban_ts_comment_option_unrecognized_value_keeps_default_policy_test.go +53 -0
  145. package/linthost/ban_ts_comment_pragma_ignores_block_comments_test.go +33 -0
  146. package/linthost/ban_ts_comment_pragma_requires_two_or_three_slashes_test.go +49 -0
  147. package/linthost/ban_ts_comment_pragma_wins_over_error_suppression_match_test.go +29 -0
  148. package/linthost/ban_ts_comment_preserves_migrated_defaults_and_options_test.go +29 -0
  149. package/linthost/ban_ts_comment_respects_inline_disable_next_line_test.go +28 -0
  150. package/linthost/ban_ts_comment_suggestion_compiler_error_boundary_test.go +56 -0
  151. package/linthost/ban_ts_comment_suggestion_rewrites_block_comment_ignore_test.go +40 -0
  152. package/linthost/ban_ts_comment_suggestion_rewrites_many_slash_line_comment_test.go +41 -0
  153. package/linthost/base_chain_walk_crosses_generic_boundary_test.go +165 -0
  154. package/linthost/behavioral_witness_audit_accepts_production_prerequisite_kinds_test.go +57 -0
  155. package/linthost/behavioral_witness_audit_publishes_one_deterministic_route_per_rule_test.go +45 -0
  156. package/linthost/behavioral_witness_audit_rejects_inert_public_rule_test.go +46 -0
  157. package/linthost/behavioral_witness_audit_rejects_invalid_non_canonical_candidate_test.go +49 -0
  158. package/linthost/behavioral_witness_coverage_test.go +379 -0
  159. package/linthost/behavioral_witness_kind_follows_rule_checker_requirement_test.go +69 -0
  160. package/linthost/binding_diagnostic_sites_helpers_test.go +31 -0
  161. package/linthost/blank_line_between_statements_returns_false_for_out_of_range_test.go +51 -0
  162. package/linthost/block_has_non_statement_comment_returns_false_for_out_of_range_test.go +56 -0
  163. package/linthost/block_has_non_statement_comment_skips_nil_stmts_test.go +42 -0
  164. package/linthost/boundaries_dependencies_alias_resolution_test.go +60 -0
  165. package/linthost/boundaries_dependencies_bare_core_builtin_test.go +36 -0
  166. package/linthost/boundaries_dependencies_command_test.go +67 -0
  167. package/linthost/boundaries_dependencies_declaration_file_test.go +50 -0
  168. package/linthost/boundaries_dependencies_default_test.go +36 -0
  169. package/linthost/boundaries_dependencies_from_to_test.go +66 -0
  170. package/linthost/boundaries_dependencies_import_kind_test.go +46 -0
  171. package/linthost/boundaries_dependencies_import_type_kinds_test.go +56 -0
  172. package/linthost/boundaries_dependencies_legacy_to_direction_test.go +43 -0
  173. package/linthost/boundaries_dependencies_local_gates_test.go +43 -0
  174. package/linthost/boundaries_dependencies_messages_test.go +58 -0
  175. package/linthost/boundaries_dependencies_options_test.go +66 -0
  176. package/linthost/boundaries_dependencies_origins_test.go +38 -0
  177. package/linthost/boundaries_dependencies_path_separators_test.go +36 -0
  178. package/linthost/boundaries_dependencies_policy_order_test.go +41 -0
  179. package/linthost/boundaries_dependencies_syntax_test.go +86 -0
  180. package/linthost/boundaries_dependencies_test.go +38 -0
  181. package/linthost/boundaries_dependencies_visibility_selectors_test.go +52 -0
  182. package/linthost/boundaries_element_types_deny_only_names_nothing_test.go +36 -0
  183. package/linthost/boundaries_element_types_ignores_dynamic_syntax_test.go +44 -0
  184. package/linthost/boundaries_element_types_names_the_allowed_set_test.go +40 -0
  185. package/linthost/boundaries_element_types_rejects_disallowed_import_test.go +43 -0
  186. package/linthost/boundaries_entry_point_rejects_non_entry_import_test.go +43 -0
  187. package/linthost/boundaries_external_deny_only_names_nothing_test.go +25 -0
  188. package/linthost/boundaries_external_names_the_allowed_set_test.go +30 -0
  189. package/linthost/boundaries_external_rejects_disallowed_package_test.go +34 -0
  190. package/linthost/boundaries_helpers_test.go +162 -0
  191. package/linthost/boundaries_no_private_rejects_cross_element_private_import_test.go +39 -0
  192. package/linthost/boundaries_no_unknown_rejects_unknown_import_target_test.go +43 -0
  193. package/linthost/check_observations.go +236 -0
  194. package/linthost/check_observations_retains_failed_program_and_raw_inputs_test.go +266 -0
  195. package/linthost/check_serve.go +23 -3
  196. package/linthost/check_serve_reuses_program_and_matches_cold_cycles_test.go +168 -0
  197. package/linthost/check_tag_names_publishes_canonical_hints_test.go +62 -0
  198. package/linthost/check_tag_names_test.go +30 -0
  199. package/linthost/check_values_test.go +31 -0
  200. package/linthost/command_build_emits_project_output_test.go +55 -0
  201. package/linthost/command_build_rejects_conflicting_emit_flags_test.go +32 -0
  202. package/linthost/command_check_applies_a_forwarded_null_reset_test.go +62 -0
  203. package/linthost/command_check_applies_forwarded_tsgo_flag_test.go +61 -0
  204. package/linthost/command_check_corpus_clean_project_exits_zero_test.go +41 -0
  205. package/linthost/command_check_corpus_ignores_future_optional_flags_test.go +34 -0
  206. package/linthost/command_check_corpus_reports_unknown_rule_names_test.go +25 -0
  207. package/linthost/command_check_honors_no_restricted_syntax_options_test.go +59 -0
  208. package/linthost/command_check_no_param_reassign_honors_props_config_test.go +46 -0
  209. package/linthost/command_check_no_restricted_imports_uses_real_config_options_test.go +53 -0
  210. package/linthost/command_check_preserves_compiler_argument_cwd_test.go +78 -0
  211. package/linthost/command_check_preserves_severity_exit_contract_test.go +54 -0
  212. package/linthost/command_check_rejects_invalid_no_param_reassign_options_before_linting_test.go +85 -0
  213. package/linthost/command_check_rejects_invalid_no_restricted_imports_options_before_linting_test.go +52 -0
  214. package/linthost/command_check_rejects_invalid_no_restricted_syntax_selector_test.go +41 -0
  215. package/linthost/command_check_relates_files_to_the_project_directory_test.go +40 -0
  216. package/linthost/command_check_reports_imported_sibling_workspace_source_test.go +45 -0
  217. package/linthost/command_check_reports_lint_diagnostic_test.go +44 -0
  218. package/linthost/command_check_reports_the_malformed_brace_it_used_to_bless_test.go +31 -0
  219. package/linthost/command_check_scopes_extends_rule_options_per_file_test.go +70 -0
  220. package/linthost/command_check_uses_parser_context_for_comment_consumers_test.go +61 -0
  221. package/linthost/command_check_warns_unknown_rules_test.go +41 -0
  222. package/linthost/command_fix_applies_both_lint_and_format_rule_edits_test.go +51 -0
  223. package/linthost/command_fix_applies_native_autofixes_test.go +48 -0
  224. package/linthost/command_fix_leaves_suggestion_only_rules_unchanged_test.go +46 -0
  225. package/linthost/command_fix_owns_its_source_reached_through_a_link_test.go +63 -0
  226. package/linthost/command_fix_rejects_emit_flag_test.go +39 -0
  227. package/linthost/command_fix_reports_but_never_rewrites_imported_sibling_source_test.go +65 -0
  228. package/linthost/command_fix_skips_default_formatting_that_format_applies_test.go +87 -0
  229. package/linthost/command_fix_unicorn_prevent_abbreviations_keeps_cross_file_merges_diagnostic_only_test.go +44 -0
  230. package/linthost/command_fix_unicorn_prevent_abbreviations_reparses_and_is_idempotent_test.go +37 -0
  231. package/linthost/command_fix_unicorn_switch_case_break_position_converges_and_is_idempotent_test.go +58 -0
  232. package/linthost/command_fix_unicorn_template_indent_converges_and_is_idempotent_test.go +43 -0
  233. package/linthost/command_format_applies_format_block_reflow_test.go +50 -0
  234. package/linthost/command_format_applies_format_rule_edits_test.go +54 -0
  235. package/linthost/command_format_arg_hugging_test.go +329 -0
  236. package/linthost/command_format_array_of_arrays_break_test.go +62 -0
  237. package/linthost/command_format_blank_line_in_list_test.go +69 -0
  238. package/linthost/command_format_brace_ownership_negative_twins_test.go +94 -0
  239. package/linthost/command_format_cedes_chained_arrow_body_test.go +50 -0
  240. package/linthost/command_format_cedes_closing_brace_under_wrapped_head_test.go +54 -0
  241. package/linthost/command_format_class_heritage_break_test.go +108 -0
  242. package/linthost/command_format_converges_on_leading_semi_guard_in_callback_test.go +69 -0
  243. package/linthost/command_format_decorated_declaration_indent_is_idempotent_test.go +57 -0
  244. package/linthost/command_format_default_import_single_specifier_break_test.go +26 -0
  245. package/linthost/command_format_display_width_test.go +33 -0
  246. package/linthost/command_format_expands_expression_nested_block_test.go +86 -0
  247. package/linthost/command_format_expression_nested_block_honors_crlf_test.go +39 -0
  248. package/linthost/command_format_fixture_corpus_test.go +179 -0
  249. package/linthost/command_format_honors_entry_ignores_alongside_rules_test.go +79 -0
  250. package/linthost/command_format_import_multi_specifier_from_overflow_break_test.go +27 -0
  251. package/linthost/command_format_indent_idempotency_helper_test.go +57 -0
  252. package/linthost/command_format_keeps_commented_statement_body_whole_test.go +23 -0
  253. package/linthost/command_format_keeps_empty_expression_nested_block_test.go +29 -0
  254. package/linthost/command_format_lays_out_a_statement_body_test.go +90 -0
  255. package/linthost/command_format_leaves_a_braceless_control_flow_body_alone_test.go +30 -0
  256. package/linthost/command_format_leaves_imported_sibling_source_untouched_test.go +68 -0
  257. package/linthost/command_format_leaves_prettier_shaped_mapped_types_untouched_test.go +39 -0
  258. package/linthost/command_format_leaves_prettier_shaped_type_members_untouched_test.go +41 -0
  259. package/linthost/command_format_leaves_token_spacing_untouched_test.go +66 -0
  260. package/linthost/command_format_multiple_callbacks_test.go +150 -0
  261. package/linthost/command_format_nested_ternary_indent_test.go +67 -0
  262. package/linthost/command_format_nested_ternary_parens_test.go +74 -0
  263. package/linthost/command_format_numeric_array_fill_test.go +94 -0
  264. package/linthost/command_format_preserves_braceless_for_body_indent_test.go +28 -0
  265. package/linthost/command_format_preserves_braceless_if_try_body_indent_test.go +30 -0
  266. package/linthost/command_format_preserves_class_typeparam_heritage_inline_test.go +27 -0
  267. package/linthost/command_format_preserves_comments_in_reflow_test.go +66 -0
  268. package/linthost/command_format_preserves_crlf_across_reflow_rules_test.go +73 -0
  269. package/linthost/command_format_preserves_generic_arg_multiline_type_literal_indent_test.go +30 -0
  270. package/linthost/command_format_preserves_generic_arg_type_literal_indent_test.go +30 -0
  271. package/linthost/command_format_preserves_interface_qualified_heritage_own_line_test.go +28 -0
  272. package/linthost/command_format_preserves_intersection_generic_type_literal_indent_test.go +36 -0
  273. package/linthost/command_format_preserves_multi_type_heritage_empty_body_test.go +28 -0
  274. package/linthost/command_format_preserves_multiline_type_param_heritage_test.go +30 -0
  275. package/linthost/command_format_preserves_nested_variable_type_literal_indent_test.go +27 -0
  276. package/linthost/command_format_preserves_param_type_literal_indent_test.go +62 -0
  277. package/linthost/command_format_preserves_union_member_type_literal_indent_test.go +28 -0
  278. package/linthost/command_format_print_width_abstains_inside_binary_expression_test.go +84 -0
  279. package/linthost/command_format_print_width_cascades_with_semi_and_quotes_test.go +62 -0
  280. package/linthost/command_format_print_width_converges_on_unbraced_control_flow_test.go +176 -0
  281. package/linthost/command_format_rejects_emit_flag_test.go +39 -0
  282. package/linthost/command_format_respects_resolved_entry_applicability_test.go +219 -0
  283. package/linthost/command_format_restores_class_member_indent_from_flat_test.go +61 -0
  284. package/linthost/command_format_restores_closing_braces_from_flat_test.go +64 -0
  285. package/linthost/command_format_restores_decorated_member_indent_from_flat_test.go +61 -0
  286. package/linthost/command_format_restores_decorated_namespace_class_indent_from_flat_test.go +62 -0
  287. package/linthost/command_format_restores_decorated_nested_class_indent_from_flat_test.go +64 -0
  288. package/linthost/command_format_restores_decorated_nested_function_indent_from_flat_test.go +60 -0
  289. package/linthost/command_format_restores_decorated_nested_interface_indent_from_flat_test.go +59 -0
  290. package/linthost/command_format_restores_nested_class_indent_from_flat_test.go +60 -0
  291. package/linthost/command_format_restores_stranded_brace_from_one_line_block_test.go +140 -0
  292. package/linthost/command_format_restores_switch_indent_from_flat_test.go +63 -0
  293. package/linthost/command_format_return_typed_arrow_hug_test.go +74 -0
  294. package/linthost/command_format_round2_coverage_test.go +57 -0
  295. package/linthost/command_format_round2_hug_fixes_test.go +70 -0
  296. package/linthost/command_format_round3_force_break_test.go +49 -0
  297. package/linthost/command_format_settles_a_member_terminator_on_a_padded_line_test.go +34 -0
  298. package/linthost/command_format_single_specifier_abstain_does_not_block_multi_break_test.go +56 -0
  299. package/linthost/command_format_single_specifier_stays_inline_test.go +60 -0
  300. package/linthost/command_format_split_call_collapses_flat_once_isolated_test.go +54 -0
  301. package/linthost/command_format_spread_comment_test.go +36 -0
  302. package/linthost/command_format_stranded_brace_honors_crlf_test.go +51 -0
  303. package/linthost/command_format_structural_rules_are_idempotent_on_their_own_output_test.go +51 -0
  304. package/linthost/command_format_structural_rules_converge_on_headline_input_test.go +56 -0
  305. package/linthost/command_format_structural_rules_converge_on_nested_block_test.go +56 -0
  306. package/linthost/command_format_switch_case_block_indent_test.go +80 -0
  307. package/linthost/command_format_terminates_a_split_interface_member_test.go +34 -0
  308. package/linthost/command_format_test_call_hug_test.go +92 -0
  309. package/linthost/command_format_wrapped_function_body_indent_test.go +43 -0
  310. package/linthost/command_lint_corpus_semantics_helpers_test.go +29 -0
  311. package/linthost/command_prints_version_test.go +38 -0
  312. package/linthost/command_rejects_conflicting_emit_flags_test.go +33 -0
  313. package/linthost/command_rejects_unknown_test.go +32 -0
  314. package/linthost/command_requires_argument_test.go +32 -0
  315. package/linthost/command_transform_normalizes_dot_segments_in_file_path_test.go +49 -0
  316. package/linthost/command_transform_outputs_requested_file_test.go +43 -0
  317. package/linthost/command_transform_requires_file_test.go +32 -0
  318. package/linthost/comment_scan.go +3 -2
  319. package/linthost/comment_scan_handles_malformed_parser_recovery_test.go +59 -0
  320. package/linthost/comment_scan_uses_parser_lexical_ranges_across_source_modes_test.go +109 -0
  321. package/linthost/compile.go +177 -38
  322. package/linthost/compile_user_pattern_caches_option_regex_test.go +70 -0
  323. package/linthost/config.go +954 -269
  324. package/linthost/config_cache_does_not_memoize_failed_evaluation_test.go +63 -0
  325. package/linthost/config_cache_portable_dependency_policies_test.go +471 -0
  326. package/linthost/config_cache_preserves_pattern_precedence_test.go +96 -0
  327. package/linthost/config_cache_reuses_evaluation_until_content_changes_test.go +81 -0
  328. package/linthost/config_fixture_helpers_test.go +70 -0
  329. package/linthost/config_format.go +5 -5
  330. package/linthost/config_glob.go +517 -0
  331. package/linthost/config_glob_bounds_matching_work_test.go +115 -0
  332. package/linthost/config_glob_preserves_expansion_semantics_test.go +128 -0
  333. package/linthost/config_glob_preserves_stored_case_recovery_test.go +64 -0
  334. package/linthost/config_json.go +85 -0
  335. package/linthost/config_loader_sources_escape_every_literal_percent_test.go +81 -0
  336. package/linthost/config_store_option_fold_honors_both_entry_orders_test.go +70 -0
  337. package/linthost/config_store_resolves_options_with_entry_scope_test.go +95 -0
  338. package/linthost/config_store_severity_only_override_inherits_matching_options_test.go +53 -0
  339. package/linthost/config_store_validates_every_scoped_option_variant_test.go +55 -0
  340. package/linthost/consistent_return_accepts_functions_that_return_on_every_path_through_switch_and_try_test.go +43 -0
  341. package/linthost/context_report_range_suggestion_separates_opt_in_edits_test.go +76 -0
  342. package/linthost/contrib_adapter.go +3 -1
  343. package/linthost/contrib_adapter_to_internal_text_edits_returns_nil_for_empty_input_test.go +34 -0
  344. package/linthost/contrib_adapter_to_internal_text_edits_round_trips_three_edits_test.go +40 -0
  345. package/linthost/contributor_ast_only_marker_skips_standalone_checker_test.go +52 -0
  346. package/linthost/contributor_bootstrap_is_single_owner_for_reusable_main_test.go +425 -0
  347. package/linthost/contributor_cannot_mutate_later_invocation_options_test.go +55 -0
  348. package/linthost/contributor_diagnostic_ranges_are_bounded_test.go +139 -0
  349. package/linthost/contributor_generic_accepts_options_method_keeps_legacy_payload_test.go +81 -0
  350. package/linthost/contributor_metadata_panic_is_rejected_test.go +84 -0
  351. package/linthost/contributor_optionless_marker_rejects_payload_test.go +63 -0
  352. package/linthost/contributor_panics_preserve_other_rules_in_process_test.go +111 -0
  353. package/linthost/contributor_range_fix_bounds_diagnostic_independently_from_edit_test.go +52 -0
  354. package/linthost/contributor_report_related_reaches_finding_test.go +101 -0
  355. package/linthost/contributor_rule_decodes_options_through_public_context_test.go +75 -0
  356. package/linthost/contributor_rule_opt_out_skips_declaration_files_test.go +56 -0
  357. package/linthost/contributor_rule_receives_and_reports_configured_severity_test.go +65 -0
  358. package/linthost/contributor_rules_visit_declaration_files_by_default_test.go +50 -0
  359. package/linthost/contributor_tagged_rule_marks_findings_test.go +78 -0
  360. package/linthost/contributor_type_aware_marker_keeps_checker_test.go +50 -0
  361. package/linthost/contributor_without_tag_marker_leaves_findings_untagged_test.go +61 -0
  362. package/linthost/cypress_assertion_before_screenshot_allows_immediately_prior_assertion_test.go +33 -0
  363. package/linthost/cypress_assertion_before_screenshot_allows_same_chain_assertion_test.go +31 -0
  364. package/linthost/cypress_assertion_before_screenshot_reports_unchecked_screenshot_test.go +34 -0
  365. package/linthost/cypress_assertion_before_screenshot_reports_unrelated_prior_assertion_test.go +36 -0
  366. package/linthost/cypress_finding_helpers_test.go +14 -0
  367. package/linthost/cypress_no_and_reports_chain_starting_and_test.go +35 -0
  368. package/linthost/cypress_no_assigning_return_values_reports_cy_assignment_test.go +35 -0
  369. package/linthost/cypress_no_async_before_reports_async_before_each_test.go +37 -0
  370. package/linthost/cypress_no_async_tests_reports_async_it_test.go +37 -0
  371. package/linthost/cypress_no_chained_get_reports_second_get_test.go +34 -0
  372. package/linthost/cypress_no_debug_reports_debug_command_test.go +34 -0
  373. package/linthost/cypress_no_force_reports_force_true_option_test.go +34 -0
  374. package/linthost/cypress_no_pause_reports_pause_command_test.go +34 -0
  375. package/linthost/cypress_no_unnecessary_waiting_reports_numeric_wait_test.go +35 -0
  376. package/linthost/cypress_no_xpath_reports_xpath_command_test.go +34 -0
  377. package/linthost/cypress_require_data_selectors_reports_class_selector_test.go +36 -0
  378. package/linthost/cypress_unsafe_to_chain_command_reports_action_middle_test.go +35 -0
  379. package/linthost/declaration_file_allowlist_names_are_registered_rules_test.go +50 -0
  380. package/linthost/default_case_accepts_block_comment_marker_test.go +28 -0
  381. package/linthost/default_case_accepts_case_insensitive_marker_test.go +28 -0
  382. package/linthost/default_case_accepts_empty_switch_test.go +24 -0
  383. package/linthost/default_case_accepts_existing_default_clause_test.go +29 -0
  384. package/linthost/default_case_accepts_no_default_marker_test.go +28 -0
  385. package/linthost/default_case_custom_pattern_replaces_default_marker_test.go +30 -0
  386. package/linthost/default_case_helpers_test.go +58 -0
  387. package/linthost/default_case_honors_custom_comment_pattern_test.go +28 -0
  388. package/linthost/default_case_invalid_comment_pattern_falls_back_to_default_test.go +28 -0
  389. package/linthost/default_case_rejects_marker_with_trailing_text_test.go +28 -0
  390. package/linthost/default_case_rejects_unrelated_trailing_comment_test.go +28 -0
  391. package/linthost/default_case_reports_switch_without_default_test.go +27 -0
  392. package/linthost/default_case_requires_marker_to_be_last_comment_test.go +30 -0
  393. package/linthost/diagnostic_codes_distinguish_former_collision_across_cli_and_lsp_test.go +97 -0
  394. package/linthost/dispatch.go +29 -9
  395. package/linthost/dispatch_array_literal_breaks_when_overflows_test.go +38 -0
  396. package/linthost/dispatch_array_literal_falls_back_when_element_nil_test.go +53 -0
  397. package/linthost/dispatch_array_literal_falls_back_when_elements_nil_test.go +48 -0
  398. package/linthost/dispatch_array_literal_flat_when_fits_test.go +34 -0
  399. package/linthost/dispatch_array_literal_returns_empty_for_nil_node_test.go +31 -0
  400. package/linthost/dispatch_arrow_function_block_body_reindents_consistently_test.go +41 -0
  401. package/linthost/dispatch_arrow_function_returns_covered_for_nil_node_test.go +38 -0
  402. package/linthost/dispatch_arrow_function_returns_verbatim_for_nil_body_test.go +46 -0
  403. package/linthost/dispatch_block_collapses_empty_body_to_braces_test.go +40 -0
  404. package/linthost/dispatch_block_keeps_covered_for_single_line_statements_test.go +42 -0
  405. package/linthost/dispatch_block_preserves_blank_line_between_statements_test.go +41 -0
  406. package/linthost/dispatch_block_reports_uncovered_for_comment_only_body_test.go +37 -0
  407. package/linthost/dispatch_block_reports_uncovered_for_inter_statement_comment_test.go +37 -0
  408. package/linthost/dispatch_block_returns_covered_for_nil_node_test.go +34 -0
  409. package/linthost/dispatch_block_returns_verbatim_for_nil_statement_test.go +47 -0
  410. package/linthost/dispatch_block_returns_verbatim_for_nil_statements_test.go +44 -0
  411. package/linthost/dispatch_call_breaks_expression_body_arrow_argument_when_overflows_test.go +44 -0
  412. package/linthost/dispatch_call_breaks_hugged_object_when_flat_form_overflows_test.go +42 -0
  413. package/linthost/dispatch_call_explodes_when_hugged_callback_header_overflows_test.go +45 -0
  414. package/linthost/dispatch_call_explodes_when_hugged_object_header_overflows_test.go +43 -0
  415. package/linthost/dispatch_call_expression_breaks_arguments_when_overflows_test.go +40 -0
  416. package/linthost/dispatch_call_expression_flat_when_fits_test.go +33 -0
  417. package/linthost/dispatch_call_hugs_last_callback_argument_test.go +41 -0
  418. package/linthost/dispatch_call_keeps_hugged_object_flat_when_it_fits_test.go +40 -0
  419. package/linthost/dispatch_expression_statement_returns_covered_for_nil_node_test.go +36 -0
  420. package/linthost/dispatch_expression_statement_returns_verbatim_for_dirty_tail_test.go +44 -0
  421. package/linthost/dispatch_expression_statement_returns_verbatim_for_nil_expression_test.go +44 -0
  422. package/linthost/dispatch_function_expression_block_body_reindents_test.go +43 -0
  423. package/linthost/dispatch_function_expression_returns_covered_for_nil_node_test.go +36 -0
  424. package/linthost/dispatch_function_expression_returns_verbatim_for_nil_body_test.go +44 -0
  425. package/linthost/dispatch_function_like_returns_verbatim_for_out_of_range_body_test.go +50 -0
  426. package/linthost/dispatch_function_like_taints_covered_for_multiline_signature_test.go +38 -0
  427. package/linthost/dispatch_import_declaration_falls_back_for_default_import_test.go +32 -0
  428. package/linthost/dispatch_import_declaration_falls_back_for_import_attributes_test.go +33 -0
  429. package/linthost/dispatch_import_declaration_falls_back_for_namespace_import_test.go +37 -0
  430. package/linthost/dispatch_import_declaration_falls_back_for_side_effect_import_test.go +36 -0
  431. package/linthost/dispatch_import_declaration_omits_semicolon_when_absent_test.go +37 -0
  432. package/linthost/dispatch_import_declaration_preserves_type_only_keyword_test.go +34 -0
  433. package/linthost/dispatch_import_declaration_returns_empty_for_nil_node_test.go +30 -0
  434. package/linthost/dispatch_import_declaration_threads_clauses_test.go +35 -0
  435. package/linthost/dispatch_named_exports_breaks_when_overflows_test.go +38 -0
  436. package/linthost/dispatch_named_exports_falls_back_when_elements_nil_test.go +49 -0
  437. package/linthost/dispatch_named_exports_falls_back_when_specifier_nil_test.go +51 -0
  438. package/linthost/dispatch_named_exports_flat_when_fits_test.go +33 -0
  439. package/linthost/dispatch_named_exports_returns_empty_for_nil_node_test.go +31 -0
  440. package/linthost/dispatch_named_imports_breaks_when_overflows_test.go +37 -0
  441. package/linthost/dispatch_named_imports_falls_back_when_elements_nil_test.go +50 -0
  442. package/linthost/dispatch_named_imports_falls_back_when_specifier_nil_test.go +54 -0
  443. package/linthost/dispatch_named_imports_flat_when_fits_test.go +34 -0
  444. package/linthost/dispatch_named_imports_returns_empty_for_nil_node_test.go +30 -0
  445. package/linthost/dispatch_nested_callback_reflows_at_every_depth_test.go +52 -0
  446. package/linthost/dispatch_new_expression_breaks_arguments_when_overflows_test.go +39 -0
  447. package/linthost/dispatch_new_expression_flat_when_fits_test.go +36 -0
  448. package/linthost/dispatch_object_literal_breaks_when_overflows_test.go +40 -0
  449. package/linthost/dispatch_object_literal_falls_back_when_properties_nil_test.go +49 -0
  450. package/linthost/dispatch_object_literal_falls_back_when_property_nil_test.go +52 -0
  451. package/linthost/dispatch_object_literal_flat_when_fits_test.go +33 -0
  452. package/linthost/dispatch_object_literal_returns_empty_for_nil_node_test.go +31 -0
  453. package/linthost/dispatch_parenthesized_expression_reflows_inner_test.go +42 -0
  454. package/linthost/dispatch_parenthesized_expression_returns_covered_for_nil_node_test.go +35 -0
  455. package/linthost/dispatch_parenthesized_expression_returns_verbatim_for_nil_inner_test.go +44 -0
  456. package/linthost/dispatch_reports_uncovered_for_multiline_verbatim_subtree_test.go +42 -0
  457. package/linthost/dispatch_return_statement_reflows_returned_expression_test.go +45 -0
  458. package/linthost/dispatch_return_statement_returns_covered_for_nil_node_test.go +36 -0
  459. package/linthost/dispatch_return_statement_returns_verbatim_for_bare_return_test.go +41 -0
  460. package/linthost/dispatch_return_statement_returns_verbatim_for_dirty_tail_test.go +43 -0
  461. package/linthost/dispatch_verbatim_fallback_preserves_unknown_kinds_test.go +41 -0
  462. package/linthost/display_width.go +29 -5
  463. package/linthost/display_width_after_last_newline_measures_tail_test.go +33 -0
  464. package/linthost/display_width_from_column_expands_tabs_to_stops_test.go +49 -0
  465. package/linthost/display_width_matches_prettier_get_string_width_test.go +124 -0
  466. package/linthost/display_width_oracle_preconditions_test.go +32 -0
  467. package/linthost/doc_join_returns_nil_for_empty_parts_test.go +33 -0
  468. package/linthost/dot_notation_declines_fix_when_comment_in_bracket_span_test.go +40 -0
  469. package/linthost/dot_notation_fix_bracket_to_dot_for_identifier_key_test.go +27 -0
  470. package/linthost/dot_notation_fix_keeps_bracket_for_reserved_word_test.go +28 -0
  471. package/linthost/dot_notation_fix_spaces_decimal_integer_receiver_test.go +76 -0
  472. package/linthost/dot_notation_offers_reserved_word_collapse_as_suggestion_test.go +36 -0
  473. package/linthost/dot_notation_offers_withheld_bracket_collapse_as_suggestion_test.go +37 -0
  474. package/linthost/dot_notation_skips_invalid_identifier_key_test.go +27 -0
  475. package/linthost/editor_format_overrides_accepts_utf8_bom_test.go +155 -0
  476. package/linthost/editor_format_overrides_combined_sections_follow_source_order_test.go +58 -0
  477. package/linthost/editor_format_overrides_drive_idempotent_output_test.go +69 -0
  478. package/linthost/editor_format_overrides_duplicate_language_section_uses_last_value_test.go +55 -0
  479. package/linthost/editor_format_overrides_equivalent_exact_sections_use_last_scope_test.go +52 -0
  480. package/linthost/editor_format_overrides_language_section_wins_test.go +37 -0
  481. package/linthost/editor_format_overrides_normalize_full_language_selectors_test.go +44 -0
  482. package/linthost/editor_format_overrides_reads_vscode_settings_test.go +45 -0
  483. package/linthost/editor_format_overrides_reject_malformed_language_selectors_test.go +36 -0
  484. package/linthost/editor_format_overrides_single_language_precedence_is_deterministic_test.go +51 -0
  485. package/linthost/editor_format_overrides_supported_language_ids_test.go +60 -0
  486. package/linthost/empty_tags_test.go +27 -0
  487. package/linthost/engine.go +523 -91
  488. package/linthost/engine_accepts_null_tuple_slot_as_absent_options_test.go +37 -0
  489. package/linthost/engine_accepts_payload_for_option_rule_test.go +36 -0
  490. package/linthost/engine_accepts_severity_only_optionless_rule_test.go +28 -0
  491. package/linthost/engine_align_uses_current_column_test.go +27 -0
  492. package/linthost/engine_block_disable_after_code_does_not_suppress_earlier_same_line_test.go +47 -0
  493. package/linthost/engine_conditional_group_empty_renders_nothing_test.go +24 -0
  494. package/linthost/engine_conditional_group_falls_back_to_last_option_test.go +30 -0
  495. package/linthost/engine_conditional_group_picks_first_fitting_option_test.go +31 -0
  496. package/linthost/engine_crlf_terminator_emits_carriage_returns_test.go +24 -0
  497. package/linthost/engine_dedupes_duplicate_kinds_in_visits_test.go +64 -0
  498. package/linthost/engine_detects_files_without_enabled_rules_test.go +40 -0
  499. package/linthost/engine_directive_accepts_typescript_namespace_prefix_test.go +48 -0
  500. package/linthost/engine_directive_after_template_expression_test.go +37 -0
  501. package/linthost/engine_directive_records_unknown_rule_in_unknown_channel_test.go +65 -0
  502. package/linthost/engine_directive_rejects_legacy_typescript_eslint_prefix_test.go +50 -0
  503. package/linthost/engine_directive_without_rules_disables_all_rules_on_target_line_test.go +57 -0
  504. package/linthost/engine_disable_line_multiline_block_comment_targets_end_line_test.go +50 -0
  505. package/linthost/engine_dispatches_only_to_interested_rules_test.go +81 -0
  506. package/linthost/engine_end_of_line_defaults_to_lf_when_empty_test.go +23 -0
  507. package/linthost/engine_fits_first_line_counts_flat_group_lines_test.go +25 -0
  508. package/linthost/engine_fits_first_line_stops_at_first_break_test.go +85 -0
  509. package/linthost/engine_fits_measures_conditional_group_as_first_option_test.go +25 -0
  510. package/linthost/engine_fits_rejects_forced_break_group_test.go +22 -0
  511. package/linthost/engine_fits_returns_false_when_remaining_negative_test.go +21 -0
  512. package/linthost/engine_fits_treats_indent_align_as_transparent_in_flat_test.go +34 -0
  513. package/linthost/engine_flatten_resolves_breaks_to_flat_form_test.go +57 -0
  514. package/linthost/engine_group_break_flag_forces_broken_layout_test.go +29 -0
  515. package/linthost/engine_group_breaks_when_overflows_width_test.go +30 -0
  516. package/linthost/engine_group_collapses_when_fits_width_test.go +28 -0
  517. package/linthost/engine_hardline_forces_break_regardless_of_width_test.go +23 -0
  518. package/linthost/engine_ifbreak_picks_broken_branch_when_group_breaks_test.go +32 -0
  519. package/linthost/engine_ifbreak_picks_flat_branch_when_group_fits_test.go +28 -0
  520. package/linthost/engine_ignores_directive_text_inside_strings_test.go +45 -0
  521. package/linthost/engine_ignores_jsx_text_inline_disable_markers_test.go +54 -0
  522. package/linthost/engine_indent_compounds_inside_group_test.go +20 -0
  523. package/linthost/engine_line_suffix_attaches_to_next_break_test.go +33 -0
  524. package/linthost/engine_line_suffix_drain_preserves_embedded_newline_test.go +23 -0
  525. package/linthost/engine_line_suffix_drains_inline_when_no_break_follows_test.go +28 -0
  526. package/linthost/engine_line_suffix_flush_preserves_embedded_newline_test.go +28 -0
  527. package/linthost/engine_literalline_emits_newline_at_column_zero_test.go +24 -0
  528. package/linthost/engine_preserves_migrated_disable_directive_population_test.go +46 -0
  529. package/linthost/engine_print_width_defaults_when_zero_test.go +39 -0
  530. package/linthost/engine_quarantines_panicking_rule_per_file_test.go +110 -0
  531. package/linthost/engine_records_unknown_rules_test.go +42 -0
  532. package/linthost/engine_recovers_from_rule_panic_test.go +68 -0
  533. package/linthost/engine_rejects_legacy_typescript_eslint_prefix_test.go +39 -0
  534. package/linthost/engine_rejects_optionless_payload_while_rule_is_off_test.go +37 -0
  535. package/linthost/engine_rejects_payload_shapes_for_optionless_rule_test.go +46 -0
  536. package/linthost/engine_requires_type_checker_for_contributor_rule_test.go +43 -0
  537. package/linthost/engine_requires_type_checker_for_prefer_const_test.go +33 -0
  538. package/linthost/engine_requires_type_checker_for_type_aware_rule_test.go +35 -0
  539. package/linthost/engine_respects_block_disable_enable_test.go +48 -0
  540. package/linthost/engine_respects_eslint_disable_line_test.go +45 -0
  541. package/linthost/engine_respects_eslint_disable_next_line_test.go +48 -0
  542. package/linthost/engine_respects_lint_disable_next_line_alias_test.go +46 -0
  543. package/linthost/engine_run_parallel_matches_serial_finding_set_test.go +86 -0
  544. package/linthost/engine_runs_format_rules_on_declaration_files_test.go +37 -0
  545. package/linthost/engine_runs_opt_in_rules_on_declaration_files_test.go +39 -0
  546. package/linthost/engine_skips_off_rules_test.go +41 -0
  547. package/linthost/engine_skips_type_checker_for_ast_only_rule_test.go +35 -0
  548. package/linthost/engine_skips_value_rules_on_declaration_files_test.go +40 -0
  549. package/linthost/engine_softline_emits_newline_when_group_breaks_test.go +23 -0
  550. package/linthost/engine_softline_renders_empty_when_flat_test.go +22 -0
  551. package/linthost/engine_starting_indent_offsets_break_decision_test.go +29 -0
  552. package/linthost/engine_tab_width_defaults_when_zero_test.go +24 -0
  553. package/linthost/engine_text_renders_verbatim_test.go +29 -0
  554. package/linthost/engine_text_with_embedded_newline_forces_break_test.go +24 -0
  555. package/linthost/engine_use_tabs_emits_remainder_spaces_test.go +27 -0
  556. package/linthost/engine_use_tabs_emits_tab_characters_test.go +24 -0
  557. package/linthost/eqeqeq_offers_unsafe_operator_rewrite_as_suggestion_test.go +45 -0
  558. package/linthost/expect_matchers_without_argument_do_not_panic_test.go +50 -0
  559. package/linthost/file_path_from_uri_preserves_literal_percent_escapes_test.go +36 -0
  560. package/linthost/file_url_matches_node_shape_test.go +64 -0
  561. package/linthost/files_selector_scopes_rules_away_from_an_imported_sibling_test.go +70 -0
  562. package/linthost/filter_format_findings_keeps_only_format_rule_findings_test.go +56 -0
  563. package/linthost/filter_known_flags_preserves_known_values_and_skips_unknowns_test.go +49 -0
  564. package/linthost/filter_known_flags_resolves_names_case_insensitively_test.go +43 -0
  565. package/linthost/filter_lint_findings_drops_format_rule_findings_test.go +43 -0
  566. package/linthost/find_lint_config_file_discovers_nearest_ancestor_test.go +37 -0
  567. package/linthost/find_lint_config_file_discovers_plain_lint_config_test.go +37 -0
  568. package/linthost/find_lint_config_file_falls_back_to_cwd_for_out_of_tree_tsconfig_test.go +43 -0
  569. package/linthost/find_lint_config_file_prefers_nearest_directory_test.go +38 -0
  570. package/linthost/find_lint_config_file_rejects_same_directory_conflicts_test.go +38 -0
  571. package/linthost/find_lint_config_file_uses_tsconfig_directory_when_outside_cwd_test.go +45 -0
  572. package/linthost/find_lint_entry_accepts_sorted_check_plugin_payload_test.go +53 -0
  573. package/linthost/fix.go +37 -11
  574. package/linthost/fix_eqeqeq_replaces_same_type_literal_operator_test.go +26 -0
  575. package/linthost/fix_eqeqeq_replaces_typeof_operator_test.go +26 -0
  576. package/linthost/fix_eqeqeq_requires_both_operands_to_share_a_primitive_kind_test.go +29 -0
  577. package/linthost/fix_eqeqeq_skips_unsafe_identifier_comparison_test.go +25 -0
  578. package/linthost/fix_interleaved_import_type_and_bracket_spacing_stays_valid_test.go +113 -0
  579. package/linthost/fix_no_extra_bind_removes_safe_member_and_call_syntax_test.go +45 -0
  580. package/linthost/fix_no_extra_bind_skips_effectful_or_commented_removals_test.go +55 -0
  581. package/linthost/fix_no_extra_non_null_assertion_drops_trailing_bang_test.go +39 -0
  582. package/linthost/fix_no_import_type_side_effects_hoists_type_keyword_test.go +29 -0
  583. package/linthost/fix_no_import_type_side_effects_preserves_leading_comment_test.go +30 -0
  584. package/linthost/fix_no_import_type_side_effects_skips_comment_import_keyword_test.go +31 -0
  585. package/linthost/fix_no_import_type_side_effects_skips_mixed_import_test.go +28 -0
  586. package/linthost/fix_no_unnecessary_type_constraint_disambiguates_cts_generic_arrow_test.go +20 -0
  587. package/linthost/fix_no_unnecessary_type_constraint_disambiguates_mts_generic_arrow_test.go +20 -0
  588. package/linthost/fix_no_unnecessary_type_constraint_disambiguates_tsx_generic_arrow_test.go +20 -0
  589. package/linthost/fix_no_unnecessary_type_constraint_drops_extends_clause_test.go +28 -0
  590. package/linthost/fix_no_unnecessary_type_constraint_keeps_default_unambiguous_test.go +20 -0
  591. package/linthost/fix_no_unnecessary_type_constraint_keeps_multiple_parameters_unambiguous_test.go +20 -0
  592. package/linthost/fix_no_unnecessary_type_constraint_keeps_non_arrow_declarations_minimal_test.go +28 -0
  593. package/linthost/fix_no_unnecessary_type_constraint_keeps_ts_generic_arrow_minimal_test.go +20 -0
  594. package/linthost/fix_no_unnecessary_type_constraint_preserves_comma_comments_test.go +22 -0
  595. package/linthost/fix_no_unnecessary_type_constraint_preserves_existing_trailing_comma_test.go +20 -0
  596. package/linthost/fix_no_useless_escape_drops_backslash_test.go +28 -0
  597. package/linthost/fix_no_useless_escape_drops_nondigit_neighbors_of_octal_exemption_test.go +31 -0
  598. package/linthost/fix_no_useless_escape_skips_backslash_digit_escapes_test.go +48 -0
  599. package/linthost/fix_no_useless_escape_skips_tagged_template_test.go +29 -0
  600. package/linthost/fix_no_useless_escape_skips_template_substitution_escape_test.go +45 -0
  601. package/linthost/fix_no_useless_rename_drops_rename_tail_test.go +39 -0
  602. package/linthost/fix_no_useless_rename_skips_string_literal_alias_test.go +34 -0
  603. package/linthost/fix_no_var_fixes_despite_label_before_test.go +30 -0
  604. package/linthost/fix_no_var_fixes_despite_member_name_before_test.go +29 -0
  605. package/linthost/fix_no_var_fixes_despite_object_key_before_test.go +30 -0
  606. package/linthost/fix_no_var_fixes_despite_type_reference_before_test.go +32 -0
  607. package/linthost/fix_no_var_keeps_bindings_observable_by_direct_eval_test.go +41 -0
  608. package/linthost/fix_no_var_preserves_script_global_object_bindings_test.go +30 -0
  609. package/linthost/fix_no_var_replaces_closure_reference_without_loop_test.go +30 -0
  610. package/linthost/fix_no_var_replaces_for_header_binding_test.go +31 -0
  611. package/linthost/fix_no_var_replaces_for_in_header_binding_test.go +31 -0
  612. package/linthost/fix_no_var_replaces_for_of_header_binding_test.go +31 -0
  613. package/linthost/fix_no_var_replaces_loop_local_without_closure_test.go +30 -0
  614. package/linthost/fix_no_var_replaces_namespace_block_binding_test.go +28 -0
  615. package/linthost/fix_no_var_replaces_reassigned_binding_test.go +30 -0
  616. package/linthost/fix_no_var_replaces_reference_in_nested_block_test.go +30 -0
  617. package/linthost/fix_no_var_replaces_reference_inside_with_body_test.go +30 -0
  618. package/linthost/fix_no_var_replaces_same_block_references_test.go +30 -0
  619. package/linthost/fix_no_var_replaces_same_case_clause_references_test.go +30 -0
  620. package/linthost/fix_no_var_replaces_unique_binding_test.go +30 -0
  621. package/linthost/fix_no_var_replaces_var_keyword_test.go +28 -0
  622. package/linthost/fix_no_var_skips_block_scope_escape_test.go +37 -0
  623. package/linthost/fix_no_var_skips_catch_binding_redeclaration_test.go +36 -0
  624. package/linthost/fix_no_var_skips_class_field_capture_in_loop_test.go +38 -0
  625. package/linthost/fix_no_var_skips_cross_case_reference_test.go +36 -0
  626. package/linthost/fix_no_var_skips_cross_scope_same_name_over_decline_test.go +36 -0
  627. package/linthost/fix_no_var_skips_deferred_self_reference_in_init_test.go +45 -0
  628. package/linthost/fix_no_var_skips_direct_self_reference_in_init_test.go +37 -0
  629. package/linthost/fix_no_var_skips_for_header_closure_capture_test.go +38 -0
  630. package/linthost/fix_no_var_skips_for_header_multi_declarator_test.go +32 -0
  631. package/linthost/fix_no_var_skips_for_header_redeclaration_test.go +36 -0
  632. package/linthost/fix_no_var_skips_for_header_use_after_loop_test.go +37 -0
  633. package/linthost/fix_no_var_skips_for_in_annex_b_initializer_test.go +33 -0
  634. package/linthost/fix_no_var_skips_for_in_header_expression_self_reference_test.go +37 -0
  635. package/linthost/fix_no_var_skips_for_of_destructuring_header_test.go +32 -0
  636. package/linthost/fix_no_var_skips_for_of_header_closure_capture_test.go +38 -0
  637. package/linthost/fix_no_var_skips_for_of_header_expression_self_reference_test.go +36 -0
  638. package/linthost/fix_no_var_skips_function_declaration_redeclaration_test.go +39 -0
  639. package/linthost/fix_no_var_skips_function_scope_escape_test.go +28 -0
  640. package/linthost/fix_no_var_skips_iife_self_reference_in_init_test.go +39 -0
  641. package/linthost/fix_no_var_skips_let_as_binding_name_test.go +32 -0
  642. package/linthost/fix_no_var_skips_loop_closure_capture_test.go +37 -0
  643. package/linthost/fix_no_var_skips_mixed_destructure_redeclaration_test.go +38 -0
  644. package/linthost/fix_no_var_skips_mixed_destructure_use_before_test.go +36 -0
  645. package/linthost/fix_no_var_skips_parameter_redeclaration_test.go +28 -0
  646. package/linthost/fix_no_var_skips_redeclaration_test.go +37 -0
  647. package/linthost/fix_no_var_skips_shorthand_value_before_test.go +37 -0
  648. package/linthost/fix_no_var_skips_single_statement_position_test.go +33 -0
  649. package/linthost/fix_no_var_skips_typeof_self_reference_in_init_test.go +38 -0
  650. package/linthost/fix_no_var_skips_use_before_declaration_test.go +36 -0
  651. package/linthost/fix_no_var_skips_use_before_for_header_test.go +36 -0
  652. package/linthost/fix_no_var_skips_while_loop_closure_capture_test.go +35 -0
  653. package/linthost/fix_no_var_skips_with_statement_body_test.go +35 -0
  654. package/linthost/fix_no_wrapper_object_types_replaces_typename_test.go +28 -0
  655. package/linthost/fix_no_wrapper_object_types_replaces_unshadowed_const_test.go +30 -0
  656. package/linthost/fix_no_wrapper_object_types_skips_function_shadow_test.go +27 -0
  657. package/linthost/fix_no_wrapper_object_types_skips_import_equals_shadow_test.go +26 -0
  658. package/linthost/fix_no_wrapper_object_types_skips_imported_name_test.go +26 -0
  659. package/linthost/fix_no_wrapper_object_types_skips_user_shadowed_name_test.go +27 -0
  660. package/linthost/fix_object_shorthand_drops_value_tail_test.go +28 -0
  661. package/linthost/fix_object_shorthand_preserves_the_prototype_setter_test.go +28 -0
  662. package/linthost/fix_prefer_as_const_preserves_comment_before_literal_type_test.go +27 -0
  663. package/linthost/fix_prefer_as_const_replaces_angle_bracket_type_with_const_test.go +27 -0
  664. package/linthost/fix_prefer_as_const_replaces_literal_type_with_const_test.go +27 -0
  665. package/linthost/fix_prefer_as_const_replaces_parenthesized_literal_assertion_test.go +28 -0
  666. package/linthost/fix_prefer_as_const_replaces_parenthesized_literal_type_test.go +28 -0
  667. package/linthost/fix_prefer_as_const_skips_null_literal_assertion_test.go +26 -0
  668. package/linthost/fix_prefer_as_const_skips_property_annotation_rewrite_test.go +27 -0
  669. package/linthost/fix_prefer_as_const_skips_template_literal_assertion_test.go +28 -0
  670. package/linthost/fix_prefer_as_const_skips_variable_annotation_rewrite_test.go +27 -0
  671. package/linthost/fix_prefer_const_counts_nested_write_in_shorthand_default_test.go +25 -0
  672. package/linthost/fix_prefer_const_keeps_nonlocal_rewrites_diagnostic_only_test.go +54 -0
  673. package/linthost/fix_prefer_const_preserves_assertion_wrapped_assignment_targets_test.go +68 -0
  674. package/linthost/fix_prefer_const_replaces_let_with_fresh_for_of_binding_test.go +29 -0
  675. package/linthost/fix_prefer_const_replaces_single_let_keyword_test.go +26 -0
  676. package/linthost/fix_prefer_const_replaces_wholly_stable_destructuring_keyword_test.go +26 -0
  677. package/linthost/fix_prefer_const_skips_destructuring_assignment_targets_test.go +42 -0
  678. package/linthost/fix_prefer_const_skips_for_in_reassignment_test.go +28 -0
  679. package/linthost/fix_prefer_const_skips_for_of_reassignment_test.go +29 -0
  680. package/linthost/fix_prefer_const_skips_multi_declaration_list_test.go +32 -0
  681. package/linthost/fix_prefer_namespace_keyword_replaces_module_keyword_test.go +29 -0
  682. package/linthost/fix_regexp_no_useless_flag_deletes_the_flag_it_named_test.go +74 -0
  683. package/linthost/fix_regexp_no_useless_quantifier_drops_exactly_one_repeat_test.go +57 -0
  684. package/linthost/fix_regexp_no_useless_two_nums_quantifier_collapses_equal_bounds_test.go +50 -0
  685. package/linthost/fix_regexp_no_zero_quantifier_stays_diagnostic_only_test.go +39 -0
  686. package/linthost/fix_regexp_prefer_d_replaces_spelled_out_digit_class_test.go +49 -0
  687. package/linthost/fix_regexp_prefer_plus_quantifier_replaces_open_ended_one_test.go +45 -0
  688. package/linthost/fix_regexp_prefer_question_quantifier_replaces_zero_to_one_test.go +43 -0
  689. package/linthost/fix_regexp_prefer_star_quantifier_replaces_open_ended_zero_test.go +43 -0
  690. package/linthost/fix_regexp_prefer_w_replaces_spelled_out_word_class_test.go +46 -0
  691. package/linthost/fix_regexp_require_unicode_regexp_offers_u_and_v_suggestions_test.go +71 -0
  692. package/linthost/fix_regexp_require_unicode_sets_regexp_offers_the_v_flag_test.go +76 -0
  693. package/linthost/fix_regexp_sort_flags_rewrites_flag_run_in_canonical_order_test.go +48 -0
  694. package/linthost/fix_regexp_withholds_a_rewrite_the_regex_parser_rejects_test.go +62 -0
  695. package/linthost/fix_security_detect_new_buffer_offers_three_successors_test.go +93 -0
  696. package/linthost/fix_security_detect_pseudo_random_bytes_proves_automatic_rename_test.go +95 -0
  697. package/linthost/fix_select_text_edit_groups_collapses_duplicate_edit_within_finding_test.go +42 -0
  698. package/linthost/fix_select_text_edit_groups_drops_partially_overlapped_finding_whole_test.go +43 -0
  699. package/linthost/fix_select_text_edit_groups_drops_self_overlapping_finding_test.go +32 -0
  700. package/linthost/fix_select_text_edit_groups_keeps_disjoint_multi_edit_finding_whole_test.go +41 -0
  701. package/linthost/fix_select_text_edits_drops_coincident_zero_width_insert_test.go +57 -0
  702. package/linthost/fix_select_text_edits_drops_duplicate_edits_test.go +38 -0
  703. package/linthost/fix_select_text_edits_drops_overlapping_ranges_test.go +32 -0
  704. package/linthost/fix_solid_imports_rewrites_sole_specifier_module_test.go +65 -0
  705. package/linthost/fix_solid_no_react_specific_props_renames_react_props_test.go +66 -0
  706. package/linthost/fix_storybook_no_renderer_packages_offers_framework_packages_test.go +95 -0
  707. package/linthost/fix_tsx_grammar_keeps_jsx_while_rewriting_var_and_let_test.go +36 -0
  708. package/linthost/flags_gen.go +2 -2
  709. package/linthost/for_direction_honors_a_negated_compound_step_test.go +37 -0
  710. package/linthost/format.go +14 -4
  711. package/linthost/format_arrow_parens_abstains_on_comment_near_trailing_comma_test.go +68 -0
  712. package/linthost/format_arrow_parens_abstains_on_param_comment_test.go +44 -0
  713. package/linthost/format_arrow_parens_avoid_keeps_return_type_parens_test.go +24 -0
  714. package/linthost/format_arrow_parens_avoid_keeps_type_parameter_parens_test.go +23 -0
  715. package/linthost/format_arrow_parens_idempotent_on_wrapped_test.go +24 -0
  716. package/linthost/format_arrow_parens_keeps_destructured_param_under_avoid_test.go +24 -0
  717. package/linthost/format_arrow_parens_keeps_ineligible_trailing_comma_params_test.go +66 -0
  718. package/linthost/format_arrow_parens_keeps_trailing_comma_param_under_always_test.go +48 -0
  719. package/linthost/format_arrow_parens_keeps_typed_param_under_avoid_test.go +24 -0
  720. package/linthost/format_arrow_parens_strips_async_single_param_test.go +26 -0
  721. package/linthost/format_arrow_parens_strips_single_param_under_avoid_test.go +24 -0
  722. package/linthost/format_arrow_parens_strips_trailing_comma_param_under_avoid_test.go +51 -0
  723. package/linthost/format_arrow_parens_strips_wrapped_param_before_list_comma_test.go +32 -0
  724. package/linthost/format_arrow_parens_wraps_bare_single_param_test.go +25 -0
  725. package/linthost/format_block_absent_keeps_format_rules_off_test.go +42 -0
  726. package/linthost/format_block_default_severity_off_keeps_format_rules_out_of_check_test.go +48 -0
  727. package/linthost/format_block_drops_format_rule_in_rules_map_test.go +45 -0
  728. package/linthost/format_block_expands_nil_raw_to_empty_map_test.go +32 -0
  729. package/linthost/format_block_jsdoc_false_skips_rule_test.go +37 -0
  730. package/linthost/format_block_propagates_jsdoc_sort_tags_option_test.go +59 -0
  731. package/linthost/format_block_propagates_prettier_options_to_rule_test.go +159 -0
  732. package/linthost/format_block_propagates_sort_imports_options_test.go +70 -0
  733. package/linthost/format_block_rejects_empty_sort_imports_order_test.go +37 -0
  734. package/linthost/format_block_rejects_invalid_jsdoc_options_test.go +68 -0
  735. package/linthost/format_block_rejects_invalid_severity_test.go +33 -0
  736. package/linthost/format_block_rejects_invalid_trailing_comma_value_test.go +36 -0
  737. package/linthost/format_block_rejects_non_array_sort_imports_order_test.go +32 -0
  738. package/linthost/format_block_rejects_non_bool_or_object_jsdoc_test.go +36 -0
  739. package/linthost/format_block_rejects_non_bool_or_object_sort_imports_test.go +30 -0
  740. package/linthost/format_block_rejects_non_bool_semi_test.go +32 -0
  741. package/linthost/format_block_rejects_non_bool_single_quote_test.go +31 -0
  742. package/linthost/format_block_rejects_non_bool_sort_imports_options_test.go +45 -0
  743. package/linthost/format_block_rejects_non_bool_use_tabs_test.go +31 -0
  744. package/linthost/format_block_rejects_non_int_print_width_test.go +31 -0
  745. package/linthost/format_block_rejects_non_int_tab_width_test.go +32 -0
  746. package/linthost/format_block_rejects_non_string_end_of_line_test.go +48 -0
  747. package/linthost/format_block_rejects_non_string_trailing_comma_test.go +32 -0
  748. package/linthost/format_block_rejects_unknown_key_test.go +39 -0
  749. package/linthost/format_block_rejects_unknown_sort_imports_key_test.go +36 -0
  750. package/linthost/format_block_severity_warning_enables_check_diagnostics_test.go +48 -0
  751. package/linthost/format_block_sort_imports_false_keeps_rule_off_test.go +27 -0
  752. package/linthost/format_block_sort_imports_true_enables_defaults_test.go +37 -0
  753. package/linthost/format_block_targets_option_accepting_rules_test.go +90 -0
  754. package/linthost/format_block_threads_end_of_line_into_sort_imports_test.go +55 -0
  755. package/linthost/format_block_wins_over_vscode_settings_test.go +36 -0
  756. package/linthost/format_brace_continuation_corrects_a_pushed_keyword_at_the_wrong_column_test.go +28 -0
  757. package/linthost/format_brace_continuation_honors_crlf_end_of_line_test.go +29 -0
  758. package/linthost/format_brace_continuation_indents_a_pushed_keyword_to_its_statement_test.go +27 -0
  759. package/linthost/format_brace_continuation_is_idempotent_in_both_directions_test.go +32 -0
  760. package/linthost/format_brace_continuation_leaves_an_if_without_an_else_alone_test.go +23 -0
  761. package/linthost/format_brace_continuation_normalizes_a_zero_width_gap_test.go +27 -0
  762. package/linthost/format_brace_continuation_pulls_catch_and_finally_onto_their_braces_test.go +28 -0
  763. package/linthost/format_brace_continuation_pulls_do_while_onto_the_closing_brace_test.go +27 -0
  764. package/linthost/format_brace_continuation_pulls_else_onto_the_closing_brace_test.go +27 -0
  765. package/linthost/format_brace_continuation_pulls_finally_onto_a_try_without_a_catch_test.go +28 -0
  766. package/linthost/format_brace_continuation_pushes_a_do_while_off_a_statement_body_test.go +28 -0
  767. package/linthost/format_brace_continuation_pushes_else_off_a_statement_consequent_test.go +28 -0
  768. package/linthost/format_brace_continuation_pushes_past_a_brace_terminated_non_block_test.go +28 -0
  769. package/linthost/format_brace_continuation_pushes_past_a_label_prefix_test.go +48 -0
  770. package/linthost/format_brace_continuation_settles_a_shared_line_through_the_cascade_test.go +44 -0
  771. package/linthost/format_brace_continuation_skips_a_commented_gap_test.go +28 -0
  772. package/linthost/format_brace_continuation_waits_for_a_statement_to_own_its_line_test.go +27 -0
  773. package/linthost/format_bracket_spacing_idempotent_on_padded_test.go +23 -0
  774. package/linthost/format_bracket_spacing_leaves_a_prettier_shaped_type_literal_alone_test.go +27 -0
  775. package/linthost/format_bracket_spacing_leaves_empty_object_test.go +74 -0
  776. package/linthost/format_bracket_spacing_pads_an_unspaced_type_literal_test.go +29 -0
  777. package/linthost/format_bracket_spacing_pads_destructure_test.go +24 -0
  778. package/linthost/format_bracket_spacing_pads_import_attributes_test.go +28 -0
  779. package/linthost/format_bracket_spacing_pads_mapped_type_test.go +27 -0
  780. package/linthost/format_bracket_spacing_pads_named_imports_test.go +24 -0
  781. package/linthost/format_bracket_spacing_pads_object_literal_test.go +26 -0
  782. package/linthost/format_bracket_spacing_strips_object_literal_under_false_test.go +26 -0
  783. package/linthost/format_clause_join_charges_the_else_width_budget_at_its_limit_test.go +37 -0
  784. package/linthost/format_clause_join_charges_the_shift_to_the_header_lines_indent_test.go +45 -0
  785. package/linthost/format_clause_join_emits_no_shift_when_the_column_is_unchanged_test.go +50 -0
  786. package/linthost/format_clause_join_hoists_across_a_multiline_template_without_moving_it_test.go +30 -0
  787. package/linthost/format_clause_join_idempotent_on_joined_body_test.go +27 -0
  788. package/linthost/format_clause_join_joins_do_body_test.go +27 -0
  789. package/linthost/format_clause_join_joins_else_body_test.go +27 -0
  790. package/linthost/format_clause_join_joins_else_if_chain_across_lines_test.go +44 -0
  791. package/linthost/format_clause_join_joins_for_and_while_bodies_test.go +32 -0
  792. package/linthost/format_clause_join_joins_labeled_block_body_test.go +31 -0
  793. package/linthost/format_clause_join_joins_single_if_body_test.go +28 -0
  794. package/linthost/format_clause_join_joins_with_body_test.go +27 -0
  795. package/linthost/format_clause_join_keeps_a_blank_line_inside_a_hoisted_body_test.go +45 -0
  796. package/linthost/format_clause_join_keeps_overlong_body_broken_test.go +31 -0
  797. package/linthost/format_clause_join_leaves_a_block_comment_interior_untouched_test.go +45 -0
  798. package/linthost/format_clause_join_leaves_a_string_continuation_untouched_test.go +45 -0
  799. package/linthost/format_clause_join_leaves_a_template_literal_type_untouched_test.go +49 -0
  800. package/linthost/format_clause_join_reindents_a_hoisted_body_inside_a_function_test.go +43 -0
  801. package/linthost/format_clause_join_reindents_a_hoisted_else_if_chain_test.go +45 -0
  802. package/linthost/format_clause_join_reindents_a_hoisted_labeled_block_test.go +27 -0
  803. package/linthost/format_clause_join_reindents_an_indentable_block_comment_test.go +50 -0
  804. package/linthost/format_clause_join_settles_a_deep_staircase_within_the_cascade_budget_test.go +44 -0
  805. package/linthost/format_clause_join_shifts_a_tab_indented_body_with_tabs_test.go +44 -0
  806. package/linthost/format_clause_join_skips_braced_body_test.go +31 -0
  807. package/linthost/format_clause_join_skips_braced_else_and_do_bodies_test.go +38 -0
  808. package/linthost/format_clause_join_skips_commented_else_gap_test.go +29 -0
  809. package/linthost/format_clause_join_skips_empty_else_and_do_bodies_test.go +33 -0
  810. package/linthost/format_clause_join_skips_empty_statement_body_test.go +36 -0
  811. package/linthost/format_command_resolver_keeps_configured_options_inside_matching_entry_test.go +64 -0
  812. package/linthost/format_command_resolver_skips_upgrade_for_entry_ignored_file_test.go +60 -0
  813. package/linthost/format_command_resolver_skips_upgrade_for_file_outside_entry_files_test.go +61 -0
  814. package/linthost/format_command_resolver_variants_replace_bare_options_with_reachable_defaults_test.go +34 -0
  815. package/linthost/format_declaration_header_abstains_on_comment_in_header_test.go +25 -0
  816. package/linthost/format_declaration_header_abstains_on_type_params_with_multi_clause_test.go +27 -0
  817. package/linthost/format_declaration_header_breaks_empty_body_at_width_boundary_test.go +32 -0
  818. package/linthost/format_declaration_header_breaks_generic_heritage_type_args_test.go +28 -0
  819. package/linthost/format_declaration_header_breaks_multi_type_interface_test.go +29 -0
  820. package/linthost/format_declaration_header_breaks_multiple_clauses_test.go +25 -0
  821. package/linthost/format_declaration_header_breaks_single_type_clause_in_multi_clause_test.go +73 -0
  822. package/linthost/format_declaration_header_breaks_type_param_default_after_equals_test.go +29 -0
  823. package/linthost/format_declaration_header_collapses_fitting_header_test.go +29 -0
  824. package/linthost/format_declaration_header_drops_brace_for_class_body_test.go +28 -0
  825. package/linthost/format_declaration_header_explodes_and_drops_brace_for_class_body_test.go +27 -0
  826. package/linthost/format_declaration_header_explodes_type_parameters_test.go +26 -0
  827. package/linthost/format_declaration_header_generic_heritage_honors_crlf_end_of_line_test.go +32 -0
  828. package/linthost/format_declaration_header_glues_brace_for_empty_body_test.go +27 -0
  829. package/linthost/format_declaration_header_idempotent_on_broken_clauses_test.go +24 -0
  830. package/linthost/format_declaration_header_idempotent_on_broken_heritage_type_args_test.go +25 -0
  831. package/linthost/format_declaration_header_idempotent_on_exploded_class_body_test.go +25 -0
  832. package/linthost/format_declaration_header_keeps_multi_type_inline_after_break_test.go +30 -0
  833. package/linthost/format_declaration_header_keeps_single_generic_heritage_arg_inline_test.go +25 -0
  834. package/linthost/format_declaration_header_keeps_single_heritage_type_inline_test.go +26 -0
  835. package/linthost/format_declaration_header_multi_clause_honors_crlf_end_of_line_test.go +30 -0
  836. package/linthost/format_declaration_header_multi_type_honors_crlf_end_of_line_test.go +30 -0
  837. package/linthost/format_declaration_header_type_param_explode_honors_crlf_end_of_line_test.go +32 -0
  838. package/linthost/format_defaults_apply_without_format_config_test.go +46 -0
  839. package/linthost/format_indent_case_block_body_matches_case_depth_test.go +30 -0
  840. package/linthost/format_indent_cedes_body_under_multiline_arrow_head_test.go +39 -0
  841. package/linthost/format_indent_cedes_callback_argument_body_test.go +31 -0
  842. package/linthost/format_indent_defers_shared_line_to_statement_split_test.go +32 -0
  843. package/linthost/format_indent_honors_custom_tab_width_test.go +28 -0
  844. package/linthost/format_indent_honors_use_tabs_option_test.go +28 -0
  845. package/linthost/format_indent_idempotent_on_correct_class_body_test.go +27 -0
  846. package/linthost/format_indent_idempotent_on_correct_nested_block_test.go +26 -0
  847. package/linthost/format_indent_idempotent_on_decorated_member_test.go +29 -0
  848. package/linthost/format_indent_normalizes_class_method_body_depth_test.go +29 -0
  849. package/linthost/format_indent_normalizes_decorated_member_declaration_line_test.go +31 -0
  850. package/linthost/format_indent_normalizes_multiple_decorator_lines_test.go +30 -0
  851. package/linthost/format_indent_normalizes_over_indented_block_statement_test.go +27 -0
  852. package/linthost/format_indent_normalizes_plain_member_header_test.go +29 -0
  853. package/linthost/format_indent_normalizes_same_line_decorated_member_test.go +49 -0
  854. package/linthost/format_indent_normalizes_switch_case_body_depth_test.go +29 -0
  855. package/linthost/format_indent_still_fixes_single_line_head_arrow_body_test.go +27 -0
  856. package/linthost/format_indent_strips_leading_indent_from_top_level_statement_test.go +27 -0
  857. package/linthost/format_jsdoc_honors_custom_tag_synonyms_option_test.go +26 -0
  858. package/linthost/format_jsdoc_preserves_example_block_body_test.go +63 -0
  859. package/linthost/format_jsdoc_rejects_malformed_tag_synonym_value_test.go +60 -0
  860. package/linthost/format_jsdoc_rewrites_arg_synonyms_to_param_test.go +25 -0
  861. package/linthost/format_jsdoc_rewrites_return_to_returns_test.go +24 -0
  862. package/linthost/format_jsdoc_skips_canonical_tags_test.go +32 -0
  863. package/linthost/format_jsdoc_skips_inline_at_text_test.go +34 -0
  864. package/linthost/format_jsdoc_skips_jsdoc_like_strings_in_source_test.go +41 -0
  865. package/linthost/format_orphan_semi_inert_under_semi_true_test.go +24 -0
  866. package/linthost/format_orphan_semi_merges_guard_under_no_semi_test.go +35 -0
  867. package/linthost/format_orphan_semi_skips_comment_between_guard_and_statement_test.go +28 -0
  868. package/linthost/format_orphan_semi_skips_non_hazard_successor_test.go +29 -0
  869. package/linthost/format_parameter_properties_breaks_multi_param_constructor_test.go +30 -0
  870. package/linthost/format_parameter_properties_breaks_override_only_constructor_test.go +31 -0
  871. package/linthost/format_parameter_properties_honors_crlf_end_of_line_test.go +29 -0
  872. package/linthost/format_parameter_properties_idempotent_on_broken_list_test.go +28 -0
  873. package/linthost/format_parameter_properties_ignores_decorated_plain_params_test.go +31 -0
  874. package/linthost/format_parameter_properties_ignores_plain_params_test.go +27 -0
  875. package/linthost/format_parameter_properties_keeps_single_param_inline_test.go +30 -0
  876. package/linthost/format_prettier_conformance_e2e_test.go +367 -0
  877. package/linthost/format_print_width_abstains_inside_jsx_expression_test.go +50 -0
  878. package/linthost/format_print_width_abstains_inside_template_substitution_test.go +31 -0
  879. package/linthost/format_print_width_abstains_when_callback_body_holds_uncovered_statement_test.go +37 -0
  880. package/linthost/format_print_width_abstains_when_inter_member_comment_present_test.go +32 -0
  881. package/linthost/format_print_width_abstains_when_trailing_block_comment_before_close_bracket_test.go +35 -0
  882. package/linthost/format_print_width_breaks_array_rest_assignment_target_without_comma_test.go +31 -0
  883. package/linthost/format_print_width_breaks_call_when_trailing_semicolon_overflows_test.go +26 -0
  884. package/linthost/format_print_width_breaks_default_plus_named_import_shape_test.go +29 -0
  885. package/linthost/format_print_width_breaks_long_call_arguments_test.go +31 -0
  886. package/linthost/format_print_width_breaks_long_named_exports_test.go +30 -0
  887. package/linthost/format_print_width_breaks_long_named_imports_test.go +30 -0
  888. package/linthost/format_print_width_breaks_long_new_expression_arguments_test.go +31 -0
  889. package/linthost/format_print_width_breaks_long_object_literal_test.go +27 -0
  890. package/linthost/format_print_width_breaks_overflowing_react_hook_deps_array_test.go +29 -0
  891. package/linthost/format_print_width_check_abstains_when_ctx_is_nil_test.go +24 -0
  892. package/linthost/format_print_width_check_abstains_when_node_is_nil_test.go +48 -0
  893. package/linthost/format_print_width_check_abstains_when_node_range_exceeds_context_source_test.go +71 -0
  894. package/linthost/format_print_width_declines_last_arg_hug_after_arrow_lead_test.go +29 -0
  895. package/linthost/format_print_width_declines_last_arg_hug_after_callback_test.go +28 -0
  896. package/linthost/format_print_width_default_width_is_80_columns_test.go +31 -0
  897. package/linthost/format_print_width_explodes_call_when_hugged_header_overflows_test.go +26 -0
  898. package/linthost/format_print_width_hangs_broken_ternary_arm_under_arm_column_test.go +40 -0
  899. package/linthost/format_print_width_has_non_child_comments_returns_false_when_node_is_nil_test.go +46 -0
  900. package/linthost/format_print_width_has_reflow_ancestor_returns_false_when_node_is_nil_test.go +40 -0
  901. package/linthost/format_print_width_honors_crlf_end_of_line_test.go +30 -0
  902. package/linthost/format_print_width_honors_custom_tab_width_test.go +27 -0
  903. package/linthost/format_print_width_honors_tab_leading_source_test.go +27 -0
  904. package/linthost/format_print_width_honors_use_tabs_option_test.go +25 -0
  905. package/linthost/format_print_width_hugs_arrow_with_object_body_test.go +32 -0
  906. package/linthost/format_print_width_hugs_first_callback_argument_test.go +31 -0
  907. package/linthost/format_print_width_hugs_first_callback_with_array_arg_test.go +27 -0
  908. package/linthost/format_print_width_hugs_object_argument_despite_long_trailing_suffix_test.go +32 -0
  909. package/linthost/format_print_width_idempotent_on_already_reflowed_input_test.go +26 -0
  910. package/linthost/format_print_width_idempotent_on_first_hugged_call_test.go +25 -0
  911. package/linthost/format_print_width_idempotent_on_hugged_callback_call_test.go +25 -0
  912. package/linthost/format_print_width_idempotent_on_nested_ternary_staircase_test.go +25 -0
  913. package/linthost/format_print_width_indents_nested_alternate_ternary_test.go +30 -0
  914. package/linthost/format_print_width_indents_nested_consequent_ternary_test.go +30 -0
  915. package/linthost/format_print_width_indents_relative_to_line_leading_indent_test.go +42 -0
  916. package/linthost/format_print_width_inserts_after_non_rest_object_assignment_target_test.go +30 -0
  917. package/linthost/format_print_width_inserts_after_object_spread_in_value_literal_test.go +30 -0
  918. package/linthost/format_print_width_keeps_call_with_trailing_line_comment_inline_test.go +24 -0
  919. package/linthost/format_print_width_keeps_empty_array_literal_flat_test.go +25 -0
  920. package/linthost/format_print_width_keeps_empty_object_literal_flat_test.go +28 -0
  921. package/linthost/format_print_width_keeps_nested_object_that_fits_test.go +24 -0
  922. package/linthost/format_print_width_keeps_object_rest_assignment_target_without_comma_test.go +29 -0
  923. package/linthost/format_print_width_keeps_react_hook_hugged_past_open_line_test.go +26 -0
  924. package/linthost/format_print_width_keeps_short_call_with_callback_hugged_test.go +32 -0
  925. package/linthost/format_print_width_keeps_short_ternary_flat_test.go +27 -0
  926. package/linthost/format_print_width_leading_column_returns_zero_when_pos_is_nonpositive_test.go +51 -0
  927. package/linthost/format_print_width_line_leading_indent_uses_two_when_tab_width_nonpositive_test.go +47 -0
  928. package/linthost/format_print_width_max_line_width_uses_two_when_tab_width_nonpositive_test.go +47 -0
  929. package/linthost/format_print_width_preserves_blank_line_in_reflowed_callback_body_test.go +29 -0
  930. package/linthost/format_print_width_preserves_call_type_arguments_test.go +32 -0
  931. package/linthost/format_print_width_preserves_leading_jsdoc_above_reflowed_node_test.go +44 -0
  932. package/linthost/format_print_width_preserves_multiline_object_test.go +30 -0
  933. package/linthost/format_print_width_preserves_optional_call_token_test.go +32 -0
  934. package/linthost/format_print_width_preserves_terminator_decision_on_imports_test.go +42 -0
  935. package/linthost/format_print_width_reflows_call_with_nested_object_argument_test.go +33 -0
  936. package/linthost/format_print_width_reflows_wide_array_with_slash_strings_test.go +34 -0
  937. package/linthost/format_print_width_reindents_callback_body_inside_indented_block_test.go +33 -0
  938. package/linthost/format_print_width_skips_namespace_import_shape_test.go +28 -0
  939. package/linthost/format_print_width_skips_nested_target_when_ancestor_covers_it_test.go +58 -0
  940. package/linthost/format_print_width_skips_short_object_literal_test.go +29 -0
  941. package/linthost/format_print_width_slice_contains_newline_clamps_out_of_range_bounds_test.go +57 -0
  942. package/linthost/format_print_width_ternary_arm_indent_bonus_test.go +44 -0
  943. package/linthost/format_print_width_trailing_line_width_excludes_trailing_line_comment_test.go +38 -0
  944. package/linthost/format_print_width_trailing_line_width_handles_guards_and_tabs_test.go +51 -0
  945. package/linthost/format_quote_props_consistent_preserves_cooked_identifier_keys_test.go +37 -0
  946. package/linthost/format_quote_props_consistent_quotes_mixed_object_test.go +28 -0
  947. package/linthost/format_quote_props_consistent_unquotes_all_identifier_keys_test.go +24 -0
  948. package/linthost/format_quote_props_consistent_unquotes_proto_with_identifier_keys_test.go +21 -0
  949. package/linthost/format_quote_props_keeps_non_identifier_key_test.go +24 -0
  950. package/linthost/format_quote_props_keeps_numeric_key_test.go +20 -0
  951. package/linthost/format_quote_props_preserve_is_noop_test.go +23 -0
  952. package/linthost/format_quote_props_unquotes_class_method_test.go +30 -0
  953. package/linthost/format_quote_props_unquotes_identifier_keys_test.go +25 -0
  954. package/linthost/format_quote_props_unquotes_interface_member_test.go +28 -0
  955. package/linthost/format_quote_props_unquotes_proto_key_without_changing_setter_semantics_test.go +21 -0
  956. package/linthost/format_quote_props_unquotes_reserved_word_key_test.go +25 -0
  957. package/linthost/format_quote_props_unquotes_type_literal_member_test.go +28 -0
  958. package/linthost/format_quotes_converts_double_to_single_preserving_apostrophe_escape_test.go +23 -0
  959. package/linthost/format_quotes_converts_single_to_double_test.go +22 -0
  960. package/linthost/format_quotes_escapes_double_quote_when_converting_test.go +22 -0
  961. package/linthost/format_quotes_honors_prefer_single_option_test.go +27 -0
  962. package/linthost/format_quotes_keeps_double_on_escape_tie_test.go +29 -0
  963. package/linthost/format_quotes_keeps_double_with_redundant_single_escape_test.go +31 -0
  964. package/linthost/format_quotes_keeps_single_with_redundant_double_escape_test.go +31 -0
  965. package/linthost/format_quotes_preserves_strings_with_unescaped_double_quotes_test.go +34 -0
  966. package/linthost/format_quotes_skips_double_quoted_literals_test.go +24 -0
  967. package/linthost/format_quotes_skips_jsx_attribute_strings_test.go +44 -0
  968. package/linthost/format_quotes_skips_template_literals_test.go +38 -0
  969. package/linthost/format_quotes_switches_double_to_single_to_minimize_escapes_test.go +31 -0
  970. package/linthost/format_quotes_switches_single_to_double_to_minimize_escapes_test.go +22 -0
  971. package/linthost/format_quotes_unescapes_apostrophe_when_converting_test.go +30 -0
  972. package/linthost/format_reflow_preserves_import_default_gap_comment_test.go +29 -0
  973. package/linthost/format_reflow_preserves_import_type_gap_comment_test.go +29 -0
  974. package/linthost/format_reflow_preserves_nested_call_arg_comment_test.go +24 -0
  975. package/linthost/format_reflow_preserves_new_constructee_gap_comment_test.go +21 -0
  976. package/linthost/format_reflow_preserves_return_comment_test.go +24 -0
  977. package/linthost/format_reflow_preserves_ternary_paren_comment_test.go +26 -0
  978. package/linthost/format_semi_fires_for_every_asi_statement_kind_test.go +103 -0
  979. package/linthost/format_semi_honors_prefer_never_option_test.go +28 -0
  980. package/linthost/format_semi_idempotent_on_stripped_interface_test.go +28 -0
  981. package/linthost/format_semi_idempotent_on_terminated_members_test.go +38 -0
  982. package/linthost/format_semi_inserts_after_missing_terminator_test.go +28 -0
  983. package/linthost/format_semi_inserts_member_terminator_before_trailing_comment_test.go +29 -0
  984. package/linthost/format_semi_keeps_a_flat_mapped_type_bare_test.go +31 -0
  985. package/linthost/format_semi_keeps_a_flat_object_types_last_member_bare_test.go +36 -0
  986. package/linthost/format_semi_keeps_braced_and_object_literal_accessors_bare_test.go +40 -0
  987. package/linthost/format_semi_keeps_class_field_semi_before_computed_member_test.go +32 -0
  988. package/linthost/format_semi_keeps_object_literal_accessor_separators_untouched_test.go +49 -0
  989. package/linthost/format_semi_keeps_one_line_interface_body_bare_test.go +29 -0
  990. package/linthost/format_semi_keeps_same_line_type_member_separator_test.go +31 -0
  991. package/linthost/format_semi_keeps_type_member_semi_before_call_signature_test.go +32 -0
  992. package/linthost/format_semi_normalizes_a_comma_member_separator_test.go +39 -0
  993. package/linthost/format_semi_prefer_never_block_comment_is_not_hazard_test.go +49 -0
  994. package/linthost/format_semi_prefer_never_keeps_a_flat_object_types_separator_test.go +38 -0
  995. package/linthost/format_semi_prefer_never_keeps_do_while_separator_test.go +32 -0
  996. package/linthost/format_semi_prefer_never_keeps_same_line_else_separator_test.go +31 -0
  997. package/linthost/format_semi_prefer_never_keeps_same_line_statement_separator_test.go +29 -0
  998. package/linthost/format_semi_prefer_never_keeps_semi_before_asi_hazard_test.go +58 -0
  999. package/linthost/format_semi_prefer_never_keeps_semi_before_regex_hazard_test.go +51 -0
  1000. package/linthost/format_semi_prefer_never_keeps_semi_before_same_line_comment_gap_test.go +30 -0
  1001. package/linthost/format_semi_prefer_never_line_comment_is_not_hazard_test.go +49 -0
  1002. package/linthost/format_semi_prefer_never_normalizes_a_comma_it_must_keep_test.go +37 -0
  1003. package/linthost/format_semi_prefer_never_strips_a_comma_member_separator_test.go +32 -0
  1004. package/linthost/format_semi_prefer_never_strips_a_flat_object_types_trailing_separator_test.go +33 -0
  1005. package/linthost/format_semi_prefer_never_strips_a_mapped_type_terminator_test.go +35 -0
  1006. package/linthost/format_semi_prefer_never_strips_across_crlf_test.go +33 -0
  1007. package/linthost/format_semi_prefer_never_strips_across_multiline_comment_gap_test.go +32 -0
  1008. package/linthost/format_semi_prefer_never_strips_before_same_line_close_brace_test.go +31 -0
  1009. package/linthost/format_semi_prefer_never_strips_member_with_space_test.go +52 -0
  1010. package/linthost/format_semi_reads_a_mapped_types_wrap_at_its_opening_brace_test.go +34 -0
  1011. package/linthost/format_semi_skips_already_terminated_statements_test.go +31 -0
  1012. package/linthost/format_semi_strips_class_field_semicolons_test.go +29 -0
  1013. package/linthost/format_semi_strips_interface_member_semicolons_test.go +29 -0
  1014. package/linthost/format_semi_strips_type_alias_semicolon_test.go +29 -0
  1015. package/linthost/format_semi_terminates_a_broken_mapped_type_test.go +40 -0
  1016. package/linthost/format_semi_terminates_a_mapped_type_across_crlf_test.go +32 -0
  1017. package/linthost/format_semi_terminates_a_mapped_type_around_its_trailing_comment_test.go +37 -0
  1018. package/linthost/format_semi_terminates_a_mapped_type_without_a_type_annotation_test.go +37 -0
  1019. package/linthost/format_semi_terminates_a_member_across_crlf_test.go +31 -0
  1020. package/linthost/format_semi_terminates_a_member_whose_type_ends_in_a_brace_test.go +31 -0
  1021. package/linthost/format_semi_terminates_broken_interface_members_test.go +45 -0
  1022. package/linthost/format_semi_terminates_broken_type_literal_member_test.go +31 -0
  1023. package/linthost/format_semi_terminates_class_index_signature_and_ambient_accessor_test.go +29 -0
  1024. package/linthost/format_sort_imports_alphabetizes_named_specifiers_test.go +31 -0
  1025. package/linthost/format_sort_imports_combine_requires_unsafe_runtime_opt_in_test.go +30 -0
  1026. package/linthost/format_sort_imports_combines_type_and_value_test.go +27 -0
  1027. package/linthost/format_sort_imports_dedupes_repeated_specifier_test.go +28 -0
  1028. package/linthost/format_sort_imports_group_separator_honors_crlf_end_of_line_test.go +40 -0
  1029. package/linthost/format_sort_imports_groups_builtins_first_test.go +29 -0
  1030. package/linthost/format_sort_imports_groups_external_before_relative_test.go +35 -0
  1031. package/linthost/format_sort_imports_groups_type_only_imports_test.go +27 -0
  1032. package/linthost/format_sort_imports_honors_crlf_end_of_line_test.go +40 -0
  1033. package/linthost/format_sort_imports_honors_custom_import_order_test.go +88 -0
  1034. package/linthost/format_sort_imports_keeps_attribute_bearing_imports_unmerged_test.go +24 -0
  1035. package/linthost/format_sort_imports_keeps_commented_list_unmerged_test.go +26 -0
  1036. package/linthost/format_sort_imports_keeps_conflicting_defaults_separate_test.go +34 -0
  1037. package/linthost/format_sort_imports_keeps_default_gap_comment_unmerged_test.go +24 -0
  1038. package/linthost/format_sort_imports_keeps_default_only_gap_comment_unmerged_test.go +24 -0
  1039. package/linthost/format_sort_imports_keeps_empty_named_imports_test.go +31 -0
  1040. package/linthost/format_sort_imports_keeps_identical_commented_imports_unmerged_test.go +35 -0
  1041. package/linthost/format_sort_imports_keeps_identical_namespace_imports_unmerged_test.go +35 -0
  1042. package/linthost/format_sort_imports_keeps_namespace_imports_separate_test.go +34 -0
  1043. package/linthost/format_sort_imports_keeps_trailing_specifier_comment_unmerged_test.go +24 -0
  1044. package/linthost/format_sort_imports_keeps_type_and_value_separate_test.go +31 -0
  1045. package/linthost/format_sort_imports_keeps_type_default_and_type_named_separate_test.go +34 -0
  1046. package/linthost/format_sort_imports_keeps_type_default_and_type_named_separate_when_combining_test.go +34 -0
  1047. package/linthost/format_sort_imports_keeps_type_default_separate_when_combining_test.go +31 -0
  1048. package/linthost/format_sort_imports_merges_default_and_named_test.go +27 -0
  1049. package/linthost/format_sort_imports_merges_duplicate_modules_test.go +28 -0
  1050. package/linthost/format_sort_imports_merges_duplicate_type_only_imports_test.go +24 -0
  1051. package/linthost/format_sort_imports_merges_type_default_with_empty_named_test.go +28 -0
  1052. package/linthost/format_sort_imports_merges_type_named_binding_test.go +33 -0
  1053. package/linthost/format_sort_imports_orders_case_insensitively_by_default_test.go +29 -0
  1054. package/linthost/format_sort_imports_orders_case_sensitively_when_enabled_test.go +29 -0
  1055. package/linthost/format_sort_imports_preserves_comments_between_imports_test.go +43 -0
  1056. package/linthost/format_sort_imports_preserves_comments_between_specifiers_test.go +38 -0
  1057. package/linthost/format_sort_imports_preserves_side_effect_imports_test.go +55 -0
  1058. package/linthost/format_sort_imports_recognizes_exact_builtin_specifiers_test.go +56 -0
  1059. package/linthost/format_sort_imports_scopes_type_group_by_regex_test.go +32 -0
  1060. package/linthost/format_sort_imports_separator_spans_empty_group_test.go +31 -0
  1061. package/linthost/format_sort_imports_skips_already_sorted_files_test.go +40 -0
  1062. package/linthost/format_sort_imports_skips_invalid_regex_group_test.go +30 -0
  1063. package/linthost/format_sort_imports_skips_invalid_types_regex_group_test.go +28 -0
  1064. package/linthost/format_sort_imports_skips_single_import_files_test.go +38 -0
  1065. package/linthost/format_sort_imports_sorts_erased_type_only_block_test.go +26 -0
  1066. package/linthost/format_sort_imports_sorts_named_specifiers_without_reordering_runtime_imports_test.go +28 -0
  1067. package/linthost/format_sort_imports_treats_inline_type_bindings_as_runtime_import_test.go +24 -0
  1068. package/linthost/format_sort_imports_unsafe_option_reorders_runtime_imports_test.go +34 -0
  1069. package/linthost/format_statement_split_abstains_on_empty_statements_test.go +26 -0
  1070. package/linthost/format_statement_split_abstains_when_block_comment_in_gap_test.go +28 -0
  1071. package/linthost/format_statement_split_breaks_statements_sharing_a_line_test.go +28 -0
  1072. package/linthost/format_statement_split_breaks_three_statements_on_one_line_test.go +27 -0
  1073. package/linthost/format_statement_split_honors_crlf_end_of_line_test.go +29 -0
  1074. package/linthost/format_statement_split_indents_split_statement_inside_block_test.go +30 -0
  1075. package/linthost/format_statement_split_keeps_block_on_case_label_line_test.go +28 -0
  1076. package/linthost/format_statement_split_keeps_leading_semi_guard_test.go +31 -0
  1077. package/linthost/format_statement_split_skips_already_one_per_line_test.go +26 -0
  1078. package/linthost/format_ternary_nullish_parens_leaves_logical_and_parenthesized_test.go +30 -0
  1079. package/linthost/format_ternary_nullish_parens_wraps_all_positions_test.go +29 -0
  1080. package/linthost/format_trailing_comma_honors_mode_es5_for_enum_members_test.go +26 -0
  1081. package/linthost/format_trailing_comma_honors_mode_es5_includes_type_level_lists_test.go +26 -0
  1082. package/linthost/format_trailing_comma_honors_mode_es5_option_test.go +28 -0
  1083. package/linthost/format_trailing_comma_honors_mode_es5_skips_arrow_parameter_test.go +29 -0
  1084. package/linthost/format_trailing_comma_honors_mode_es5_skips_call_argument_test.go +28 -0
  1085. package/linthost/format_trailing_comma_honors_mode_es5_skips_constructor_parameter_test.go +29 -0
  1086. package/linthost/format_trailing_comma_honors_mode_es5_skips_function_expression_parameter_test.go +29 -0
  1087. package/linthost/format_trailing_comma_honors_mode_es5_skips_method_parameter_test.go +29 -0
  1088. package/linthost/format_trailing_comma_honors_mode_es5_skips_new_argument_test.go +28 -0
  1089. package/linthost/format_trailing_comma_honors_mode_es5_skips_set_accessor_parameter_test.go +29 -0
  1090. package/linthost/format_trailing_comma_inserts_after_array_spread_in_value_literal_test.go +26 -0
  1091. package/linthost/format_trailing_comma_inserts_after_decorated_parameter_test.go +27 -0
  1092. package/linthost/format_trailing_comma_inserts_after_last_array_element_test.go +25 -0
  1093. package/linthost/format_trailing_comma_inserts_after_last_arrow_parameter_test.go +25 -0
  1094. package/linthost/format_trailing_comma_inserts_after_last_call_argument_test.go +25 -0
  1095. package/linthost/format_trailing_comma_inserts_after_last_call_signature_parameter_test.go +28 -0
  1096. package/linthost/format_trailing_comma_inserts_after_last_construct_signature_parameter_test.go +28 -0
  1097. package/linthost/format_trailing_comma_inserts_after_last_constructor_parameter_test.go +26 -0
  1098. package/linthost/format_trailing_comma_inserts_after_last_constructor_type_parameter_test.go +28 -0
  1099. package/linthost/format_trailing_comma_inserts_after_last_element_in_multiple_lists_test.go +27 -0
  1100. package/linthost/format_trailing_comma_inserts_after_last_function_expression_parameter_test.go +25 -0
  1101. package/linthost/format_trailing_comma_inserts_after_last_function_parameter_test.go +25 -0
  1102. package/linthost/format_trailing_comma_inserts_after_last_function_type_parameter_test.go +28 -0
  1103. package/linthost/format_trailing_comma_inserts_after_last_method_parameter_test.go +26 -0
  1104. package/linthost/format_trailing_comma_inserts_after_last_method_signature_parameter_test.go +28 -0
  1105. package/linthost/format_trailing_comma_inserts_after_last_named_export_test.go +25 -0
  1106. package/linthost/format_trailing_comma_inserts_after_last_named_import_test.go +25 -0
  1107. package/linthost/format_trailing_comma_inserts_after_last_new_argument_test.go +27 -0
  1108. package/linthost/format_trailing_comma_inserts_after_last_object_property_test.go +25 -0
  1109. package/linthost/format_trailing_comma_inserts_after_last_set_accessor_parameter_test.go +26 -0
  1110. package/linthost/format_trailing_comma_inserts_after_last_tuple_element_test.go +25 -0
  1111. package/linthost/format_trailing_comma_inserts_after_last_type_parameter_test.go +28 -0
  1112. package/linthost/format_trailing_comma_inserts_after_non_rest_array_assignment_target_test.go +27 -0
  1113. package/linthost/format_trailing_comma_inserts_after_non_rest_object_assignment_target_test.go +27 -0
  1114. package/linthost/format_trailing_comma_inserts_after_object_spread_in_value_literal_test.go +26 -0
  1115. package/linthost/format_trailing_comma_inserts_after_parameter_property_in_constructor_test.go +28 -0
  1116. package/linthost/format_trailing_comma_mode_none_removes_trailing_comma_test.go +28 -0
  1117. package/linthost/format_trailing_comma_places_comma_before_trailing_line_comment_test.go +31 -0
  1118. package/linthost/format_trailing_comma_removes_call_comma_under_es5_test.go +27 -0
  1119. package/linthost/format_trailing_comma_skips_already_terminated_lists_test.go +31 -0
  1120. package/linthost/format_trailing_comma_skips_array_rest_assignment_target_test.go +28 -0
  1121. package/linthost/format_trailing_comma_skips_call_when_close_paren_shares_line_with_last_argument_test.go +30 -0
  1122. package/linthost/format_trailing_comma_skips_dynamic_import_argument_test.go +28 -0
  1123. package/linthost/format_trailing_comma_skips_empty_lists_test.go +32 -0
  1124. package/linthost/format_trailing_comma_skips_inline_block_comment_before_close_bracket_test.go +31 -0
  1125. package/linthost/format_trailing_comma_skips_object_rest_assignment_target_test.go +28 -0
  1126. package/linthost/format_trailing_comma_skips_rest_parameter_test.go +39 -0
  1127. package/linthost/format_trailing_comma_skips_single_line_lists_test.go +34 -0
  1128. package/linthost/format_trailing_comma_skips_unparenthesized_arrow_with_multiline_body_test.go +28 -0
  1129. package/linthost/format_whitespace_collapses_all_blank_file_to_single_eol_test.go +30 -0
  1130. package/linthost/format_whitespace_collapses_consecutive_blank_lines_test.go +27 -0
  1131. package/linthost/format_whitespace_fixes_missing_final_newline_with_trailing_space_test.go +29 -0
  1132. package/linthost/format_whitespace_inserts_missing_final_newline_test.go +28 -0
  1133. package/linthost/format_whitespace_keeps_blank_line_inside_template_test.go +27 -0
  1134. package/linthost/format_whitespace_normalizes_crlf_to_lf_by_default_test.go +28 -0
  1135. package/linthost/format_whitespace_preserves_crlf_under_crlf_end_of_line_test.go +28 -0
  1136. package/linthost/format_whitespace_preserves_nested_template_content_test.go +28 -0
  1137. package/linthost/format_whitespace_preserves_trailing_space_across_template_substitution_test.go +29 -0
  1138. package/linthost/format_whitespace_preserves_trailing_spaces_inside_template_literal_test.go +35 -0
  1139. package/linthost/format_whitespace_skips_empty_file_test.go +26 -0
  1140. package/linthost/format_whitespace_skips_single_blank_line_test.go +26 -0
  1141. package/linthost/format_whitespace_strips_leading_blank_lines_test.go +27 -0
  1142. package/linthost/format_whitespace_strips_trailing_blank_lines_test.go +27 -0
  1143. package/linthost/format_whitespace_trims_trailing_spaces_test.go +28 -0
  1144. package/linthost/functional_helpers_test.go +88 -0
  1145. package/linthost/functional_immutable_data_ignores_code_pattern_test.go +28 -0
  1146. package/linthost/functional_immutable_data_rejects_property_assignment_test.go +25 -0
  1147. package/linthost/functional_no_class_inheritance_rejects_extends_test.go +24 -0
  1148. package/linthost/functional_no_classes_rejects_class_declaration_test.go +24 -0
  1149. package/linthost/functional_no_conditional_statements_rejects_if_test.go +23 -0
  1150. package/linthost/functional_no_expression_statements_rejects_call_test.go +23 -0
  1151. package/linthost/functional_no_let_ignores_identifier_pattern_test.go +28 -0
  1152. package/linthost/functional_no_let_rejects_let_declaration_test.go +24 -0
  1153. package/linthost/functional_no_loop_statements_rejects_for_test.go +23 -0
  1154. package/linthost/functional_no_mixed_types_check_interfaces_false_skips_interface_test.go +28 -0
  1155. package/linthost/functional_no_mixed_types_check_interfaces_false_still_checks_type_literal_test.go +28 -0
  1156. package/linthost/functional_no_mixed_types_check_type_literals_false_skips_type_literal_test.go +28 -0
  1157. package/linthost/functional_no_mixed_types_check_type_literals_false_still_checks_interface_test.go +28 -0
  1158. package/linthost/functional_no_mixed_types_rejects_method_and_property_test.go +23 -0
  1159. package/linthost/functional_no_promise_reject_rejects_static_call_test.go +23 -0
  1160. package/linthost/functional_no_return_void_allow_null_false_rejects_null_return_type_test.go +27 -0
  1161. package/linthost/functional_no_return_void_allow_undefined_false_rejects_undefined_return_type_test.go +28 -0
  1162. package/linthost/functional_no_return_void_allows_null_return_type_by_default_test.go +23 -0
  1163. package/linthost/functional_no_return_void_allows_undefined_return_type_by_default_test.go +23 -0
  1164. package/linthost/functional_no_return_void_ignore_inferred_types_keeps_annotated_bare_return_test.go +28 -0
  1165. package/linthost/functional_no_return_void_ignore_inferred_types_reads_a_get_accessor_annotation_test.go +30 -0
  1166. package/linthost/functional_no_return_void_ignore_inferred_types_skips_unannotated_bare_return_test.go +28 -0
  1167. package/linthost/functional_no_return_void_ignore_inferred_types_stops_at_the_nearest_function_test.go +29 -0
  1168. package/linthost/functional_no_return_void_rejects_void_annotation_test.go +23 -0
  1169. package/linthost/functional_no_this_expressions_rejects_this_test.go +23 -0
  1170. package/linthost/functional_no_throw_statements_rejects_throw_test.go +23 -0
  1171. package/linthost/functional_no_try_statements_rejects_try_test.go +23 -0
  1172. package/linthost/functional_parameters_ignores_identifier_pattern_test.go +27 -0
  1173. package/linthost/functional_parameters_rejects_rest_parameter_test.go +25 -0
  1174. package/linthost/functional_prefer_immutable_types_ignores_identifier_pattern_test.go +28 -0
  1175. package/linthost/functional_prefer_immutable_types_rejects_array_type_test.go +23 -0
  1176. package/linthost/functional_prefer_immutable_types_rejects_mutable_parameter_array_test.go +24 -0
  1177. package/linthost/functional_prefer_property_signatures_rejects_method_signature_test.go +23 -0
  1178. package/linthost/functional_prefer_readonly_type_allow_mutable_return_type_covers_call_signature_test.go +29 -0
  1179. package/linthost/functional_prefer_readonly_type_allow_mutable_return_type_keeps_parameter_annotation_test.go +28 -0
  1180. package/linthost/functional_prefer_readonly_type_allow_mutable_return_type_skips_return_annotation_test.go +28 -0
  1181. package/linthost/functional_prefer_readonly_type_ignore_class_fields_only_keeps_method_parameter_test.go +34 -0
  1182. package/linthost/functional_prefer_readonly_type_ignore_class_keeps_module_scope_checked_test.go +29 -0
  1183. package/linthost/functional_prefer_readonly_type_ignore_class_skips_class_body_test.go +29 -0
  1184. package/linthost/functional_prefer_readonly_type_ignore_collections_keeps_property_signature_test.go +28 -0
  1185. package/linthost/functional_prefer_readonly_type_ignore_collections_skips_array_type_test.go +28 -0
  1186. package/linthost/functional_prefer_readonly_type_ignore_interface_keeps_type_alias_member_test.go +28 -0
  1187. package/linthost/functional_prefer_readonly_type_ignore_interface_skips_interface_member_test.go +28 -0
  1188. package/linthost/functional_prefer_readonly_type_ignores_code_pattern_test.go +27 -0
  1189. package/linthost/functional_prefer_readonly_type_rejects_array_type_test.go +23 -0
  1190. package/linthost/functional_prefer_tacit_check_member_expressions_false_keeps_identifier_callee_test.go +27 -0
  1191. package/linthost/functional_prefer_tacit_check_member_expressions_false_skips_member_callee_test.go +28 -0
  1192. package/linthost/functional_prefer_tacit_rejects_single_argument_wrapper_test.go +24 -0
  1193. package/linthost/functional_readonly_type_rejects_readonly_array_generic_test.go +23 -0
  1194. package/linthost/functional_type_declaration_immutability_ignores_identifier_pattern_test.go +27 -0
  1195. package/linthost/functional_type_declaration_immutability_rejects_mutable_interface_test.go +23 -0
  1196. package/linthost/getter_return_follows_every_path_through_switch_try_and_loops_test.go +64 -0
  1197. package/linthost/global_ignores_remove_an_imported_source_from_the_read_scope_test.go +60 -0
  1198. package/linthost/graph_nodes.go +12 -2
  1199. package/linthost/graph_nodes_drops_what_a_consumer_cannot_index_test.go +98 -0
  1200. package/linthost/graph_nodes_publishes_nothing_without_a_publisher_test.go +51 -0
  1201. package/linthost/grapheme_break_unicode_16_conformance_test.go +99 -0
  1202. package/linthost/grouped_accessor_pairs_object_literal_message_test.go +75 -0
  1203. package/linthost/guard_for_in_structural_matrix_test.go +74 -0
  1204. package/linthost/has_nil_entry_distinguishes_malformed_and_valid_lists_test.go +35 -0
  1205. package/linthost/has_nil_entry_returns_false_for_nil_list_test.go +26 -0
  1206. package/linthost/helpers_test.go +910 -0
  1207. package/linthost/hints.go +11 -1
  1208. package/linthost/host.go +126 -43
  1209. package/linthost/imported_tsx_source_joins_the_read_scope_test.go +67 -0
  1210. package/linthost/indent_unit_uses_tab_width_when_positive_test.go +49 -0
  1211. package/linthost/inline_resolver_carries_options_in_resolved_config_test.go +36 -0
  1212. package/linthost/input_observation.go +571 -0
  1213. package/linthost/invalid_contributor_range_cannot_panic_inline_directive_filtering_test.go +46 -0
  1214. package/linthost/is_format_rule_detects_marker_interface_test.go +62 -0
  1215. package/linthost/jsdoc_helpers_test.go +30 -0
  1216. package/linthost/jsx_a11y_alt_text_allows_img_spread_props_test.go +21 -0
  1217. package/linthost/jsx_a11y_alt_text_requires_img_alt_test.go +22 -0
  1218. package/linthost/jsx_a11y_anchor_ambiguous_text_test.go +24 -0
  1219. package/linthost/jsx_a11y_anchor_has_content_rejects_empty_anchor_test.go +25 -0
  1220. package/linthost/jsx_a11y_anchor_is_valid_allows_spread_props_test.go +21 -0
  1221. package/linthost/jsx_a11y_anchor_is_valid_rejects_hash_href_despite_spread_test.go +22 -0
  1222. package/linthost/jsx_a11y_anchor_is_valid_rejects_hash_href_test.go +22 -0
  1223. package/linthost/jsx_a11y_aria_activedescendant_has_tabindex_requires_focus_target_test.go +23 -0
  1224. package/linthost/jsx_a11y_aria_props_rejects_unknown_prop_test.go +22 -0
  1225. package/linthost/jsx_a11y_aria_proptypes_rejects_bad_boolean_test.go +23 -0
  1226. package/linthost/jsx_a11y_aria_role_rejects_unknown_role_test.go +22 -0
  1227. package/linthost/jsx_a11y_aria_unsupported_elements_rejects_meta_aria_test.go +23 -0
  1228. package/linthost/jsx_a11y_aria_unsupported_elements_rejects_role_despite_spread_test.go +24 -0
  1229. package/linthost/jsx_a11y_autocomplete_valid_allows_appropriate_input_type_test.go +29 -0
  1230. package/linthost/jsx_a11y_autocomplete_valid_rejects_inappropriate_input_type_test.go +21 -0
  1231. package/linthost/jsx_a11y_autocomplete_valid_rejects_invalid_token_sequence_test.go +26 -0
  1232. package/linthost/jsx_a11y_autocomplete_valid_rejects_unknown_token_test.go +22 -0
  1233. package/linthost/jsx_a11y_click_events_have_key_events_requires_keyboard_handler_test.go +21 -0
  1234. package/linthost/jsx_a11y_control_has_associated_label_requires_button_label_test.go +21 -0
  1235. package/linthost/jsx_a11y_heading_has_content_rejects_empty_heading_test.go +22 -0
  1236. package/linthost/jsx_a11y_helpers_test.go +33 -0
  1237. package/linthost/jsx_a11y_html_has_lang_allows_non_empty_lang_test.go +21 -0
  1238. package/linthost/jsx_a11y_html_has_lang_allows_spread_props_test.go +24 -0
  1239. package/linthost/jsx_a11y_html_has_lang_rejects_empty_lang_test.go +27 -0
  1240. package/linthost/jsx_a11y_html_has_lang_requires_lang_test.go +21 -0
  1241. package/linthost/jsx_a11y_iframe_has_title_allows_spread_props_test.go +23 -0
  1242. package/linthost/jsx_a11y_iframe_has_title_requires_title_test.go +21 -0
  1243. package/linthost/jsx_a11y_img_redundant_alt_rejects_image_word_despite_spread_test.go +25 -0
  1244. package/linthost/jsx_a11y_img_redundant_alt_rejects_image_word_test.go +21 -0
  1245. package/linthost/jsx_a11y_interactive_supports_focus_requires_tabindex_test.go +21 -0
  1246. package/linthost/jsx_a11y_label_has_associated_control_requires_for_or_child_test.go +21 -0
  1247. package/linthost/jsx_a11y_label_has_for_alias_matches_associated_control_test.go +21 -0
  1248. package/linthost/jsx_a11y_lang_allows_valid_bcp47_tag_test.go +22 -0
  1249. package/linthost/jsx_a11y_lang_rejects_empty_lang_test.go +20 -0
  1250. package/linthost/jsx_a11y_lang_rejects_invalid_bcp47_tag_test.go +25 -0
  1251. package/linthost/jsx_a11y_media_has_caption_requires_track_test.go +22 -0
  1252. package/linthost/jsx_a11y_mouse_events_have_key_events_requires_focus_test.go +21 -0
  1253. package/linthost/jsx_a11y_no_access_key_rejects_access_key_test.go +21 -0
  1254. package/linthost/jsx_a11y_no_aria_hidden_on_focusable_rejects_hidden_button_test.go +21 -0
  1255. package/linthost/jsx_a11y_no_autofocus_rejects_autofocus_test.go +21 -0
  1256. package/linthost/jsx_a11y_no_distracting_elements_rejects_marquee_test.go +21 -0
  1257. package/linthost/jsx_a11y_no_interactive_element_to_noninteractive_role_rejects_button_presentation_test.go +21 -0
  1258. package/linthost/jsx_a11y_no_noninteractive_element_interactions_rejects_li_click_test.go +21 -0
  1259. package/linthost/jsx_a11y_no_noninteractive_element_to_interactive_role_rejects_ul_button_test.go +21 -0
  1260. package/linthost/jsx_a11y_no_noninteractive_tabindex_rejects_section_tabindex_test.go +21 -0
  1261. package/linthost/jsx_a11y_no_redundant_roles_rejects_button_role_button_test.go +21 -0
  1262. package/linthost/jsx_a11y_no_static_element_interactions_requires_role_test.go +21 -0
  1263. package/linthost/jsx_a11y_prefer_tag_over_role_rejects_div_button_test.go +21 -0
  1264. package/linthost/jsx_a11y_role_has_required_aria_props_allows_native_checkbox_test.go +21 -0
  1265. package/linthost/jsx_a11y_role_has_required_aria_props_allows_spread_props_test.go +23 -0
  1266. package/linthost/jsx_a11y_role_has_required_aria_props_requires_checkbox_checked_test.go +21 -0
  1267. package/linthost/jsx_a11y_role_supports_aria_props_allows_explicit_button_pressed_test.go +21 -0
  1268. package/linthost/jsx_a11y_role_supports_aria_props_allows_native_button_pressed_test.go +21 -0
  1269. package/linthost/jsx_a11y_role_supports_aria_props_rejects_button_checked_test.go +21 -0
  1270. package/linthost/jsx_a11y_rules_survive_spread_attributes_test.go +60 -0
  1271. package/linthost/jsx_a11y_scope_rejects_scope_on_td_test.go +21 -0
  1272. package/linthost/jsx_a11y_tabindex_no_positive_rejects_positive_tabindex_test.go +21 -0
  1273. package/linthost/known_symbol_property_name_finds_iteration_and_disposal_protocol_members_test.go +112 -0
  1274. package/linthost/legacy_custom_resolver_keeps_rule_options_fallback_test.go +45 -0
  1275. package/linthost/lint_corpus_companions_belong_to_their_own_case_test.go +53 -0
  1276. package/linthost/lint_corpus_diagnostics_are_attributed_to_the_main_source_test.go +51 -0
  1277. package/linthost/lint_corpus_directives_reject_malformed_or_duplicate_markers_test.go +89 -0
  1278. package/linthost/lint_corpus_discovery_classifies_every_typescript_suffix_test.go +56 -0
  1279. package/linthost/lint_corpus_discovery_rejects_invalid_companion_contracts_test.go +50 -0
  1280. package/linthost/lint_corpus_discovery_rejects_unclassified_sources_test.go +39 -0
  1281. package/linthost/lint_corpus_expectation_parser_rejects_malformed_or_targetless_markers_test.go +46 -0
  1282. package/linthost/lint_corpus_expectation_parser_resolves_line_and_jsx_block_markers_test.go +53 -0
  1283. package/linthost/lint_corpus_filename_separators_share_materialized_source_identity_test.go +85 -0
  1284. package/linthost/lint_corpus_loader_helpers_test.go +704 -0
  1285. package/linthost/lint_corpus_project_selects_jsx_mode_for_included_tsx_sources_test.go +118 -0
  1286. package/linthost/lint_corpus_skips_name_one_rule_and_one_harness_test.go +63 -0
  1287. package/linthost/lint_fixture_corpus_test.go +166 -0
  1288. package/linthost/lint_trace.go +202 -0
  1289. package/linthost/lint_trace_preserves_raw_invocation_and_integrity_test.go +139 -0
  1290. package/linthost/load_config_file_rejects_unsupported_extension_test.go +38 -0
  1291. package/linthost/load_config_resolver_compact_globs_preserve_entry_policy_test.go +97 -0
  1292. package/linthost/load_config_resolver_scopes_extends_options_in_engine_test.go +65 -0
  1293. package/linthost/load_json_config_file_rejects_invalid_json_test.go +38 -0
  1294. package/linthost/load_program_keeps_checker_pool_for_type_aware_rules_test.go +184 -0
  1295. package/linthost/load_program_skips_checker_for_ast_only_rules_test.go +59 -0
  1296. package/linthost/load_rule_config_configfile_overrides_discovery_test.go +51 -0
  1297. package/linthost/load_rule_config_discovers_cwd_config_for_out_of_tree_tsconfig_test.go +46 -0
  1298. package/linthost/load_rule_config_discovers_plain_lint_config_test.go +39 -0
  1299. package/linthost/load_rule_config_extends_with_ignores_and_rules_ignores_globally_test.go +141 -0
  1300. package/linthost/load_rule_config_honors_plugin_config_dir_env_test.go +53 -0
  1301. package/linthost/load_rule_config_loads_json_config_file_test.go +55 -0
  1302. package/linthost/load_rule_config_missing_config_error_names_search_origins_test.go +44 -0
  1303. package/linthost/load_rule_config_preserves_json_pattern_precedence_test.go +80 -0
  1304. package/linthost/load_rule_config_rejects_array_rules_test.go +34 -0
  1305. package/linthost/load_rule_config_rejects_empty_extends_test.go +34 -0
  1306. package/linthost/load_rule_config_rejects_extends_cycle_between_two_configs_test.go +71 -0
  1307. package/linthost/load_rule_config_rejects_missing_discovered_config_test.go +37 -0
  1308. package/linthost/load_rule_config_rejects_overly_deep_extends_chain_test.go +53 -0
  1309. package/linthost/load_rule_config_rejects_self_referential_extends_test.go +49 -0
  1310. package/linthost/load_rule_config_resolves_configfile_relative_to_plugin_config_dir_env_test.go +46 -0
  1311. package/linthost/load_rule_config_resolves_linear_extends_chain_test.go +81 -0
  1312. package/linthost/load_rules_ignores_non_lint_plugin_payload_test.go +33 -0
  1313. package/linthost/loader_module_option_follows_the_config_package_type_test.go +103 -0
  1314. package/linthost/loader_rootdir_contains_loader_and_config_test.go +59 -0
  1315. package/linthost/loader_temp_base_stays_on_config_volume_test.go +35 -0
  1316. package/linthost/logic_rules_cover_boolean_call_arguments_undefined_typeof_negative_zero_and_number_nan_test.go +43 -0
  1317. package/linthost/lookup_rule_returns_registered_implementation_or_nil_test.go +49 -0
  1318. package/linthost/lsp.go +185 -34
  1319. package/linthost/lsp_apply_suggestion_rejects_stale_source_test.go +49 -0
  1320. package/linthost/lsp_apply_suggestion_resolves_junction_project_link_test.go +33 -0
  1321. package/linthost/lsp_apply_suggestion_resolves_logical_project_link_test.go +35 -0
  1322. package/linthost/lsp_await_thenable_suggestion_executes_exact_token_test.go +52 -0
  1323. package/linthost/lsp_ban_ts_comment_suggestion_preserves_crlf_block_test.go +52 -0
  1324. package/linthost/lsp_code_action_helpers_test.go +55 -0
  1325. package/linthost/lsp_code_actions_fail_closed_for_invalid_quickfix_range_test.go +88 -0
  1326. package/linthost/lsp_code_actions_reject_more_specific_context_only_test.go +37 -0
  1327. package/linthost/lsp_code_actions_returns_empty_for_node_modules_target_test.go +44 -0
  1328. package/linthost/lsp_code_actions_returns_empty_for_outside_cwd_target_test.go +45 -0
  1329. package/linthost/lsp_code_actions_short_circuits_unowned_context_only_test.go +46 -0
  1330. package/linthost/lsp_code_actions_split_lint_and_format_commands_test.go +41 -0
  1331. package/linthost/lsp_command_discovery_reports_owned_commands_and_kinds_test.go +67 -0
  1332. package/linthost/lsp_command_helpers_test.go +113 -0
  1333. package/linthost/lsp_command_workspace_preserves_nested_dependency_scopes_test.go +77 -0
  1334. package/linthost/lsp_commands_accept_windows_short_cwd_test.go +62 -0
  1335. package/linthost/lsp_diagnostic_omits_code_description_for_contributor_rule_test.go +81 -0
  1336. package/linthost/lsp_diagnostic_tags_drop_unknown_values_test.go +41 -0
  1337. package/linthost/lsp_diagnostic_wire_drops_code_description_key_when_unmapped_test.go +65 -0
  1338. package/linthost/lsp_diagnostics_link_rule_codes_to_documentation_test.go +84 -0
  1339. package/linthost/lsp_document_write_scope_preserves_project_and_sibling_boundaries_test.go +68 -0
  1340. package/linthost/lsp_execute_command_applies_utf16_edit_after_non_bmp_prefix_test.go +48 -0
  1341. package/linthost/lsp_execute_command_cascades_format_fixes_without_mutating_disk_test.go +50 -0
  1342. package/linthost/lsp_execute_command_cascades_lint_fixes_without_mutating_disk_test.go +48 -0
  1343. package/linthost/lsp_execute_command_copies_read_only_file_as_writable_test.go +46 -0
  1344. package/linthost/lsp_execute_command_maps_absolute_config_file_into_temp_workspace_test.go +40 -0
  1345. package/linthost/lsp_execute_command_materializes_duplicate_symlinked_directories_test.go +57 -0
  1346. package/linthost/lsp_execute_command_materializes_junctioned_directory_without_mutating_original_test.go +61 -0
  1347. package/linthost/lsp_execute_command_materializes_symlink_target_without_mutating_original_test.go +55 -0
  1348. package/linthost/lsp_execute_command_materializes_symlinked_directory_without_mutating_original_test.go +56 -0
  1349. package/linthost/lsp_execute_command_rejects_target_outside_cwd_before_read_test.go +61 -0
  1350. package/linthost/lsp_execute_command_returns_null_for_node_modules_target_test.go +59 -0
  1351. package/linthost/lsp_execute_command_returns_null_when_no_edits_test.go +51 -0
  1352. package/linthost/lsp_execute_command_splits_lint_and_format_edits_test.go +43 -0
  1353. package/linthost/lsp_fix_all_leaves_suggestion_only_rewrites_unchanged_test.go +37 -0
  1354. package/linthost/lsp_format_buffer_formats_missing_disk_file_test.go +42 -0
  1355. package/linthost/lsp_format_buffer_helpers_test.go +68 -0
  1356. package/linthost/lsp_format_buffer_ignores_disk_content_test.go +52 -0
  1357. package/linthost/lsp_format_buffer_in_memory_test.go +47 -0
  1358. package/linthost/lsp_format_buffer_type_aware_contributor_test.go +142 -0
  1359. package/linthost/lsp_format_paths_honor_entry_ignores_test.go +45 -0
  1360. package/linthost/lsp_format_paths_use_canonical_defaults_test.go +72 -0
  1361. package/linthost/lsp_format_paths_use_defaults_without_format_block_test.go +28 -0
  1362. package/linthost/lsp_format_paths_use_editor_language_overrides_test.go +34 -0
  1363. package/linthost/lsp_hints_publishes_jsdoc_check_tag_names_corpus_test.go +56 -0
  1364. package/linthost/lsp_hints_skips_the_program_when_nothing_publishes_test.go +46 -0
  1365. package/linthost/lsp_hints_still_loads_the_program_for_a_declared_publisher_test.go +42 -0
  1366. package/linthost/lsp_logical_project_link_helpers_test.go +127 -0
  1367. package/linthost/lsp_position_columns_count_utf16_across_planes_test.go +107 -0
  1368. package/linthost/lsp_position_counts_non_bmp_as_two_utf16_units_test.go +26 -0
  1369. package/linthost/lsp_prefer_as_const_suggestion_executes_selected_range_test.go +51 -0
  1370. package/linthost/lsp_project_diagnostics_recomputes_external_state_without_document_test.go +187 -0
  1371. package/linthost/lsp_serve_answers_hints_from_the_resident_daemon_test.go +73 -0
  1372. package/linthost/lsp_switch_exhaustiveness_suggestions_preserve_default_anchors_test.go +206 -0
  1373. package/linthost/match_any_pattern_accepts_native_and_slash_separators_test.go +47 -0
  1374. package/linthost/match_any_pattern_handles_brace_expansion_test.go +43 -0
  1375. package/linthost/match_any_pattern_matches_dot_directory_globs_test.go +44 -0
  1376. package/linthost/max_nested_callbacks_counts_only_functions_passed_to_calls_test.go +46 -0
  1377. package/linthost/migrated_no_misused_promises_helpers_test.go +30 -0
  1378. package/linthost/migrated_no_unused_expressions_helpers_test.go +50 -0
  1379. package/linthost/migrated_typed_rule_helpers_test.go +46 -0
  1380. package/linthost/misc_testing_library_rules_test.go +63 -0
  1381. package/linthost/mixed_diagnostics_render_empty_is_silent_test.go +29 -0
  1382. package/linthost/mixed_diagnostics_render_interleaves_parser_and_lint_test.go +51 -0
  1383. package/linthost/mixed_diagnostics_render_orders_files_and_ties_test.go +58 -0
  1384. package/linthost/new_print_context_zero_print_width_applies_defaults_test.go +36 -0
  1385. package/linthost/no_array_delete_asks_the_type_not_the_subscript_test.go +70 -0
  1386. package/linthost/no_await_in_loop_complete_semantics_test.go +205 -0
  1387. package/linthost/no_base_to_string_test.go +48 -0
  1388. package/linthost/no_class_assign_test.go +217 -0
  1389. package/linthost/no_container_ignores_unrelated_container_binding_test.go +33 -0
  1390. package/linthost/no_deprecated_test.go +45 -0
  1391. package/linthost/no_dupe_class_members_allows_typescript_overload_signatures_test.go +41 -0
  1392. package/linthost/no_dupe_class_members_rejects_accessor_data_collisions_test.go +28 -0
  1393. package/linthost/no_dupe_else_if_logical_coverage_test.go +152 -0
  1394. package/linthost/no_dupe_keys_computed_key_static_resolution_test.go +72 -0
  1395. package/linthost/no_duplicate_imports_allow_separate_type_imports_allows_value_plus_type_import_test.go +30 -0
  1396. package/linthost/no_duplicate_imports_allow_separate_type_imports_still_reports_type_pairs_test.go +30 -0
  1397. package/linthost/no_duplicate_imports_allow_separate_type_imports_still_reports_value_pairs_test.go +29 -0
  1398. package/linthost/no_duplicate_imports_allows_inline_type_specifier_beside_type_import_test.go +29 -0
  1399. package/linthost/no_duplicate_imports_allows_named_and_namespace_value_imports_test.go +31 -0
  1400. package/linthost/no_duplicate_imports_allows_type_default_and_type_named_imports_test.go +31 -0
  1401. package/linthost/no_duplicate_imports_allows_type_namespace_and_type_named_imports_test.go +28 -0
  1402. package/linthost/no_duplicate_imports_classifies_inline_type_specifier_as_value_test.go +31 -0
  1403. package/linthost/no_duplicate_imports_helpers_test.go +78 -0
  1404. package/linthost/no_duplicate_imports_ignores_misspelled_option_keys_test.go +30 -0
  1405. package/linthost/no_duplicate_imports_ignores_reexports_by_default_test.go +32 -0
  1406. package/linthost/no_duplicate_imports_include_exports_allows_export_star_beside_named_import_test.go +31 -0
  1407. package/linthost/no_duplicate_imports_include_exports_allows_export_star_beside_namespace_reexport_test.go +29 -0
  1408. package/linthost/no_duplicate_imports_include_exports_allows_namespace_reexport_beside_named_import_test.go +29 -0
  1409. package/linthost/no_duplicate_imports_include_exports_reports_both_pairings_on_one_declaration_test.go +34 -0
  1410. package/linthost/no_duplicate_imports_include_exports_reports_export_star_beside_side_effect_import_test.go +35 -0
  1411. package/linthost/no_duplicate_imports_include_exports_reports_import_after_reexport_test.go +30 -0
  1412. package/linthost/no_duplicate_imports_include_exports_reports_reexport_after_import_test.go +30 -0
  1413. package/linthost/no_duplicate_imports_include_exports_reports_repeated_export_star_test.go +30 -0
  1414. package/linthost/no_duplicate_imports_include_exports_reports_second_reexport_test.go +29 -0
  1415. package/linthost/no_duplicate_imports_include_exports_reports_type_reexport_after_value_import_test.go +30 -0
  1416. package/linthost/no_duplicate_imports_include_exports_skips_local_export_without_module_test.go +31 -0
  1417. package/linthost/no_duplicate_imports_include_exports_treats_empty_reexport_clause_as_side_effect_test.go +31 -0
  1418. package/linthost/no_duplicate_imports_include_exports_with_allow_separate_allows_type_reexport_test.go +30 -0
  1419. package/linthost/no_duplicate_imports_preserves_migrated_json_tuple_options_test.go +47 -0
  1420. package/linthost/no_duplicate_imports_reports_default_then_named_value_imports_test.go +31 -0
  1421. package/linthost/no_duplicate_imports_reports_default_then_namespace_value_imports_test.go +30 -0
  1422. package/linthost/no_duplicate_imports_reports_each_later_duplicate_import_test.go +31 -0
  1423. package/linthost/no_duplicate_imports_reports_nonadjacent_duplicate_value_imports_test.go +30 -0
  1424. package/linthost/no_duplicate_imports_reports_repeated_side_effect_imports_test.go +29 -0
  1425. package/linthost/no_duplicate_imports_reports_side_effect_import_after_named_import_test.go +30 -0
  1426. package/linthost/no_duplicate_imports_reports_two_namespace_value_imports_test.go +29 -0
  1427. package/linthost/no_duplicate_imports_reports_two_type_default_imports_test.go +29 -0
  1428. package/linthost/no_duplicate_imports_reports_value_default_then_type_named_import_test.go +33 -0
  1429. package/linthost/no_duplicate_imports_reports_value_then_type_named_import_by_default_test.go +30 -0
  1430. package/linthost/no_duplicate_imports_skips_empty_module_specifiers_test.go +30 -0
  1431. package/linthost/no_duplicate_imports_treats_default_with_empty_named_clause_as_default_test.go +30 -0
  1432. package/linthost/no_duplicate_imports_treats_empty_named_import_clause_as_side_effect_test.go +32 -0
  1433. package/linthost/no_duplicate_imports_trims_module_specifier_whitespace_test.go +29 -0
  1434. package/linthost/no_else_return_allow_else_if_false_reports_else_if_test.go +60 -0
  1435. package/linthost/no_else_return_allows_break_before_else_test.go +34 -0
  1436. package/linthost/no_else_return_allows_continue_before_else_test.go +34 -0
  1437. package/linthost/no_else_return_allows_else_if_return_chain_test.go +34 -0
  1438. package/linthost/no_else_return_allows_throw_before_else_test.go +32 -0
  1439. package/linthost/no_else_return_reports_once_on_terminal_else_test.go +31 -0
  1440. package/linthost/no_else_return_reports_plain_else_after_return_test.go +27 -0
  1441. package/linthost/no_empty_character_class_semantics_test.go +62 -0
  1442. package/linthost/no_empty_complete_semantics_test.go +89 -0
  1443. package/linthost/no_empty_function_comments_preserve_every_kind_test.go +35 -0
  1444. package/linthost/no_empty_function_options_test.go +60 -0
  1445. package/linthost/no_empty_function_typescript_exceptions_and_category_boundaries_test.go +248 -0
  1446. package/linthost/no_empty_static_block_comment_boundaries_test.go +37 -0
  1447. package/linthost/no_extend_native_covers_assignment_and_static_callee_forms_test.go +52 -0
  1448. package/linthost/no_extend_native_covers_every_native_constructor_with_a_prototype_test.go +45 -0
  1449. package/linthost/no_extend_native_define_property_and_computed_test.go +71 -0
  1450. package/linthost/no_extend_native_respects_constructor_bindings_test.go +48 -0
  1451. package/linthost/no_extra_bind_function_body_test.go +72 -0
  1452. package/linthost/no_extra_bind_offers_withheld_removal_as_suggestion_test.go +43 -0
  1453. package/linthost/no_extra_bind_preserves_throwing_receiver_reads_test.go +32 -0
  1454. package/linthost/no_extra_boolean_cast_declines_fix_for_comment_between_bangs_test.go +28 -0
  1455. package/linthost/no_extra_boolean_cast_declines_fix_for_leading_comment_in_call_test.go +29 -0
  1456. package/linthost/no_extra_boolean_cast_declines_fix_for_trailing_comment_in_call_test.go +28 -0
  1457. package/linthost/no_extra_boolean_cast_fix_boolean_call_in_boolean_context_test.go +43 -0
  1458. package/linthost/no_extra_boolean_cast_fix_collapses_nested_boolean_call_test.go +30 -0
  1459. package/linthost/no_extra_boolean_cast_fix_double_bang_in_boolean_context_test.go +28 -0
  1460. package/linthost/no_extra_boolean_cast_fix_keeps_bare_identifier_under_bang_test.go +28 -0
  1461. package/linthost/no_extra_boolean_cast_fix_keeps_parenthesized_argument_without_double_wrap_test.go +28 -0
  1462. package/linthost/no_extra_boolean_cast_fix_parenthesizes_arrow_argument_in_ternary_condition_test.go +30 -0
  1463. package/linthost/no_extra_boolean_cast_fix_parenthesizes_assignment_in_ternary_condition_test.go +28 -0
  1464. package/linthost/no_extra_boolean_cast_fix_parenthesizes_await_argument_under_bang_test.go +28 -0
  1465. package/linthost/no_extra_boolean_cast_fix_parenthesizes_logical_operand_under_bang_test.go +28 -0
  1466. package/linthost/no_extra_boolean_cast_fix_parenthesizes_nested_ternary_condition_test.go +30 -0
  1467. package/linthost/no_extra_boolean_cast_fix_parenthesizes_yield_argument_under_bang_test.go +28 -0
  1468. package/linthost/no_extra_boolean_cast_fix_preserves_comment_inside_argument_test.go +29 -0
  1469. package/linthost/no_extra_boolean_cast_fix_skips_wrap_for_logical_ternary_condition_test.go +29 -0
  1470. package/linthost/no_extra_boolean_cast_fix_skips_wrap_inside_explicit_parens_under_bang_test.go +29 -0
  1471. package/linthost/no_extra_boolean_cast_keeps_meaningful_double_bang_outside_boolean_context_test.go +28 -0
  1472. package/linthost/no_extra_boolean_cast_offers_withheld_splice_as_suggestion_test.go +37 -0
  1473. package/linthost/no_extra_boolean_cast_preserves_shadowed_converters_test.go +76 -0
  1474. package/linthost/no_fallthrough_accepts_adjacent_empty_case_labels_test.go +28 -0
  1475. package/linthost/no_fallthrough_accepts_block_marker_with_trailing_unrelated_comment_test.go +32 -0
  1476. package/linthost/no_fallthrough_accepts_break_in_try_with_normal_finally_test.go +33 -0
  1477. package/linthost/no_fallthrough_accepts_breaking_catch_after_throwing_try_test.go +34 -0
  1478. package/linthost/no_fallthrough_accepts_continue_terminating_case_test.go +33 -0
  1479. package/linthost/no_fallthrough_accepts_do_while_with_always_throwing_body_test.go +33 -0
  1480. package/linthost/no_fallthrough_accepts_empty_case_with_same_line_comment_test.go +29 -0
  1481. package/linthost/no_fallthrough_accepts_if_else_terminating_every_path_test.go +38 -0
  1482. package/linthost/no_fallthrough_accepts_infinite_for_without_break_test.go +31 -0
  1483. package/linthost/no_fallthrough_accepts_infinite_loop_with_labeled_break_to_outer_test.go +35 -0
  1484. package/linthost/no_fallthrough_accepts_infinite_while_without_break_test.go +31 -0
  1485. package/linthost/no_fallthrough_accepts_labeled_break_to_outer_loop_test.go +34 -0
  1486. package/linthost/no_fallthrough_accepts_marked_empty_case_with_blank_gap_test.go +30 -0
  1487. package/linthost/no_fallthrough_accepts_marked_fallthrough_variants_test.go +43 -0
  1488. package/linthost/no_fallthrough_accepts_marker_in_sole_empty_block_test.go +30 -0
  1489. package/linthost/no_fallthrough_accepts_marker_inside_sole_block_statement_test.go +32 -0
  1490. package/linthost/no_fallthrough_accepts_nested_switch_terminating_on_every_path_test.go +38 -0
  1491. package/linthost/no_fallthrough_accepts_terminating_finally_test.go +34 -0
  1492. package/linthost/no_fallthrough_accepts_terminating_try_and_catch_with_normal_finally_test.go +41 -0
  1493. package/linthost/no_fallthrough_accepts_unreachable_labeled_break_in_while_false_test.go +39 -0
  1494. package/linthost/no_fallthrough_accepts_unreachable_labeled_break_in_while_zero_test.go +37 -0
  1495. package/linthost/no_fallthrough_accepts_while_bigint_one_literal_test.go +31 -0
  1496. package/linthost/no_fallthrough_accepts_while_nonempty_string_literal_test.go +31 -0
  1497. package/linthost/no_fallthrough_accepts_while_numeric_one_literal_test.go +31 -0
  1498. package/linthost/no_fallthrough_accepts_while_regex_literal_test.go +31 -0
  1499. package/linthost/no_fallthrough_accepts_with_statement_body_break_test.go +33 -0
  1500. package/linthost/no_fallthrough_allow_empty_case_permits_blank_line_gap_test.go +29 -0
  1501. package/linthost/no_fallthrough_command_composes_nested_try_finally_test.go +124 -0
  1502. package/linthost/no_fallthrough_command_composes_statement_and_loop_throw_edges_test.go +108 -0
  1503. package/linthost/no_fallthrough_command_helpers_test.go +68 -0
  1504. package/linthost/no_fallthrough_command_preserves_bigint_literal_truthiness_test.go +82 -0
  1505. package/linthost/no_fallthrough_command_preserves_catch_break_continue_test.go +66 -0
  1506. package/linthost/no_fallthrough_command_preserves_code_path_boundaries_test.go +136 -0
  1507. package/linthost/no_fallthrough_command_preserves_jsx_code_path_boundaries_test.go +68 -0
  1508. package/linthost/no_fallthrough_command_preserves_markers_across_catch_reachability_test.go +40 -0
  1509. package/linthost/no_fallthrough_command_tracks_binding_reference_edges_test.go +70 -0
  1510. package/linthost/no_fallthrough_command_tracks_return_exception_edges_test.go +79 -0
  1511. package/linthost/no_fallthrough_custom_pattern_replaces_default_marker_test.go +32 -0
  1512. package/linthost/no_fallthrough_directive_suppression_still_wins_test.go +32 -0
  1513. package/linthost/no_fallthrough_helpers_test.go +55 -0
  1514. package/linthost/no_fallthrough_honors_custom_comment_pattern_test.go +30 -0
  1515. package/linthost/no_fallthrough_ignores_switch_without_clauses_test.go +24 -0
  1516. package/linthost/no_fallthrough_ignores_trailing_unreachable_statements_test.go +33 -0
  1517. package/linthost/no_fallthrough_ignores_unreachable_break_in_infinite_loop_test.go +35 -0
  1518. package/linthost/no_fallthrough_invalid_comment_pattern_falls_back_to_default_test.go +31 -0
  1519. package/linthost/no_fallthrough_never_reports_last_open_case_test.go +27 -0
  1520. package/linthost/no_fallthrough_rejects_breakable_conditional_while_test.go +33 -0
  1521. package/linthost/no_fallthrough_rejects_directive_comment_as_marker_test.go +31 -0
  1522. package/linthost/no_fallthrough_rejects_do_while_exited_by_labeled_continue_test.go +34 -0
  1523. package/linthost/no_fallthrough_rejects_do_while_exited_by_unlabeled_continue_test.go +33 -0
  1524. package/linthost/no_fallthrough_rejects_do_while_with_break_test.go +32 -0
  1525. package/linthost/no_fallthrough_rejects_empty_case_followed_by_blank_line_test.go +30 -0
  1526. package/linthost/no_fallthrough_rejects_empty_case_with_comment_line_gap_test.go +31 -0
  1527. package/linthost/no_fallthrough_rejects_empty_statement_case_despite_allow_empty_case_test.go +29 -0
  1528. package/linthost/no_fallthrough_rejects_for_of_with_always_throwing_body_test.go +33 -0
  1529. package/linthost/no_fallthrough_rejects_if_else_with_one_open_branch_test.go +36 -0
  1530. package/linthost/no_fallthrough_rejects_if_without_else_test.go +33 -0
  1531. package/linthost/no_fallthrough_rejects_infinite_loop_broken_by_own_label_test.go +32 -0
  1532. package/linthost/no_fallthrough_rejects_infinite_while_containing_break_test.go +32 -0
  1533. package/linthost/no_fallthrough_rejects_labeled_block_broken_by_own_label_test.go +33 -0
  1534. package/linthost/no_fallthrough_rejects_lint_directive_comment_as_marker_test.go +31 -0
  1535. package/linthost/no_fallthrough_rejects_marker_before_last_statement_test.go +32 -0
  1536. package/linthost/no_fallthrough_rejects_marker_in_block_that_is_not_sole_statement_test.go +31 -0
  1537. package/linthost/no_fallthrough_rejects_marker_inside_nested_inner_block_test.go +31 -0
  1538. package/linthost/no_fallthrough_rejects_nested_switch_exited_by_inner_break_test.go +34 -0
  1539. package/linthost/no_fallthrough_rejects_nested_switch_without_default_test.go +36 -0
  1540. package/linthost/no_fallthrough_rejects_non_literal_constant_condition_test.go +33 -0
  1541. package/linthost/no_fallthrough_rejects_normally_completing_catch_test.go +34 -0
  1542. package/linthost/no_fallthrough_rejects_open_try_with_normal_finally_test.go +34 -0
  1543. package/linthost/no_fallthrough_rejects_return_inside_arrow_test.go +32 -0
  1544. package/linthost/no_fallthrough_rejects_return_inside_function_declaration_test.go +33 -0
  1545. package/linthost/no_fallthrough_rejects_return_inside_function_expression_test.go +33 -0
  1546. package/linthost/no_fallthrough_rejects_unrelated_comment_in_sole_empty_block_test.go +29 -0
  1547. package/linthost/no_fallthrough_rejects_unrelated_trailing_comment_test.go +30 -0
  1548. package/linthost/no_fallthrough_reports_case_message_after_leading_default_test.go +37 -0
  1549. package/linthost/no_fallthrough_reports_default_message_for_default_clause_test.go +35 -0
  1550. package/linthost/no_fallthrough_reports_each_unmarked_transition_once_test.go +32 -0
  1551. package/linthost/no_fallthrough_reports_inner_and_outer_switch_transitions_test.go +37 -0
  1552. package/linthost/no_fallthrough_reports_unused_comment_after_terminating_if_else_test.go +46 -0
  1553. package/linthost/no_fallthrough_reports_unused_comment_inside_sole_block_test.go +36 -0
  1554. package/linthost/no_fallthrough_reports_unused_fallthrough_comment_test.go +38 -0
  1555. package/linthost/no_fallthrough_reports_unused_marker_after_unreachable_catch_test.go +37 -0
  1556. package/linthost/no_fallthrough_requires_marker_to_be_last_comment_test.go +32 -0
  1557. package/linthost/no_fallthrough_unused_check_accepts_real_fallthrough_marker_test.go +30 -0
  1558. package/linthost/no_fallthrough_unused_check_ignores_non_marker_comment_test.go +31 -0
  1559. package/linthost/no_fallthrough_unused_check_skips_last_case_marker_test.go +28 -0
  1560. package/linthost/no_fallthrough_unused_check_skips_reachable_empty_case_test.go +30 -0
  1561. package/linthost/no_fallthrough_unused_comment_ignored_by_default_test.go +31 -0
  1562. package/linthost/no_floating_promises_credits_a_handler_through_an_optional_chain_test.go +55 -0
  1563. package/linthost/no_floating_promises_default_semantics_test.go +48 -0
  1564. package/linthost/no_floating_promises_detects_index_value_type_parameters_test.go +145 -0
  1565. package/linthost/no_floating_promises_handler_chains_test.go +53 -0
  1566. package/linthost/no_floating_promises_helpers_test.go +43 -0
  1567. package/linthost/no_floating_promises_iife_test.go +32 -0
  1568. package/linthost/no_floating_promises_javascript_generic_defaults_test.go +177 -0
  1569. package/linthost/no_floating_promises_mixed_receiver_results_test.go +222 -0
  1570. package/linthost/no_floating_promises_options_test.go +56 -0
  1571. package/linthost/no_floating_promises_preserves_call_resolution_test.go +291 -0
  1572. package/linthost/no_floating_promises_preserves_candidate_context_literals_test.go +289 -0
  1573. package/linthost/no_floating_promises_preserves_contextual_callback_returns_test.go +208 -0
  1574. package/linthost/no_floating_promises_preserves_migrated_default_contexts_test.go +20 -0
  1575. package/linthost/no_floating_promises_preserves_optional_callback_overloads_test.go +42 -0
  1576. package/linthost/no_floating_promises_preserves_subtype_overload_priority_test.go +40 -0
  1577. package/linthost/no_floating_promises_rejects_inapplicable_generic_receiver_branches_test.go +254 -0
  1578. package/linthost/no_floating_promises_rejects_opaque_mapped_type_parameters_test.go +159 -0
  1579. package/linthost/no_floating_promises_safe_calls_in_composites_specifiers_test.go +43 -0
  1580. package/linthost/no_floating_promises_safe_calls_in_composites_test.go +88 -0
  1581. package/linthost/no_floating_promises_specifiers_test.go +108 -0
  1582. package/linthost/no_floating_promises_test.go +46 -0
  1583. package/linthost/no_floating_promises_thenable_scope_follows_check_thenables_test.go +87 -0
  1584. package/linthost/no_floating_promises_type_shapes_test.go +100 -0
  1585. package/linthost/no_for_in_array_test.go +49 -0
  1586. package/linthost/no_func_assign_test.go +195 -0
  1587. package/linthost/no_import_assign_binding_identity_and_complete_writes_test.go +140 -0
  1588. package/linthost/no_import_assign_binding_identity_helpers_test.go +114 -0
  1589. package/linthost/no_import_assign_ignores_resolved_shadows_and_deeper_values_test.go +118 -0
  1590. package/linthost/no_import_assign_recognizes_every_assignment_operator_test.go +36 -0
  1591. package/linthost/no_import_assign_test.go +48 -0
  1592. package/linthost/no_inner_declarations_both_mode_test.go +73 -0
  1593. package/linthost/no_inner_declarations_default_allows_strict_script_block_functions_test.go +33 -0
  1594. package/linthost/no_inner_declarations_default_module_test.go +35 -0
  1595. package/linthost/no_inner_declarations_default_strict_context_test.go +93 -0
  1596. package/linthost/no_inner_declarations_disallow_block_functions_test.go +57 -0
  1597. package/linthost/no_inner_declarations_helpers_test.go +32 -0
  1598. package/linthost/no_invalid_this_accepts_class_field_initializers_test.go +32 -0
  1599. package/linthost/no_irregular_whitespace_allows_string_literals_and_reports_code_test.go +44 -0
  1600. package/linthost/no_loop_func_allows_safe_bindings_and_excluded_headers_test.go +67 -0
  1601. package/linthost/no_loop_func_allows_using_bindings_test.go +52 -0
  1602. package/linthost/no_loop_func_checks_all_runtime_function_forms_test.go +52 -0
  1603. package/linthost/no_loop_func_helpers_test.go +55 -0
  1604. package/linthost/no_loop_func_iife_boundaries_test.go +41 -0
  1605. package/linthost/no_loop_func_reports_only_unsafe_references_test.go +83 -0
  1606. package/linthost/no_loop_func_test.go +68 -0
  1607. package/linthost/no_loop_func_tracks_write_forms_and_symbol_identity_test.go +49 -0
  1608. package/linthost/no_loop_func_treats_class_field_initializers_as_variable_scopes_test.go +46 -0
  1609. package/linthost/no_loss_of_precision_accepts_exact_unsafe_integer_test.go +36 -0
  1610. package/linthost/no_loss_of_precision_handles_every_number_syntax_test.go +93 -0
  1611. package/linthost/no_loss_of_precision_rejects_huge_decimal_integer_test.go +28 -0
  1612. package/linthost/no_meaningless_void_operator_test.go +48 -0
  1613. package/linthost/no_misused_promises_arguments_test.go +82 -0
  1614. package/linthost/no_misused_promises_defaults_test.go +89 -0
  1615. package/linthost/no_misused_promises_helpers_test.go +135 -0
  1616. package/linthost/no_misused_promises_native_array_predicates_test.go +91 -0
  1617. package/linthost/no_misused_promises_options_test.go +103 -0
  1618. package/linthost/no_misused_promises_preserves_migrated_default_contexts_test.go +23 -0
  1619. package/linthost/no_misused_promises_test.go +53 -0
  1620. package/linthost/no_mixed_operators_allow_same_precedence_false_flags_additive_test.go +42 -0
  1621. package/linthost/no_mixed_operators_allows_bitwise_beside_comparison_test.go +26 -0
  1622. package/linthost/no_mixed_operators_allows_bitwise_beside_logical_test.go +25 -0
  1623. package/linthost/no_mixed_operators_allows_parenthesized_inner_test.go +27 -0
  1624. package/linthost/no_mixed_operators_allows_relational_same_precedence_test.go +27 -0
  1625. package/linthost/no_mixed_operators_allows_same_operator_chain_test.go +26 -0
  1626. package/linthost/no_mixed_operators_allows_same_precedence_multiplicative_test.go +26 -0
  1627. package/linthost/no_mixed_operators_allows_ternary_beside_logical_by_default_test.go +27 -0
  1628. package/linthost/no_mixed_operators_custom_groups_omitting_arithmetic_allow_test.go +28 -0
  1629. package/linthost/no_mixed_operators_custom_groups_ternary_flags_logical_test.go +43 -0
  1630. package/linthost/no_mixed_operators_flags_logical_and_left_of_or_test.go +27 -0
  1631. package/linthost/no_mixed_operators_flags_logical_and_right_of_or_test.go +27 -0
  1632. package/linthost/no_mixed_operators_flags_multiplicative_within_additive_test.go +26 -0
  1633. package/linthost/no_mixed_operators_flags_relational_within_equality_test.go +28 -0
  1634. package/linthost/no_mixed_operators_flags_shift_within_bitwise_test.go +28 -0
  1635. package/linthost/no_mixed_operators_reports_both_operator_tokens_test.go +60 -0
  1636. package/linthost/no_namespace_exempts_global_augmentation_test.go +52 -0
  1637. package/linthost/no_param_reassign_complete_semantics_test.go +75 -0
  1638. package/linthost/no_param_reassign_default_props_leaves_property_writes_alone_test.go +38 -0
  1639. package/linthost/no_param_reassign_helpers_test.go +63 -0
  1640. package/linthost/no_param_reassign_options_validation_helpers_test.go +12 -0
  1641. package/linthost/no_param_reassign_options_validation_test.go +58 -0
  1642. package/linthost/no_param_reassign_options_validator_rejects_every_invalid_schema_boundary_test.go +109 -0
  1643. package/linthost/no_param_reassign_props_follows_official_mutation_boundaries_and_ignores_test.go +89 -0
  1644. package/linthost/no_param_reassign_test.go +52 -0
  1645. package/linthost/no_param_reassign_uses_checker_identity_across_nested_scopes_test.go +73 -0
  1646. package/linthost/no_promise_executor_return_allow_void_test.go +80 -0
  1647. package/linthost/no_promise_executor_return_complete_semantics_test.go +145 -0
  1648. package/linthost/no_promise_executor_return_test.go +35 -0
  1649. package/linthost/no_promise_in_fire_event_test.go +36 -0
  1650. package/linthost/no_redeclare_relates_first_definition_test.go +55 -0
  1651. package/linthost/no_render_in_lifecycle_test.go +35 -0
  1652. package/linthost/no_restricted_imports_allow_type_imports_handles_whole_and_inline_type_syntax_test.go +57 -0
  1653. package/linthost/no_restricted_imports_allowed_name_pattern_covers_imports_and_reexports_test.go +32 -0
  1654. package/linthost/no_restricted_imports_allowed_names_reject_only_the_complement_test.go +43 -0
  1655. package/linthost/no_restricted_imports_exact_paths_cover_every_static_module_form_test.go +77 -0
  1656. package/linthost/no_restricted_imports_exact_paths_preserve_module_specifier_whitespace_test.go +31 -0
  1657. package/linthost/no_restricted_imports_groups_keep_gitignore_anchors_globstars_and_unicode_test.go +78 -0
  1658. package/linthost/no_restricted_imports_matches_source_names_and_reports_exact_specifier_ranges_test.go +71 -0
  1659. package/linthost/no_restricted_imports_missing_and_empty_restrictions_are_no_op_test.go +42 -0
  1660. package/linthost/no_restricted_imports_options_helpers_test.go +76 -0
  1661. package/linthost/no_restricted_imports_patterns_honor_negation_case_regex_and_name_patterns_test.go +46 -0
  1662. package/linthost/no_restricted_imports_positional_paths_do_not_reach_dynamic_imports_test.go +32 -0
  1663. package/linthost/no_restricted_imports_string_patterns_keep_gitignore_parent_negation_semantics_test.go +30 -0
  1664. package/linthost/no_restricted_imports_test.go +14 -0
  1665. package/linthost/no_restricted_imports_validator_accepts_every_official_option_branch_test.go +48 -0
  1666. package/linthost/no_restricted_imports_validator_rejects_malformed_configuration_at_the_boundary_test.go +64 -0
  1667. package/linthost/no_restricted_syntax_applies_every_configured_entry_and_custom_message_test.go +45 -0
  1668. package/linthost/no_restricted_syntax_checks_structured_option_uniqueness_by_fields_test.go +40 -0
  1669. package/linthost/no_restricted_syntax_coerces_empty_node_lists_for_numeric_comparisons_test.go +34 -0
  1670. package/linthost/no_restricted_syntax_compares_strings_as_utf16_test.go +37 -0
  1671. package/linthost/no_restricted_syntax_distinguishes_assignment_patterns_from_literals_test.go +81 -0
  1672. package/linthost/no_restricted_syntax_distinguishes_object_binding_properties_from_rest_test.go +44 -0
  1673. package/linthost/no_restricted_syntax_distinguishes_rest_and_spread_aliases_test.go +54 -0
  1674. package/linthost/no_restricted_syntax_exposes_computed_keys_and_property_value_paths_test.go +34 -0
  1675. package/linthost/no_restricted_syntax_exposes_scalar_statement_bodies_test.go +43 -0
  1676. package/linthost/no_restricted_syntax_exposes_switch_case_test_and_consequent_test.go +36 -0
  1677. package/linthost/no_restricted_syntax_helpers_test.go +56 -0
  1678. package/linthost/no_restricted_syntax_inherits_declare_from_variable_statements_test.go +42 -0
  1679. package/linthost/no_restricted_syntax_keeps_template_and_literal_aliases_distinct_test.go +32 -0
  1680. package/linthost/no_restricted_syntax_limits_boolean_properties_and_es_tree_aliases_test.go +51 -0
  1681. package/linthost/no_restricted_syntax_matches_attributes_nested_paths_regex_types_and_lengths_test.go +47 -0
  1682. package/linthost/no_restricted_syntax_matches_classes_alternatives_and_type_script_nodes_test.go +61 -0
  1683. package/linthost/no_restricted_syntax_matches_combinators_fields_pseudos_and_subjects_test.go +111 -0
  1684. package/linthost/no_restricted_syntax_matches_indexed_paths_literal_types_and_prefix_test.go +169 -0
  1685. package/linthost/no_restricted_syntax_preserves_null_across_nested_paths_test.go +35 -0
  1686. package/linthost/no_restricted_syntax_rejects_invalid_configuration_before_dispatch_test.go +58 -0
  1687. package/linthost/no_restricted_syntax_reports_matches_in_source_order_test.go +36 -0
  1688. package/linthost/no_restricted_syntax_stringifies_regular_expression_values_test.go +38 -0
  1689. package/linthost/no_restricted_syntax_test.go +29 -0
  1690. package/linthost/no_restricted_syntax_uses_the_last_message_for_a_repeated_selector_test.go +37 -0
  1691. package/linthost/no_restricted_types_external_config_validates_at_engine_binding_test.go +39 -0
  1692. package/linthost/no_restricted_types_fixes_whole_qualified_generic_and_empty_type_surfaces_test.go +56 -0
  1693. package/linthost/no_restricted_types_has_no_implicit_defaults_test.go +51 -0
  1694. package/linthost/no_restricted_types_helpers_test.go +63 -0
  1695. package/linthost/no_restricted_types_later_whitespace_equivalent_key_wins_test.go +40 -0
  1696. package/linthost/no_restricted_types_matches_every_official_type_surface_exactly_test.go +144 -0
  1697. package/linthost/no_restricted_types_options_accept_complete_runtime_schema_test.go +54 -0
  1698. package/linthost/no_restricted_types_options_reject_malformed_schema_boundaries_test.go +60 -0
  1699. package/linthost/no_restricted_types_rejects_only_exact_type_syntax_test.go +56 -0
  1700. package/linthost/no_restricted_types_runs_on_declaration_files_test.go +36 -0
  1701. package/linthost/no_restricted_types_structured_policy_provides_fix_and_every_suggestion_test.go +172 -0
  1702. package/linthost/no_restricted_types_uses_configured_surface_spelling_across_symbols_test.go +74 -0
  1703. package/linthost/no_restricted_types_validation_helpers_test.go +12 -0
  1704. package/linthost/no_return_assign_allows_parenthesized_assignment_test.go +91 -0
  1705. package/linthost/no_types_test.go +29 -0
  1706. package/linthost/no_undef_init_ignores_const_declarations_test.go +33 -0
  1707. package/linthost/no_uninstalled_addons_test.go +45 -0
  1708. package/linthost/no_unnecessary_act_test.go +38 -0
  1709. package/linthost/no_unnecessary_boolean_literal_compare_test.go +50 -0
  1710. package/linthost/no_unnecessary_condition_test.go +50 -0
  1711. package/linthost/no_unnecessary_qualifier_test.go +121 -0
  1712. package/linthost/no_unnecessary_template_expression_test.go +48 -0
  1713. package/linthost/no_unnecessary_type_arguments_leaves_unresolved_aliases_alone_test.go +42 -0
  1714. package/linthost/no_unnecessary_type_arguments_preserves_callable_semantics_test.go +98 -0
  1715. package/linthost/no_unnecessary_type_arguments_preserves_heritage_defaults_test.go +38 -0
  1716. package/linthost/no_unnecessary_type_arguments_resolves_imported_aliases_test.go +58 -0
  1717. package/linthost/no_unnecessary_type_arguments_test.go +49 -0
  1718. package/linthost/no_unnecessary_type_assertion_test.go +48 -0
  1719. package/linthost/no_unneeded_ternary_fix_false_true_branches_test.go +34 -0
  1720. package/linthost/no_unneeded_ternary_fix_false_true_with_low_precedence_cond_test.go +29 -0
  1721. package/linthost/no_unneeded_ternary_fix_true_false_branches_test.go +28 -0
  1722. package/linthost/no_unneeded_ternary_uses_intrinsic_boolean_coercion_test.go +28 -0
  1723. package/linthost/no_unreachable_reports_one_region_and_exempts_hoisted_declarations_test.go +50 -0
  1724. package/linthost/no_unsafe_argument_test.go +50 -0
  1725. package/linthost/no_unsafe_assignment_aliases_test.go +28 -0
  1726. package/linthost/no_unsafe_assignment_array_destructuring_test.go +33 -0
  1727. package/linthost/no_unsafe_assignment_array_spreads_test.go +29 -0
  1728. package/linthost/no_unsafe_assignment_binding_defaults_test.go +39 -0
  1729. package/linthost/no_unsafe_assignment_class_initializers_test.go +30 -0
  1730. package/linthost/no_unsafe_assignment_destructuring_reassignment_test.go +33 -0
  1731. package/linthost/no_unsafe_assignment_direct_declarations_test.go +28 -0
  1732. package/linthost/no_unsafe_assignment_empty_map_test.go +26 -0
  1733. package/linthost/no_unsafe_assignment_generic_constraints_test.go +33 -0
  1734. package/linthost/no_unsafe_assignment_helpers_test.go +114 -0
  1735. package/linthost/no_unsafe_assignment_jsx_attributes_test.go +31 -0
  1736. package/linthost/no_unsafe_assignment_mapped_types_test.go +29 -0
  1737. package/linthost/no_unsafe_assignment_object_destructuring_test.go +43 -0
  1738. package/linthost/no_unsafe_assignment_object_literals_test.go +31 -0
  1739. package/linthost/no_unsafe_assignment_parameter_defaults_test.go +37 -0
  1740. package/linthost/no_unsafe_assignment_preserves_migrated_assignment_sites_test.go +42 -0
  1741. package/linthost/no_unsafe_assignment_readonly_arrays_test.go +27 -0
  1742. package/linthost/no_unsafe_assignment_reassignment_test.go +29 -0
  1743. package/linthost/no_unsafe_assignment_recursive_generics_test.go +26 -0
  1744. package/linthost/no_unsafe_assignment_recursive_types_test.go +30 -0
  1745. package/linthost/no_unsafe_assignment_tuples_test.go +26 -0
  1746. package/linthost/no_unsafe_assignment_unions_intersections_test.go +40 -0
  1747. package/linthost/no_unsafe_call_test.go +49 -0
  1748. package/linthost/no_unsafe_enum_comparison_test.go +51 -0
  1749. package/linthost/no_unsafe_finally_resolves_jump_targets_inside_and_outside_the_finally_test.go +40 -0
  1750. package/linthost/no_unsafe_member_access_test.go +50 -0
  1751. package/linthost/no_unsafe_optional_chaining_preserves_contiguous_chain_test.go +28 -0
  1752. package/linthost/no_unsafe_return_test.go +52 -0
  1753. package/linthost/no_unsafe_unary_minus_test.go +47 -0
  1754. package/linthost/no_unused_expressions_allows_jsx_by_default_test.go +38 -0
  1755. package/linthost/no_unused_expressions_allows_productive_kinds_test.go +61 -0
  1756. package/linthost/no_unused_expressions_composes_short_circuit_and_ternary_test.go +60 -0
  1757. package/linthost/no_unused_expressions_directive_prologue_positions_test.go +63 -0
  1758. package/linthost/no_unused_expressions_honors_allow_short_circuit_test.go +59 -0
  1759. package/linthost/no_unused_expressions_honors_allow_tagged_templates_test.go +52 -0
  1760. package/linthost/no_unused_expressions_honors_allow_ternary_test.go +58 -0
  1761. package/linthost/no_unused_expressions_honors_enforce_for_jsx_test.go +56 -0
  1762. package/linthost/no_unused_expressions_honors_ignore_directives_test.go +62 -0
  1763. package/linthost/no_unused_expressions_preserves_migrated_default_controls_test.go +29 -0
  1764. package/linthost/no_unused_expressions_ts_wrappers_inherit_classification_test.go +61 -0
  1765. package/linthost/no_useless_catch_reports_a_rethrowing_catch_with_and_without_finally_test.go +42 -0
  1766. package/linthost/no_useless_constructor_preserves_argument_filtering_test.go +44 -0
  1767. package/linthost/no_useless_empty_export_allows_module_marker_test.go +36 -0
  1768. package/linthost/no_useless_escape_flags_regex_character_class_test.go +53 -0
  1769. package/linthost/no_useless_escape_invalid_utf8_names_replacement_character_test.go +63 -0
  1770. package/linthost/no_useless_escape_judges_quotes_and_template_escapes_by_enclosing_delimiter_test.go +58 -0
  1771. package/linthost/no_useless_escape_message_names_decoded_rune_test.go +74 -0
  1772. package/linthost/no_useless_escape_multibyte_range_covers_backslash_only_test.go +71 -0
  1773. package/linthost/no_useless_escape_nested_untagged_template_in_tagged_substitution_test.go +67 -0
  1774. package/linthost/no_useless_escape_v_flag_class_preserves_syntax_char_escapes_test.go +60 -0
  1775. package/linthost/no_useless_rename_declines_fix_when_comment_between_names_test.go +38 -0
  1776. package/linthost/no_useless_rename_offers_withheld_tail_deletion_as_suggestion_test.go +37 -0
  1777. package/linthost/no_var_preserves_loop_body_retained_values_test.go +33 -0
  1778. package/linthost/no_var_skips_ambient_declare_var_test.go +55 -0
  1779. package/linthost/no_var_skips_declaration_file_vars_test.go +41 -0
  1780. package/linthost/no_var_skips_using_declarations_test.go +44 -0
  1781. package/linthost/node_config_loader_env_prepends_nearest_node_modules_test.go +51 -0
  1782. package/linthost/node_package_manifest_from_resolves_a_relative_anchor_test.go +56 -0
  1783. package/linthost/node_package_manifest_from_skips_a_node_modules_directory_test.go +51 -0
  1784. package/linthost/node_platform_pair_matches_the_npm_platform_vocabulary_test.go +62 -0
  1785. package/linthost/node_report_bounds_before_skipping_trivia_test.go +44 -0
  1786. package/linthost/node_spans_multiple_lines_returns_false_for_nil_node_test.go +41 -0
  1787. package/linthost/node_suggestions_preserve_owned_edit_channels_test.go +86 -0
  1788. package/linthost/non_nullable_type_assertion_style_test.go +49 -0
  1789. package/linthost/object_shorthand_declines_fix_when_comment_in_value_span_test.go +38 -0
  1790. package/linthost/object_shorthand_offers_withheld_collapse_as_suggestion_test.go +37 -0
  1791. package/linthost/only_throw_error_test.go +44 -0
  1792. package/linthost/override_glob_matches_a_file_named_through_a_miscased_import_test.go +49 -0
  1793. package/linthost/override_glob_stored_case_preserves_character_class_test.go +41 -0
  1794. package/linthost/parse_config_store_accepts_severity_tuples_test.go +49 -0
  1795. package/linthost/parse_config_store_keeps_ignores_entry_scoped_when_files_present_test.go +56 -0
  1796. package/linthost/parse_config_store_promotes_global_ignores_alongside_rules_test.go +56 -0
  1797. package/linthost/parse_config_store_promotes_global_ignores_with_format_block_test.go +53 -0
  1798. package/linthost/parse_config_store_resolves_files_and_ignores_test.go +70 -0
  1799. package/linthost/parse_external_rule_entry_preserves_three_slot_tuple_test.go +54 -0
  1800. package/linthost/parse_external_rule_entry_treats_null_second_slot_as_no_options_test.go +35 -0
  1801. package/linthost/parse_plugins_blank_payload_returns_nil_test.go +29 -0
  1802. package/linthost/parse_plugins_rejects_bad_json_test.go +31 -0
  1803. package/linthost/parse_plugins_round_trip_test.go +51 -0
  1804. package/linthost/parse_rules_accepts_eslint_tuples_in_standard_inline_config_test.go +64 -0
  1805. package/linthost/parse_rules_accepts_legacy_numeric_severities_test.go +44 -0
  1806. package/linthost/parse_rules_accepts_string_severities_test.go +60 -0
  1807. package/linthost/parse_rules_nil_treated_as_empty_test.go +35 -0
  1808. package/linthost/parse_rules_preserves_positional_options_test.go +75 -0
  1809. package/linthost/parse_subcommand_flags_accepts_common_flag_combinations_test.go +57 -0
  1810. package/linthost/playwright_no_force_option_ignores_non_playwright_options_test.go +35 -0
  1811. package/linthost/playwright_no_networkidle_ignores_non_playwright_wait_until_test.go +35 -0
  1812. package/linthost/prefer_as_const_preserves_migrated_all_family_contexts_test.go +20 -0
  1813. package/linthost/prefer_as_const_property_annotation_offers_exact_suggestion_test.go +41 -0
  1814. package/linthost/prefer_as_const_variable_annotation_offers_exact_suggestion_test.go +41 -0
  1815. package/linthost/prefer_const_allows_reads_in_destructuring_pattern_test.go +43 -0
  1816. package/linthost/prefer_const_counts_non_null_assignment_target_by_symbol_test.go +24 -0
  1817. package/linthost/prefer_const_counts_parenthesized_update_target_by_symbol_test.go +26 -0
  1818. package/linthost/prefer_const_counts_write_forms_by_symbol_test.go +57 -0
  1819. package/linthost/prefer_const_honors_destructuring_option_test.go +77 -0
  1820. package/linthost/prefer_const_honors_ignore_read_before_assign_for_shorthand_read_test.go +30 -0
  1821. package/linthost/prefer_const_honors_ignore_read_before_assign_test.go +58 -0
  1822. package/linthost/prefer_const_preserves_migrated_lexical_fixture_test.go +112 -0
  1823. package/linthost/prefer_const_test.go +57 -0
  1824. package/linthost/prefer_const_tracks_lexical_binding_identity_test.go +60 -0
  1825. package/linthost/prefer_explicit_assert_test.go +36 -0
  1826. package/linthost/prefer_find_test.go +48 -0
  1827. package/linthost/prefer_implicit_assert_test.go +36 -0
  1828. package/linthost/prefer_includes_test.go +49 -0
  1829. package/linthost/prefer_presence_queries_test.go +37 -0
  1830. package/linthost/prefer_promise_reject_errors_test.go +45 -0
  1831. package/linthost/prefer_query_by_disappearance_test.go +35 -0
  1832. package/linthost/prefer_query_matchers_test.go +37 -0
  1833. package/linthost/prefer_readonly_preserves_mutated_private_fields_test.go +57 -0
  1834. package/linthost/prefer_reduce_type_parameter_test.go +56 -0
  1835. package/linthost/prefer_regexp_exec_test.go +48 -0
  1836. package/linthost/prefer_return_this_type_requires_all_completion_paths_test.go +43 -0
  1837. package/linthost/prefer_return_this_type_test.go +55 -0
  1838. package/linthost/prefer_screen_queries_test.go +39 -0
  1839. package/linthost/prefer_string_starts_ends_with_test.go +52 -0
  1840. package/linthost/prefer_template_declines_fix_when_comment_in_concat_span_test.go +50 -0
  1841. package/linthost/prefer_template_fix_embeds_numeric_subchain_as_single_slot_test.go +33 -0
  1842. package/linthost/prefer_template_fix_escapes_backtick_in_literal_test.go +32 -0
  1843. package/linthost/prefer_template_fix_escapes_dollar_brace_seam_test.go +33 -0
  1844. package/linthost/prefer_template_fix_flattens_operands_after_leading_string_test.go +34 -0
  1845. package/linthost/prefer_template_fix_ignores_string_under_other_operator_test.go +32 -0
  1846. package/linthost/prefer_template_fix_keeps_parenthesized_subchain_single_slot_test.go +32 -0
  1847. package/linthost/prefer_template_fix_leading_identifier_chain_test.go +30 -0
  1848. package/linthost/prefer_template_fix_preserves_carriage_return_test.go +33 -0
  1849. package/linthost/prefer_template_fix_preserves_newline_test.go +30 -0
  1850. package/linthost/prefer_template_fix_preserves_template_operand_group_test.go +27 -0
  1851. package/linthost/prefer_template_fix_renders_empty_string_operand_with_default_coercion_test.go +31 -0
  1852. package/linthost/prefer_template_fix_sees_string_through_parens_when_flattening_test.go +34 -0
  1853. package/linthost/prefer_template_fix_three_part_concat_test.go +31 -0
  1854. package/linthost/prefer_template_offers_withheld_template_as_suggestion_test.go +37 -0
  1855. package/linthost/prefer_template_preserves_default_coercion_hint_test.go +30 -0
  1856. package/linthost/prefer_template_skips_all_literal_chain_test.go +27 -0
  1857. package/linthost/prefer_template_skips_numeric_only_chain_test.go +28 -0
  1858. package/linthost/prefer_user_event_setup_ignores_setup_call_test.go +35 -0
  1859. package/linthost/print_arg_list_emits_trailing_comma_when_mode_all_test.go +38 -0
  1860. package/linthost/print_arg_list_omits_trailing_comma_when_mode_es5_test.go +39 -0
  1861. package/linthost/print_arg_list_omits_trailing_comma_when_mode_none_test.go +39 -0
  1862. package/linthost/print_arg_list_returns_parens_for_nil_list_test.go +30 -0
  1863. package/linthost/print_call_expression_falls_back_verbatim_when_args_contain_nil_test.go +43 -0
  1864. package/linthost/print_call_expression_includes_question_dot_token_test.go +36 -0
  1865. package/linthost/print_call_expression_includes_type_arguments_test.go +34 -0
  1866. package/linthost/print_call_expression_returns_empty_for_nil_node_test.go +29 -0
  1867. package/linthost/print_dispatch.go +50 -15
  1868. package/linthost/print_doc.go +206 -41
  1869. package/linthost/print_engine.go +78 -51
  1870. package/linthost/print_new_expression_falls_back_verbatim_when_args_contain_nil_test.go +42 -0
  1871. package/linthost/print_new_expression_includes_type_arguments_test.go +36 -0
  1872. package/linthost/print_new_expression_omits_argument_list_when_absent_test.go +36 -0
  1873. package/linthost/print_new_expression_returns_empty_for_nil_node_test.go +28 -0
  1874. package/linthost/print_node_returns_empty_for_nil_node_test.go +31 -0
  1875. package/linthost/print_nodes_control_flow.go +4 -4
  1876. package/linthost/print_nodes_function.go +9 -11
  1877. package/linthost/print_nodes_imports.go +8 -11
  1878. package/linthost/print_nodes_object.go +3 -6
  1879. package/linthost/printer_test_helpers_test.go +46 -0
  1880. package/linthost/project_companion_preserves_file_scoped_rule_config_test.go +45 -0
  1881. package/linthost/project_contributor_ast_only_marker_keeps_parallel_walk_test.go +54 -0
  1882. package/linthost/project_contributor_generic_accepts_options_method_keeps_legacy_payload_test.go +81 -0
  1883. package/linthost/project_contributor_optionless_marker_rejects_payload_test.go +62 -0
  1884. package/linthost/project_contributor_without_marker_keeps_options_compatibility_test.go +70 -0
  1885. package/linthost/project_contributor_without_marker_keeps_type_checker_test.go +53 -0
  1886. package/linthost/project_engine.go +8 -0
  1887. package/linthost/project_hint_collection_requires_passed_published_state_test.go +105 -0
  1888. package/linthost/project_hint_publication_filters_malformed_and_recovers_panic_test.go +66 -0
  1889. package/linthost/project_identity_mints_distinct_program_lifecycles_test.go +51 -0
  1890. package/linthost/project_input_reader.go +358 -0
  1891. package/linthost/project_input_snapshot_normalizes_windows_case_and_separators_test.go +43 -0
  1892. package/linthost/project_input_snapshot_preserves_missing_files_zero_match_globs_and_config_provenance_test.go +130 -0
  1893. package/linthost/project_input_snapshot_reconciles_options_and_physical_paths_test.go +108 -0
  1894. package/linthost/project_input_snapshot_rejects_remote_urls_test.go +59 -0
  1895. package/linthost/project_inputs.go +31 -4
  1896. package/linthost/project_inputs_command_publishes_configured_snapshot_without_program_test.go +115 -0
  1897. package/linthost/project_rule_config_folds_global_extends_and_options_test.go +68 -0
  1898. package/linthost/project_rule_config_rejects_any_files_selector_test.go +46 -0
  1899. package/linthost/project_rule_live_reports_are_concurrent_and_deterministic_test.go +89 -0
  1900. package/linthost/project_rule_reports_per_finding_severity_test.go +74 -0
  1901. package/linthost/project_rule_results_reach_public_file_context_test.go +172 -0
  1902. package/linthost/project_rule_runs_for_empty_source_set_test.go +52 -0
  1903. package/linthost/project_rule_sources_apply_only_global_ignores_test.go +62 -0
  1904. package/linthost/project_rule_sources_include_imported_sibling_source_test.go +110 -0
  1905. package/linthost/project_rule_state_and_live_failure_reach_file_dispatch_test.go +89 -0
  1906. package/linthost/project_rule_state_and_reporter_are_isolated_between_cycles_test.go +87 -0
  1907. package/linthost/project_source_files_follow_tsconfig_selection_test.go +86 -0
  1908. package/linthost/project_source_selection_preserves_explicit_bundled_roots_test.go +73 -0
  1909. package/linthost/promise_function_async_test.go +49 -0
  1910. package/linthost/public_rule_context_accepts_legacy_reporter_test.go +50 -0
  1911. package/linthost/public_rule_context_legacy_reporter_drops_fix_edits_test.go +57 -0
  1912. package/linthost/public_rule_context_options_are_isolated_test.go +106 -0
  1913. package/linthost/public_rule_context_report_fix_falls_back_when_no_edits_test.go +39 -0
  1914. package/linthost/public_rule_context_report_fix_forwards_to_fixreporter_test.go +102 -0
  1915. package/linthost/public_rule_context_report_fix_off_severity_drops_silently_test.go +41 -0
  1916. package/linthost/public_rule_context_report_fix_skips_nil_node_test.go +34 -0
  1917. package/linthost/public_rule_context_report_range_fix_falls_back_when_no_edits_test.go +38 -0
  1918. package/linthost/public_rule_context_report_range_fix_forwards_to_fixreporter_test.go +49 -0
  1919. package/linthost/public_rule_context_report_related_falls_back_test.go +58 -0
  1920. package/linthost/public_rule_context_report_related_forwards_test.go +108 -0
  1921. package/linthost/public_rule_context_report_suggestion_falls_back_when_unsupported_test.go +41 -0
  1922. package/linthost/public_rule_context_report_suggestion_forwards_to_suggestionreporter_test.go +97 -0
  1923. package/linthost/public_rule_context_report_suggestion_with_no_choices_reports_test.go +33 -0
  1924. package/linthost/radix_accepts_every_integer_radix_from_two_through_thirty_six_test.go +33 -0
  1925. package/linthost/range_suggestion_finding_uses_canonical_bounds_test.go +47 -0
  1926. package/linthost/react_button_has_type_requires_explicit_type_test.go +22 -0
  1927. package/linthost/react_compiler_subset_reports_local_purity_violations_test.go +72 -0
  1928. package/linthost/react_display_name_reports_anonymous_memo_test.go +25 -0
  1929. package/linthost/react_exhaustive_deps_reports_missing_identifiers_test.go +58 -0
  1930. package/linthost/react_helpers_test.go +36 -0
  1931. package/linthost/react_iframe_missing_sandbox_reports_iframe_test.go +21 -0
  1932. package/linthost/react_jsx_key_reports_array_element_test.go +21 -0
  1933. package/linthost/react_jsx_key_reports_conditional_map_element_test.go +23 -0
  1934. package/linthost/react_jsx_key_reports_logical_map_element_test.go +23 -0
  1935. package/linthost/react_jsx_no_duplicate_props_reports_duplicate_test.go +21 -0
  1936. package/linthost/react_jsx_no_script_url_reports_javascript_href_test.go +20 -0
  1937. package/linthost/react_jsx_no_target_blank_reports_missing_rel_test.go +22 -0
  1938. package/linthost/react_jsx_no_undef_declarations_collected_once_per_file_test.go +63 -0
  1939. package/linthost/react_jsx_no_undef_reports_undeclared_component_test.go +25 -0
  1940. package/linthost/react_jsx_no_undef_skips_declared_components_test.go +46 -0
  1941. package/linthost/react_jsx_no_useless_fragment_test.go +29 -0
  1942. package/linthost/react_no_array_index_key_reports_index_key_test.go +21 -0
  1943. package/linthost/react_no_array_index_key_reports_renamed_index_key_test.go +23 -0
  1944. package/linthost/react_no_array_index_key_skips_nested_non_list_element_test.go +22 -0
  1945. package/linthost/react_no_array_index_key_skips_unrelated_index_identifier_test.go +21 -0
  1946. package/linthost/react_no_children_prop_reports_children_prop_test.go +21 -0
  1947. package/linthost/react_no_danger_reports_dangerously_set_inner_html_test.go +21 -0
  1948. package/linthost/react_no_danger_with_children_reports_mixed_content_test.go +22 -0
  1949. package/linthost/react_no_danger_with_children_survives_spread_props_test.go +23 -0
  1950. package/linthost/react_no_direct_mutation_state_reports_state_property_write_test.go +22 -0
  1951. package/linthost/react_no_find_dom_node_reports_call_test.go +20 -0
  1952. package/linthost/react_no_is_mounted_reports_call_test.go +20 -0
  1953. package/linthost/react_no_string_refs_reports_string_ref_test.go +20 -0
  1954. package/linthost/react_no_unescaped_entities_reports_quote_text_test.go +21 -0
  1955. package/linthost/react_only_export_components_honors_allow_options_test.go +41 -0
  1956. package/linthost/react_only_export_components_reports_non_component_export_test.go +41 -0
  1957. package/linthost/react_perf_helpers_test.go +58 -0
  1958. package/linthost/react_perf_jsx_no_jsx_as_prop_test.go +29 -0
  1959. package/linthost/react_perf_jsx_no_new_array_as_prop_test.go +30 -0
  1960. package/linthost/react_perf_jsx_no_new_function_as_prop_test.go +31 -0
  1961. package/linthost/react_perf_jsx_no_new_object_as_prop_test.go +31 -0
  1962. package/linthost/react_perf_native_allow_list_test.go +49 -0
  1963. package/linthost/react_perf_rules_skip_jsx_source_test.go +29 -0
  1964. package/linthost/react_rules_of_hooks_rejects_hook_after_conditional_return_test.go +54 -0
  1965. package/linthost/react_rules_of_hooks_rejects_invalid_call_sites_test.go +65 -0
  1966. package/linthost/react_source_file_rules_handle_tsx_descendants_test.go +77 -0
  1967. package/linthost/react_state_setters_reject_render_and_effect_calls_test.go +62 -0
  1968. package/linthost/react_style_prop_object_reports_string_style_test.go +22 -0
  1969. package/linthost/react_void_dom_elements_no_children_reports_img_child_test.go +22 -0
  1970. package/linthost/regex_optimizer_distinguishes_a_zero_upper_bound_from_an_open_range_test.go +44 -0
  1971. package/linthost/regex_optimizer_preserves_ranges_crossing_meta_sets_test.go +67 -0
  1972. package/linthost/regex_tree_optimizer.go +54 -10
  1973. package/linthost/regexp_alias_rules_test.go +53 -0
  1974. package/linthost/regexp_cache.go +63 -33
  1975. package/linthost/regexp_character_class_and_group_rules_test.go +64 -0
  1976. package/linthost/regexp_duplicate_class_uses_code_points_test.go +41 -0
  1977. package/linthost/regexp_quantifier_and_flag_rules_test.go +52 -0
  1978. package/linthost/regexp_useless_ignore_case_flag_test.go +111 -0
  1979. package/linthost/regexp_useless_multiline_flag_test.go +71 -0
  1980. package/linthost/register_rejects_duplicate_rule_name_test.go +74 -0
  1981. package/linthost/reject_any_type_test.go +50 -0
  1982. package/linthost/reject_function_type_test.go +48 -0
  1983. package/linthost/related_getter_setter_pairs_test.go +56 -0
  1984. package/linthost/render_result_dom_access_and_events_test.go +45 -0
  1985. package/linthost/require_array_sort_compare_test.go +47 -0
  1986. package/linthost/require_await_counts_for_await_and_promise_returns_test.go +76 -0
  1987. package/linthost/require_description_test.go +29 -0
  1988. package/linthost/require_param_description_allows_multiline_continuation_test.go +27 -0
  1989. package/linthost/require_param_description_test.go +29 -0
  1990. package/linthost/require_param_name_test.go +26 -0
  1991. package/linthost/require_property_description_allows_multiline_continuation_test.go +27 -0
  1992. package/linthost/require_property_description_test.go +30 -0
  1993. package/linthost/require_property_name_test.go +26 -0
  1994. package/linthost/require_returns_description_allows_multiline_continuation_test.go +27 -0
  1995. package/linthost/require_returns_description_test.go +29 -0
  1996. package/linthost/required_behavioral_witness_kinds_ignore_non_public_candidates_test.go +51 -0
  1997. package/linthost/resident_apply_change_matches_cold_load_test.go +106 -0
  1998. package/linthost/resident_cache_replaces_a_checker_free_program_when_a_checker_arrives_test.go +57 -0
  1999. package/linthost/resident_cache_retains_program_for_declared_external_change_test.go +61 -0
  2000. package/linthost/resident_cache_serves_a_checker_free_verb_from_the_checker_program_test.go +51 -0
  2001. package/linthost/resident_heritage_update_rebuilds_checker_test.go +70 -0
  2002. package/linthost/resident_regex_cache_retires_reloaded_configurations_test.go +123 -0
  2003. package/linthost/resident_rules_are_reused_only_while_their_config_is_unchanged_test.go +180 -0
  2004. package/linthost/resident_whole_corpus_matches_cold_load_test.go +167 -0
  2005. package/linthost/resolve_config_file_path_uses_tsconfig_directory_test.go +34 -0
  2006. package/linthost/resolve_config_tsgo_falls_back_to_the_project_root_anchor_test.go +36 -0
  2007. package/linthost/resolve_config_tsgo_keeps_an_explicitly_pinned_compiler_test.go +41 -0
  2008. package/linthost/resolve_config_tsgo_prefers_the_config_anchor_over_the_project_root_test.go +41 -0
  2009. package/linthost/resolve_config_tsgo_resolves_the_project_compiler_without_the_environment_test.go +33 -0
  2010. package/linthost/resolve_config_tsgo_resolves_through_a_linked_typescript_install_test.go +48 -0
  2011. package/linthost/resolve_config_tsgo_returns_nothing_without_a_project_typescript_test.go +32 -0
  2012. package/linthost/resolve_config_tsgo_returns_nothing_without_the_platform_package_test.go +40 -0
  2013. package/linthost/resolve_ttsx_launcher_falls_back_to_the_bare_command_test.go +36 -0
  2014. package/linthost/resolve_ttsx_launcher_keeps_an_explicitly_pinned_binary_test.go +40 -0
  2015. package/linthost/resolve_ttsx_launcher_resolves_the_project_launcher_without_the_environment_test.go +33 -0
  2016. package/linthost/restrict_plus_operands_test.go +47 -0
  2017. package/linthost/restrict_template_expressions_test.go +47 -0
  2018. package/linthost/return_await_test.go +54 -0
  2019. package/linthost/rule_codes.go +16 -2
  2020. package/linthost/rule_codes_are_unique_and_banded_across_live_registry_test.go +74 -0
  2021. package/linthost/rule_docs.go +1 -1
  2022. package/linthost/rule_documentation_urls_cover_the_builtin_corpus_test.go +86 -0
  2023. package/linthost/rule_snapshot_engine_requires_a_valid_active_rule_test.go +59 -0
  2024. package/linthost/rules_boundaries.go +19 -7
  2025. package/linthost/rules_consistent_return.go +323 -16
  2026. package/linthost/rules_core_extra.go +41 -82
  2027. package/linthost/rules_default_case.go +1 -1
  2028. package/linthost/rules_escape.go +18 -3
  2029. package/linthost/rules_finally.go +49 -15
  2030. package/linthost/rules_format_arrow_parens.go +8 -10
  2031. package/linthost/rules_format_bracket_spacing.go +14 -19
  2032. package/linthost/rules_format_print_width.go +28 -19
  2033. package/linthost/rules_format_quote_props.go +5 -11
  2034. package/linthost/rules_format_quotes.go +5 -6
  2035. package/linthost/rules_format_sort_imports.go +27 -15
  2036. package/linthost/rules_format_statement_split.go +3 -5
  2037. package/linthost/rules_functional.go +21 -14
  2038. package/linthost/rules_gap.go +9 -12
  2039. package/linthost/rules_jsdoc.go +2 -3
  2040. package/linthost/rules_jsx_a11y.go +2 -0
  2041. package/linthost/rules_logic.go +88 -11
  2042. package/linthost/rules_loops.go +16 -2
  2043. package/linthost/rules_max_nested_callbacks.go +28 -12
  2044. package/linthost/rules_misc.go +38 -8
  2045. package/linthost/rules_no_extend_native.go +52 -13
  2046. package/linthost/rules_no_fallthrough.go +1 -1
  2047. package/linthost/rules_no_invalid_this.go +6 -3
  2048. package/linthost/rules_no_mixed_operators.go +42 -10
  2049. package/linthost/rules_no_param_reassign.go +1 -1
  2050. package/linthost/rules_no_unreachable.go +61 -2
  2051. package/linthost/rules_no_useless_constructor.go +21 -27
  2052. package/linthost/rules_problems.go +26 -2
  2053. package/linthost/rules_regexp.go +76 -28
  2054. package/linthost/rules_security.go +4 -4
  2055. package/linthost/rules_self.go +42 -6
  2056. package/linthost/rules_solid.go +14 -26
  2057. package/linthost/rules_sort_keys.go +12 -14
  2058. package/linthost/rules_storybook.go +16 -26
  2059. package/linthost/rules_strings.go +9 -19
  2060. package/linthost/rules_suggestions.go +79 -45
  2061. package/linthost/rules_testing_library.go +18 -0
  2062. package/linthost/rules_ts_no_restricted_types.go +9 -1
  2063. package/linthost/rules_ts_no_unnecessary_type_arguments.go +44 -47
  2064. package/linthost/rules_ts_prefer_readonly.go +111 -42
  2065. package/linthost/rules_ts_prefer_return_this_type.go +21 -14
  2066. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +12 -17
  2067. package/linthost/rules_unicorn_no_unnecessary_await.go +39 -13
  2068. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +7 -10
  2069. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +29 -12
  2070. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +7 -25
  2071. package/linthost/rules_unicorn_no_useless_length_check.go +19 -19
  2072. package/linthost/rules_unicorn_prefer_array_some.go +1 -2
  2073. package/linthost/rules_unicorn_prefer_bigint_literals.go +21 -18
  2074. package/linthost/rules_unicorn_prefer_date_now.go +7 -17
  2075. package/linthost/rules_unicorn_prefer_default_parameters.go +7 -15
  2076. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +7 -13
  2077. package/linthost/rules_unicorn_prefer_negative_index.go +12 -13
  2078. package/linthost/rules_unicorn_prefer_node_protocol.go +5 -5
  2079. package/linthost/rules_unicorn_prefer_object_from_entries.go +7 -14
  2080. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +17 -19
  2081. package/linthost/rules_unicorn_prefer_single_call.go +12 -6
  2082. package/linthost/rules_unicorn_prefer_spread.go +7 -13
  2083. package/linthost/rules_unicorn_prefer_string_replace_all.go +4 -3
  2084. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +22 -3
  2085. package/linthost/rules_unicorn_prefer_top_level_await.go +4 -3
  2086. package/linthost/rules_unicorn_relative_url_style.go +33 -14
  2087. package/linthost/rules_var.go +73 -3
  2088. package/linthost/runtime_rule_codes_are_collision_free_and_order_independent_test.go +101 -0
  2089. package/linthost/security_assigned_names_unwrap_assertion_targets_test.go +54 -0
  2090. package/linthost/security_bindings_collected_once_per_file_test.go +63 -0
  2091. package/linthost/security_detect_bidi_characters_test.go +44 -0
  2092. package/linthost/security_name_based_node_api_findings_stay_untagged_test.go +87 -0
  2093. package/linthost/self_compare_and_self_assign_ignore_calls_and_empty_template_curly_is_not_a_placeholder_test.go +50 -0
  2094. package/linthost/semantic_finding_guard_rejects_recovered_execution_failures_test.go +75 -0
  2095. package/linthost/serve.go +42 -25
  2096. package/linthost/set_env_replaces_or_appends_test.go +39 -0
  2097. package/linthost/severity_string_formats_values_test.go +34 -0
  2098. package/linthost/signature_flags_expose_construct_signature_abstractness_test.go +136 -0
  2099. package/linthost/signature_introspection_reaches_runtime_endpoints_test.go +123 -0
  2100. package/linthost/solid_helpers_test.go +92 -0
  2101. package/linthost/solid_import_proxy_and_dependency_rules_test.go +48 -0
  2102. package/linthost/solid_imports_leaves_a_type_only_destination_alone_test.go +42 -0
  2103. package/linthost/solid_imports_relocates_a_misrouted_specifier_test.go +69 -0
  2104. package/linthost/solid_jsx_attribute_guards_test.go +69 -0
  2105. package/linthost/solid_no_react_deps_tags_dependency_array_unnecessary_test.go +106 -0
  2106. package/linthost/solid_reactivity_and_component_returns_test.go +49 -0
  2107. package/linthost/solid_rendering_style_preferences_test.go +59 -0
  2108. package/linthost/solid_self_closing_comp_keeps_text_children_test.go +32 -0
  2109. package/linthost/solid_source_file_rules_handle_jsx_initializers_test.go +47 -0
  2110. package/linthost/solid_style_prop_reports_non_zero_numeric_lengths_test.go +37 -0
  2111. package/linthost/solid_validate_jsx_nesting_test.go +53 -0
  2112. package/linthost/sort_keys_compares_across_a_computed_key_and_resets_at_a_spread_test.go +33 -0
  2113. package/linthost/source_extension_tables_separate_selection_from_widening_test.go +44 -0
  2114. package/linthost/source_has_statement_terminator_detects_semicolon_test.go +28 -0
  2115. package/linthost/source_has_statement_terminator_returns_false_for_empty_string_test.go +27 -0
  2116. package/linthost/source_has_statement_terminator_returns_false_for_unclosed_block_comment_test.go +31 -0
  2117. package/linthost/source_has_statement_terminator_returns_false_when_absent_test.go +29 -0
  2118. package/linthost/source_has_statement_terminator_skips_trailing_block_comment_test.go +30 -0
  2119. package/linthost/source_has_statement_terminator_skips_trailing_whitespace_test.go +31 -0
  2120. package/linthost/standalone_checker_resolves_cross_file_type_after_pooled_diagnostics_test.go +85 -0
  2121. package/linthost/storybook_deletion_findings_tag_unnecessary_test.go +127 -0
  2122. package/linthost/storybook_legacy_api_findings_tag_deprecated_test.go +110 -0
  2123. package/linthost/strict_boolean_expressions_test.go +49 -0
  2124. package/linthost/switch_exhaustiveness_check_advanced_type_shapes_test.go +83 -0
  2125. package/linthost/switch_exhaustiveness_check_finite_members_test.go +76 -0
  2126. package/linthost/switch_exhaustiveness_check_helpers_test.go +99 -0
  2127. package/linthost/switch_exhaustiveness_check_no_unchecked_indexed_access_test.go +56 -0
  2128. package/linthost/switch_exhaustiveness_check_options_test.go +118 -0
  2129. package/linthost/switch_exhaustiveness_check_parser_comment_ranges_test.go +64 -0
  2130. package/linthost/switch_exhaustiveness_check_preserves_migrated_defaults_and_options_test.go +139 -0
  2131. package/linthost/switch_exhaustiveness_check_test.go +73 -0
  2132. package/linthost/tail_is_clean_terminator_returns_false_for_invalid_inputs_test.go +64 -0
  2133. package/linthost/testing_library_helpers_test.go +71 -0
  2134. package/linthost/tsdoc_syntax_test.go +64 -0
  2135. package/linthost/ttsx_command_context_spawns_the_project_launcher_test.go +47 -0
  2136. package/linthost/type_alias_reference_node_uses_borrowed_builder_context_test.go +128 -0
  2137. package/linthost/type_args_start_and_end_guard_branches_test.go +58 -0
  2138. package/linthost/type_instantiation_mappers_reach_runtime_endpoints_test.go +213 -0
  2139. package/linthost/type_mapper_parallel_substitution_avoids_capture_test.go +106 -0
  2140. package/linthost/typed_rule_semantic_helpers_test.go +34 -0
  2141. package/linthost/unbound_method_test.go +53 -0
  2142. package/linthost/unicorn_array_some_requires_an_existence_comparison_test.go +29 -0
  2143. package/linthost/unicorn_await_literal_does_not_assume_an_object_has_no_then_test.go +33 -0
  2144. package/linthost/unicorn_better_regex_constructor_fix_escapes_cooked_pattern_test.go +146 -0
  2145. package/linthost/unicorn_better_regex_fix_is_idempotent_test.go +37 -0
  2146. package/linthost/unicorn_better_regex_leaves_optimal_literals_test.go +36 -0
  2147. package/linthost/unicorn_better_regex_reports_exact_range_and_message_test.go +52 -0
  2148. package/linthost/unicorn_better_regex_reports_without_fix_on_source_member_test.go +38 -0
  2149. package/linthost/unicorn_better_regex_rewrites_regexp_constructor_test.go +70 -0
  2150. package/linthost/unicorn_better_regex_skips_unicode_flag_literals_test.go +34 -0
  2151. package/linthost/unicorn_better_regex_sort_character_classes_option_test.go +39 -0
  2152. package/linthost/unicorn_better_regex_test.go +44 -0
  2153. package/linthost/unicorn_bigint_literal_requires_an_exact_integer_value_test.go +34 -0
  2154. package/linthost/unicorn_consistent_destructuring_jsx_tag_names_are_exempt_test.go +53 -0
  2155. package/linthost/unicorn_consistent_destructuring_skips_valid_forms_test.go +221 -0
  2156. package/linthost/unicorn_consistent_destructuring_suggestion_is_opt_in_and_idempotent_test.go +54 -0
  2157. package/linthost/unicorn_consistent_destructuring_test.go +306 -0
  2158. package/linthost/unicorn_consistent_existence_index_check_fix_is_idempotent_test.go +45 -0
  2159. package/linthost/unicorn_consistent_existence_index_check_fix_rewrites_magnitude_comparisons_test.go +96 -0
  2160. package/linthost/unicorn_consistent_existence_index_check_skips_upstream_valid_forms_test.go +143 -0
  2161. package/linthost/unicorn_consistent_existence_index_check_test.go +212 -0
  2162. package/linthost/unicorn_consistent_function_scoping_chains_blocks_inside_loop_bodies_test.go +53 -0
  2163. package/linthost/unicorn_consistent_function_scoping_checks_arrow_lexical_environment_test.go +48 -0
  2164. package/linthost/unicorn_consistent_function_scoping_checks_returned_arrow_chains_test.go +29 -0
  2165. package/linthost/unicorn_consistent_function_scoping_honors_check_arrow_functions_test.go +42 -0
  2166. package/linthost/unicorn_consistent_function_scoping_keeps_shared_outer_references_together_test.go +28 -0
  2167. package/linthost/unicorn_consistent_function_scoping_outer_reference_pins_recursive_function_test.go +31 -0
  2168. package/linthost/unicorn_consistent_function_scoping_preserves_upstream_factory_exceptions_test.go +59 -0
  2169. package/linthost/unicorn_consistent_function_scoping_protects_super_and_private_names_test.go +57 -0
  2170. package/linthost/unicorn_consistent_function_scoping_reads_class_head_positions_as_lexical_environment_test.go +42 -0
  2171. package/linthost/unicorn_consistent_function_scoping_reports_canonical_head_ranges_test.go +44 -0
  2172. package/linthost/unicorn_consistent_function_scoping_resolves_jsx_component_captures_test.go +44 -0
  2173. package/linthost/unicorn_consistent_function_scoping_test.go +45 -0
  2174. package/linthost/unicorn_consistent_function_scoping_treats_loop_scopes_as_one_boundary_test.go +36 -0
  2175. package/linthost/unicorn_consistent_function_scoping_uses_binding_identity_and_ignores_self_recursion_test.go +42 -0
  2176. package/linthost/unicorn_consistent_function_scoping_validates_the_public_option_shape_test.go +58 -0
  2177. package/linthost/unicorn_consistent_template_literal_escape_command_fix_idempotence_test.go +41 -0
  2178. package/linthost/unicorn_consistent_template_literal_escape_fires_on_declaration_files_test.go +35 -0
  2179. package/linthost/unicorn_consistent_template_literal_escape_fixes_template_literal_types_test.go +35 -0
  2180. package/linthost/unicorn_consistent_template_literal_escape_fixes_upstream_invalid_corpus_test.go +80 -0
  2181. package/linthost/unicorn_consistent_template_literal_escape_honors_backslash_parity_test.go +64 -0
  2182. package/linthost/unicorn_consistent_template_literal_escape_preserves_continuations_crlf_and_unicode_test.go +34 -0
  2183. package/linthost/unicorn_consistent_template_literal_escape_reports_exact_element_ranges_test.go +71 -0
  2184. package/linthost/unicorn_consistent_template_literal_escape_reports_untagged_inside_tagged_test.go +43 -0
  2185. package/linthost/unicorn_consistent_template_literal_escape_skips_tagged_templates_test.go +40 -0
  2186. package/linthost/unicorn_consistent_template_literal_escape_skips_upstream_valid_corpus_test.go +49 -0
  2187. package/linthost/unicorn_date_now_preserves_constructor_arguments_test.go +34 -0
  2188. package/linthost/unicorn_escape_case_bounds_escape_digit_runs_test.go +97 -0
  2189. package/linthost/unicorn_escape_case_honors_backslash_parity_test.go +67 -0
  2190. package/linthost/unicorn_escape_case_reports_interpolated_template_segments_test.go +97 -0
  2191. package/linthost/unicorn_escape_case_skips_tagged_templates_test.go +62 -0
  2192. package/linthost/unicorn_escape_family_survives_crlf_and_astral_literals_test.go +67 -0
  2193. package/linthost/unicorn_filename_case_cases_key_order_shapes_message_test.go +42 -0
  2194. package/linthost/unicorn_filename_case_default_ignored_index_basenames_test.go +40 -0
  2195. package/linthost/unicorn_filename_case_directory_handling_test.go +89 -0
  2196. package/linthost/unicorn_filename_case_extension_lowercase_test.go +72 -0
  2197. package/linthost/unicorn_filename_case_ignore_patterns_match_segments_test.go +78 -0
  2198. package/linthost/unicorn_filename_case_multiple_file_extensions_option_test.go +77 -0
  2199. package/linthost/unicorn_filename_case_option_validation_test.go +74 -0
  2200. package/linthost/unicorn_filename_case_real_project_paths_test.go +50 -0
  2201. package/linthost/unicorn_filename_case_report_anchors_and_no_fix_test.go +59 -0
  2202. package/linthost/unicorn_filename_case_split_name_line_terminator_edge_test.go +37 -0
  2203. package/linthost/unicorn_filename_case_test.go +131 -0
  2204. package/linthost/unicorn_filename_case_unicode_segments_test.go +33 -0
  2205. package/linthost/unicorn_filename_case_upstream_invalid_filenames_test.go +268 -0
  2206. package/linthost/unicorn_filename_case_upstream_valid_filenames_test.go +173 -0
  2207. package/linthost/unicorn_import_style_accepts_mixed_styles_when_all_allowed_test.go +29 -0
  2208. package/linthost/unicorn_import_style_banned_module_reports_dedicated_message_test.go +70 -0
  2209. package/linthost/unicorn_import_style_check_toggles_disable_each_syntax_family_test.go +61 -0
  2210. package/linthost/unicorn_import_style_default_module_policy_matrix_test.go +69 -0
  2211. package/linthost/unicorn_import_style_default_policies_at_exact_ranges_test.go +65 -0
  2212. package/linthost/unicorn_import_style_default_policies_skip_compliant_and_unknown_modules_test.go +37 -0
  2213. package/linthost/unicorn_import_style_disjunction_lists_allowed_styles_in_order_test.go +44 -0
  2214. package/linthost/unicorn_import_style_dynamic_import_expression_forms_test.go +69 -0
  2215. package/linthost/unicorn_import_style_evaluates_static_string_module_names_test.go +58 -0
  2216. package/linthost/unicorn_import_style_extend_default_styles_false_drops_builtin_policies_test.go +46 -0
  2217. package/linthost/unicorn_import_style_named_module_policy_matrix_test.go +81 -0
  2218. package/linthost/unicorn_import_style_namespace_module_policy_matrix_test.go +63 -0
  2219. package/linthost/unicorn_import_style_object_pattern_key_forms_test.go +46 -0
  2220. package/linthost/unicorn_import_style_optional_require_calls_are_never_classified_test.go +24 -0
  2221. package/linthost/unicorn_import_style_rejects_malformed_options_before_linting_test.go +56 -0
  2222. package/linthost/unicorn_import_style_reports_no_automatic_fixes_test.go +31 -0
  2223. package/linthost/unicorn_import_style_skips_non_matching_reference_shapes_test.go +47 -0
  2224. package/linthost/unicorn_import_style_style_overrides_replace_inherited_flags_test.go +69 -0
  2225. package/linthost/unicorn_import_style_test.go +87 -0
  2226. package/linthost/unicorn_import_style_type_only_imports_follow_value_semantics_test.go +53 -0
  2227. package/linthost/unicorn_import_style_unassigned_policy_accepts_unassigned_forms_test.go +31 -0
  2228. package/linthost/unicorn_import_style_unassigned_policy_reports_every_assigned_form_test.go +66 -0
  2229. package/linthost/unicorn_isolated_functions_arguments_test.go +48 -0
  2230. package/linthost/unicorn_isolated_functions_browser_and_page_callees_test.go +63 -0
  2231. package/linthost/unicorn_isolated_functions_comments_test.go +131 -0
  2232. package/linthost/unicorn_isolated_functions_execute_script_func_property_test.go +83 -0
  2233. package/linthost/unicorn_isolated_functions_function_name_callees_test.go +100 -0
  2234. package/linthost/unicorn_isolated_functions_helpers_test.go +76 -0
  2235. package/linthost/unicorn_isolated_functions_override_globals_test.go +92 -0
  2236. package/linthost/unicorn_isolated_functions_parameter_default_capture_test.go +47 -0
  2237. package/linthost/unicorn_isolated_functions_scope_internals_test.go +57 -0
  2238. package/linthost/unicorn_isolated_functions_selector_test.go +43 -0
  2239. package/linthost/unicorn_isolated_functions_test.go +75 -0
  2240. package/linthost/unicorn_isolated_functions_this_and_super_test.go +110 -0
  2241. package/linthost/unicorn_isolated_functions_typeof_this_test.go +45 -0
  2242. package/linthost/unicorn_isolated_functions_typescript_types_test.go +39 -0
  2243. package/linthost/unicorn_isolated_functions_unresolved_reference_test.go +41 -0
  2244. package/linthost/unicorn_known_boundary_observations_test.go +113 -0
  2245. package/linthost/unicorn_length_check_preserves_escaped_foreach_results_test.go +33 -0
  2246. package/linthost/unicorn_negative_index_requires_its_own_receiver_and_index_argument_test.go +32 -0
  2247. package/linthost/unicorn_no_hex_escape_honors_backslash_parity_test.go +63 -0
  2248. package/linthost/unicorn_no_hex_escape_ignores_non_hex_escapes_test.go +75 -0
  2249. package/linthost/unicorn_no_hex_escape_reports_interpolated_template_segments_test.go +86 -0
  2250. package/linthost/unicorn_no_hex_escape_skips_tagged_templates_test.go +57 -0
  2251. package/linthost/unicorn_no_typeof_undefined_check_global_variables_option_test.go +90 -0
  2252. package/linthost/unicorn_no_typeof_undefined_declines_unsafe_fix_test.go +50 -0
  2253. package/linthost/unicorn_no_typeof_undefined_fix_rewrites_comparisons_test.go +43 -0
  2254. package/linthost/unicorn_no_typeof_undefined_skips_upstream_valid_forms_test.go +57 -0
  2255. package/linthost/unicorn_no_typeof_undefined_test.go +88 -0
  2256. package/linthost/unicorn_no_unnecessary_polyfills_checks_only_static_string_specifiers_test.go +50 -0
  2257. package/linthost/unicorn_no_unnecessary_polyfills_config_discovery_test.go +109 -0
  2258. package/linthost/unicorn_no_unnecessary_polyfills_core_js_compat_oracle_test.go +74 -0
  2259. package/linthost/unicorn_no_unnecessary_polyfills_corpus_project_scenario_test.go +30 -0
  2260. package/linthost/unicorn_no_unnecessary_polyfills_custom_stats_discovery_test.go +45 -0
  2261. package/linthost/unicorn_no_unnecessary_polyfills_engine_oracle_test.go +101 -0
  2262. package/linthost/unicorn_no_unnecessary_polyfills_engines_discovery_test.go +29 -0
  2263. package/linthost/unicorn_no_unnecessary_polyfills_option_overrides_config_discovery_test.go +28 -0
  2264. package/linthost/unicorn_no_unnecessary_polyfills_options_test.go +38 -0
  2265. package/linthost/unicorn_no_unnecessary_polyfills_package_json_browserslist_section_test.go +25 -0
  2266. package/linthost/unicorn_no_unnecessary_polyfills_pattern_table_oracle_test.go +47 -0
  2267. package/linthost/unicorn_no_unnecessary_polyfills_rejects_malformed_options_test.go +48 -0
  2268. package/linthost/unicorn_no_unnecessary_polyfills_silent_without_resolvable_targets_test.go +26 -0
  2269. package/linthost/unicorn_no_unnecessary_polyfills_test.go +128 -0
  2270. package/linthost/unicorn_no_unnecessary_polyfills_upstream_invalid_targets_test.go +73 -0
  2271. package/linthost/unicorn_no_unused_properties_corpus_test.go +81 -0
  2272. package/linthost/unicorn_no_unused_properties_key_matching_test.go +83 -0
  2273. package/linthost/unicorn_no_unused_properties_object_literal_semantics_test.go +211 -0
  2274. package/linthost/unicorn_no_unused_properties_reference_identity_test.go +72 -0
  2275. package/linthost/unicorn_no_unused_properties_reporting_shape_test.go +89 -0
  2276. package/linthost/unicorn_no_unused_properties_script_global_scope_test.go +60 -0
  2277. package/linthost/unicorn_no_unused_properties_template_keys_test.go +35 -0
  2278. package/linthost/unicorn_no_unused_properties_type_literal_semantics_test.go +155 -0
  2279. package/linthost/unicorn_number_literal_case_fix_is_idempotent_test.go +54 -0
  2280. package/linthost/unicorn_number_literal_case_fixes_bigint_and_separated_literals_test.go +43 -0
  2281. package/linthost/unicorn_number_literal_case_fixes_every_literal_in_one_pass_test.go +37 -0
  2282. package/linthost/unicorn_number_literal_case_fixes_literals_in_every_syntactic_position_test.go +51 -0
  2283. package/linthost/unicorn_number_literal_case_fixes_radix_prefix_and_hex_digits_test.go +42 -0
  2284. package/linthost/unicorn_number_literal_case_fixes_uppercase_exponent_test.go +42 -0
  2285. package/linthost/unicorn_number_literal_case_reports_exact_range_and_message_test.go +53 -0
  2286. package/linthost/unicorn_number_literal_case_skips_canonical_literals_test.go +38 -0
  2287. package/linthost/unicorn_number_literal_case_uppercases_hex_exponent_digits_test.go +44 -0
  2288. package/linthost/unicorn_prefer_number_properties_autofixes_is_na_n_with_number_argument_test.go +24 -0
  2289. package/linthost/unicorn_prefer_number_properties_autofixes_safe_global_test.go +24 -0
  2290. package/linthost/unicorn_prefer_number_properties_checks_infinity_when_enabled_test.go +43 -0
  2291. package/linthost/unicorn_prefer_number_properties_checks_na_n_when_enabled_test.go +30 -0
  2292. package/linthost/unicorn_prefer_number_properties_expands_shorthand_fix_test.go +24 -0
  2293. package/linthost/unicorn_prefer_number_properties_fixes_negative_infinity_test.go +25 -0
  2294. package/linthost/unicorn_prefer_number_properties_interpolates_message_test.go +33 -0
  2295. package/linthost/unicorn_prefer_number_properties_leaves_infinity_and_na_n_under_defaults_test.go +24 -0
  2296. package/linthost/unicorn_prefer_number_properties_reports_object_value_positions_test.go +37 -0
  2297. package/linthost/unicorn_prefer_number_properties_skips_base10_and_missing_radix_test.go +35 -0
  2298. package/linthost/unicorn_prefer_number_properties_skips_shadowed_bindings_test.go +40 -0
  2299. package/linthost/unicorn_prefer_number_properties_suggests_unsafe_is_na_n_test.go +38 -0
  2300. package/linthost/unicorn_prefer_number_properties_test.go +81 -0
  2301. package/linthost/unicorn_prefer_number_properties_validates_options_test.go +64 -0
  2302. package/linthost/unicorn_prefer_optional_catch_binding_test.go +53 -0
  2303. package/linthost/unicorn_prefer_simple_condition_first_handles_or_chains_and_non_logical_type_wrappers_test.go +45 -0
  2304. package/linthost/unicorn_prefer_simple_condition_first_parser_aware_comments_do_not_mistake_literal_text_test.go +28 -0
  2305. package/linthost/unicorn_prefer_simple_condition_first_preserves_mixed_operators_and_parentheses_test.go +32 -0
  2306. package/linthost/unicorn_prefer_simple_condition_first_reports_exact_safe_finding_and_stable_fix_test.go +64 -0
  2307. package/linthost/unicorn_prefer_simple_condition_first_restricts_reports_to_boolean_contexts_test.go +68 -0
  2308. package/linthost/unicorn_prefer_simple_condition_first_reviews_each_homogeneous_mixed_operator_chain_test.go +55 -0
  2309. package/linthost/unicorn_prefer_simple_condition_first_uses_canonical_simple_expression_grammar_test.go +105 -0
  2310. package/linthost/unicorn_prefer_simple_condition_first_withholds_unsafe_and_syntax_owned_fixes_test.go +57 -0
  2311. package/linthost/unicorn_prefer_string_raw_survives_unterminated_literals_test.go +36 -0
  2312. package/linthost/unicorn_prevent_abbreviations_allows_generated_names_to_shadow_without_capture_test.go +23 -0
  2313. package/linthost/unicorn_prevent_abbreviations_allows_reserved_words_in_property_suggestions_test.go +43 -0
  2314. package/linthost/unicorn_prevent_abbreviations_applies_import_controls_to_static_require_bindings_test.go +29 -0
  2315. package/linthost/unicorn_prevent_abbreviations_applies_import_mode_to_external_import_equals_test.go +29 -0
  2316. package/linthost/unicorn_prevent_abbreviations_applies_internal_import_defaults_and_preserves_imported_names_test.go +40 -0
  2317. package/linthost/unicorn_prevent_abbreviations_avoids_catch_parameter_body_redeclarations_test.go +23 -0
  2318. package/linthost/unicorn_prevent_abbreviations_avoids_compiler_provided_global_bindings_test.go +23 -0
  2319. package/linthost/unicorn_prevent_abbreviations_avoids_var_lexical_early_error_collisions_test.go +23 -0
  2320. package/linthost/unicorn_prevent_abbreviations_checks_physical_filename_without_offering_edits_test.go +52 -0
  2321. package/linthost/unicorn_prevent_abbreviations_checks_shorthand_destructuring_only_when_enabled_test.go +25 -0
  2322. package/linthost/unicorn_prevent_abbreviations_does_not_apply_require_mode_to_qualified_import_equals_test.go +24 -0
  2323. package/linthost/unicorn_prevent_abbreviations_does_not_capture_outer_reads_with_unused_inner_bindings_test.go +23 -0
  2324. package/linthost/unicorn_prevent_abbreviations_does_not_capture_unresolved_names_test.go +23 -0
  2325. package/linthost/unicorn_prevent_abbreviations_does_not_report_destructuring_assignment_keys_as_properties_test.go +23 -0
  2326. package/linthost/unicorn_prevent_abbreviations_does_not_treat_destructuring_property_keys_as_collisions_test.go +23 -0
  2327. package/linthost/unicorn_prevent_abbreviations_expands_compound_and_cased_names_but_skips_constants_test.go +23 -0
  2328. package/linthost/unicorn_prevent_abbreviations_false_replacement_disables_compound_matches_test.go +23 -0
  2329. package/linthost/unicorn_prevent_abbreviations_false_replacement_stops_case_variant_fallback_test.go +22 -0
  2330. package/linthost/unicorn_prevent_abbreviations_honors_negative_replacement_and_allow_list_patches_test.go +40 -0
  2331. package/linthost/unicorn_prevent_abbreviations_honors_replacement_allow_and_ignore_options_test.go +42 -0
  2332. package/linthost/unicorn_prevent_abbreviations_ignores_detached_js_doc_when_deciding_fix_safety_test.go +47 -0
  2333. package/linthost/unicorn_prevent_abbreviations_ignores_non_lexical_jsx_and_tuple_names_for_collisions_test.go +24 -0
  2334. package/linthost/unicorn_prevent_abbreviations_keeps_exported_js_doc_and_jsx_bindings_diagnostic_only_test.go +107 -0
  2335. package/linthost/unicorn_prevent_abbreviations_keeps_independent_loop_and_switch_scopes_independent_test.go +23 -0
  2336. package/linthost/unicorn_prevent_abbreviations_keeps_mapped_and_conditional_type_scopes_independent_test.go +23 -0
  2337. package/linthost/unicorn_prevent_abbreviations_keeps_shadowed_bindings_independent_and_avoids_collisions_test.go +23 -0
  2338. package/linthost/unicorn_prevent_abbreviations_keeps_type_script_signature_scopes_independent_test.go +23 -0
  2339. package/linthost/unicorn_prevent_abbreviations_offers_whole_binding_suggestions_for_ambiguous_names_test.go +40 -0
  2340. package/linthost/unicorn_prevent_abbreviations_preserves_astral_first_rune_casing_test.go +27 -0
  2341. package/linthost/unicorn_prevent_abbreviations_preserves_canonical_upper_first_for_uncased_prefixes_test.go +23 -0
  2342. package/linthost/unicorn_prevent_abbreviations_preserves_explicit_imported_alias_names_test.go +22 -0
  2343. package/linthost/unicorn_prevent_abbreviations_preserves_exported_alias_names_test.go +35 -0
  2344. package/linthost/unicorn_prevent_abbreviations_property_checks_are_opt_in_and_suggestion_only_test.go +34 -0
  2345. package/linthost/unicorn_prevent_abbreviations_recognizes_only_canonical_static_require_calls_test.go +43 -0
  2346. package/linthost/unicorn_prevent_abbreviations_rejects_malformed_options_test.go +36 -0
  2347. package/linthost/unicorn_prevent_abbreviations_renames_class_inner_and_outer_references_together_test.go +23 -0
  2348. package/linthost/unicorn_prevent_abbreviations_renames_default_export_local_names_test.go +23 -0
  2349. package/linthost/unicorn_prevent_abbreviations_renames_merged_type_and_value_references_together_test.go +23 -0
  2350. package/linthost/unicorn_prevent_abbreviations_renames_type_predicate_references_test.go +23 -0
  2351. package/linthost/unicorn_prevent_abbreviations_reports_binding_once_and_fixes_every_reference_test.go +31 -0
  2352. package/linthost/unicorn_prevent_abbreviations_separates_generated_names_at_cross_scope_reads_test.go +23 -0
  2353. package/linthost/unicorn_prevent_abbreviations_separates_generated_names_in_one_scope_test.go +23 -0
  2354. package/linthost/unicorn_prevent_abbreviations_supports_canonical_empty_replacement_spelling_test.go +23 -0
  2355. package/linthost/unicorn_prevent_abbreviations_test.go +34 -0
  2356. package/linthost/unicorn_prevent_abbreviations_uses_default_import_control_for_named_default_syntax_test.go +25 -0
  2357. package/linthost/unicorn_prevent_abbreviations_uses_function_scope_for_destructured_var_collisions_test.go +23 -0
  2358. package/linthost/unicorn_prevent_abbreviations_uses_function_scope_for_var_collisions_test.go +23 -0
  2359. package/linthost/unicorn_prevent_abbreviations_uses_java_script_full_unicode_casing_test.go +29 -0
  2360. package/linthost/unicorn_prevent_abbreviations_uses_strict_binding_grammar_for_custom_replacements_test.go +51 -0
  2361. package/linthost/unicorn_regexp_test_requires_a_boolean_result_consumer_test.go +33 -0
  2362. package/linthost/unicorn_relative_url_style_preserves_leading_trimmed_characters_test.go +47 -0
  2363. package/linthost/unicorn_report_only_advice_exposes_semantic_preconditions_test.go +48 -0
  2364. package/linthost/unicorn_rule_finding_helpers_test.go +14 -0
  2365. package/linthost/unicorn_rule_names_helpers_test.go +11 -0
  2366. package/linthost/unicorn_single_call_excludes_event_listener_registration_test.go +30 -0
  2367. package/linthost/unicorn_slice_end_preserves_other_receiver_bounds_test.go +30 -0
  2368. package/linthost/unicorn_splice_count_preserves_bounds_and_insertions_test.go +33 -0
  2369. package/linthost/unicorn_spread_fallback_is_load_bearing_for_arrays_test.go +31 -0
  2370. package/linthost/unicorn_string_content_applies_first_matching_pattern_in_configured_order_test.go +55 -0
  2371. package/linthost/unicorn_string_content_escapes_backticks_and_dollars_in_template_fix_test.go +75 -0
  2372. package/linthost/unicorn_string_content_escapes_delimiter_quotes_in_literal_fix_test.go +60 -0
  2373. package/linthost/unicorn_string_content_escapes_line_separators_keeps_other_whitespace_raw_test.go +79 -0
  2374. package/linthost/unicorn_string_content_fix_false_reports_suggestion_only_test.go +73 -0
  2375. package/linthost/unicorn_string_content_honors_custom_message_and_placeholders_test.go +41 -0
  2376. package/linthost/unicorn_string_content_jsx_attribute_fix_uses_html_entities_test.go +103 -0
  2377. package/linthost/unicorn_string_content_matches_case_insensitively_when_configured_test.go +68 -0
  2378. package/linthost/unicorn_string_content_normalizes_template_line_endings_like_acorn_test.go +87 -0
  2379. package/linthost/unicorn_string_content_preserves_control_escapes_in_literal_fix_test.go +93 -0
  2380. package/linthost/unicorn_string_content_rejects_malformed_options_before_linting_test.go +79 -0
  2381. package/linthost/unicorn_string_content_reports_and_fixes_plain_string_literal_test.go +54 -0
  2382. package/linthost/unicorn_string_content_reports_each_template_quasi_at_exact_ranges_test.go +61 -0
  2383. package/linthost/unicorn_string_content_selector_matches_keep_ignored_tag_exemption_test.go +33 -0
  2384. package/linthost/unicorn_string_content_selectors_restrict_checked_nodes_test.go +68 -0
  2385. package/linthost/unicorn_string_content_skips_empty_and_non_string_literals_test.go +43 -0
  2386. package/linthost/unicorn_string_content_skips_ignored_template_tags_test.go +81 -0
  2387. package/linthost/unicorn_string_content_stays_silent_without_pattern_options_test.go +34 -0
  2388. package/linthost/unicorn_string_content_treats_pattern_as_regular_expression_test.go +77 -0
  2389. package/linthost/unicorn_switch_case_break_position_declines_unsafe_or_semantic_moves_test.go +111 -0
  2390. package/linthost/unicorn_switch_case_break_position_fix_preserves_statements_comments_and_eol_test.go +187 -0
  2391. package/linthost/unicorn_switch_case_break_position_reports_every_supported_terminator_at_exact_range_test.go +132 -0
  2392. package/linthost/unicorn_switch_case_break_position_requires_sole_non_empty_block_then_direct_terminator_test.go +112 -0
  2393. package/linthost/unicorn_template_indent_accepts_parenthesized_jest_inline_snapshot_test.go +26 -0
  2394. package/linthost/unicorn_template_indent_detects_tabs_outside_templates_test.go +31 -0
  2395. package/linthost/unicorn_template_indent_falls_back_to_two_spaces_without_any_indent_signal_test.go +23 -0
  2396. package/linthost/unicorn_template_indent_fix_preserves_quasis_substitutions_escapes_and_blank_lines_test.go +71 -0
  2397. package/linthost/unicorn_template_indent_fixes_empty_boundary_quasis_with_insertions_test.go +37 -0
  2398. package/linthost/unicorn_template_indent_fixes_nested_templates_without_touching_expressions_test.go +52 -0
  2399. package/linthost/unicorn_template_indent_honors_configured_tags_functions_comments_and_selectors_test.go +69 -0
  2400. package/linthost/unicorn_template_indent_honors_numeric_and_whitespace_indent_options_test.go +51 -0
  2401. package/linthost/unicorn_template_indent_pins_every_default_matcher_test.go +46 -0
  2402. package/linthost/unicorn_template_indent_preserves_content_trailing_spaces_test.go +31 -0
  2403. package/linthost/unicorn_template_indent_preserves_crlf_test.go +35 -0
  2404. package/linthost/unicorn_template_indent_preserves_every_interior_ecma_script_line_ending_test.go +39 -0
  2405. package/linthost/unicorn_template_indent_preserves_leading_byte_order_mark_test.go +27 -0
  2406. package/linthost/unicorn_template_indent_preserves_mixed_interior_line_endings_test.go +35 -0
  2407. package/linthost/unicorn_template_indent_recognizes_every_ecma_script_source_line_separator_test.go +48 -0
  2408. package/linthost/unicorn_template_indent_rejects_jest_inline_snapshot_near_misses_test.go +35 -0
  2409. package/linthost/unicorn_template_indent_rejects_malformed_options_before_linting_test.go +52 -0
  2410. package/linthost/unicorn_template_indent_selects_every_official_entry_point_at_exact_range_test.go +56 -0
  2411. package/linthost/unicorn_template_indent_skips_unselected_single_line_and_already_correct_templates_test.go +37 -0
  2412. package/linthost/unicorn_template_indent_test.go +20 -0
  2413. package/linthost/unicorn_text_encoding_identifier_case_enforces_dash_in_jsx_charset_attributes_test.go +69 -0
  2414. package/linthost/unicorn_text_encoding_identifier_case_enforces_dash_in_text_decoder_test.go +47 -0
  2415. package/linthost/unicorn_text_encoding_identifier_case_fixes_fs_read_file_encoding_test.go +44 -0
  2416. package/linthost/unicorn_text_encoding_identifier_case_handles_template_literals_test.go +46 -0
  2417. package/linthost/unicorn_text_encoding_identifier_case_reports_suggestion_range_and_message_test.go +78 -0
  2418. package/linthost/unicorn_text_encoding_identifier_case_skips_canonical_and_unknown_labels_test.go +35 -0
  2419. package/linthost/unicorn_text_encoding_identifier_case_suggests_without_fixing_off_read_file_positions_test.go +36 -0
  2420. package/linthost/unicorn_text_encoding_identifier_case_withdash_option_prefers_dash_test.go +52 -0
  2421. package/linthost/unicorn_throw_new_error_fix_parenthesizes_a_shielded_call_chain_test.go +69 -0
  2422. package/linthost/unicorn_throw_new_error_fix_spaces_an_abutting_throw_keyword_test.go +64 -0
  2423. package/linthost/unicorn_throw_new_error_fixes_every_throw_in_one_pass_test.go +42 -0
  2424. package/linthost/unicorn_throw_new_error_fixes_upstream_invalid_corpus_test.go +114 -0
  2425. package/linthost/unicorn_throw_new_error_reports_custom_and_member_callees_test.go +62 -0
  2426. package/linthost/unicorn_throw_new_error_skips_non_matching_callees_test.go +68 -0
  2427. package/linthost/unregistered_rule_code_lookup_preserves_registered_assignments_test.go +102 -0
  2428. package/linthost/use_unknown_in_catch_callback_variable_test.go +48 -0
  2429. package/linthost/user_pattern_cache_follows_resolver_ownership_test.go +87 -0
  2430. package/linthost/user_pattern_cache_parallel_reuses_results_test.go +67 -0
  2431. package/linthost/user_source_files_exclude_imported_declarations_and_javascript_test.go +82 -0
  2432. package/linthost/user_source_files_span_program_typescript_sources_test.go +72 -0
  2433. package/linthost/valid_typeof_equality_operator_scope_test.go +173 -0
  2434. package/linthost/verbatim_range_returns_empty_for_invalid_range_test.go +53 -0
  2435. package/linthost/verbatim_returns_empty_for_nil_node_test.go +30 -0
  2436. package/linthost/verbatim_returns_empty_for_out_of_range_node_test.go +52 -0
  2437. package/linthost/vitest_expect_expect_reports_empty_test_test.go +35 -0
  2438. package/linthost/vitest_finding_helpers_test.go +14 -0
  2439. package/linthost/vitest_no_conditional_expect_reports_expect_inside_if_test.go +37 -0
  2440. package/linthost/vitest_no_conditional_tests_reports_test_inside_if_test.go +35 -0
  2441. package/linthost/vitest_no_disabled_tests_reports_skip_test.go +34 -0
  2442. package/linthost/vitest_no_done_callback_reports_test_parameter_test.go +34 -0
  2443. package/linthost/vitest_no_focused_tests_reports_only_test.go +34 -0
  2444. package/linthost/vitest_no_identical_title_reports_duplicate_sibling_test.go +35 -0
  2445. package/linthost/vitest_no_standalone_expect_reports_top_level_expect_test.go +33 -0
  2446. package/linthost/vitest_no_test_return_statement_reports_return_test.go +35 -0
  2447. package/linthost/vitest_prefer_to_have_length_reports_length_matcher_test.go +34 -0
  2448. package/linthost/vitest_valid_describe_callback_reports_async_callback_test.go +34 -0
  2449. package/linthost/vitest_valid_expect_reports_missing_matcher_test.go +35 -0
  2450. package/linthost/vitest_valid_title_reports_empty_title_test.go +34 -0
  2451. package/linthost/wait_for_assertion_and_side_effect_guards_test.go +55 -0
  2452. package/linthost/windows_junction_dependency_entry_matches_node_fingerprint_test.go +55 -0
  2453. package/linthost/windows_loader_temp_base_stays_on_config_volume_test.go +98 -0
  2454. package/linthost/windows_project_source_selection_preserves_physical_aliases_test.go +69 -0
  2455. package/linthost/windows_real_project_path_expands_windows_short_ancestor_test.go +47 -0
  2456. package/linthost/windows_resolve_config_tsgo_through_linked_typescript_install_test.go +52 -0
  2457. package/linthost/windows_short_path_other_test.go +11 -0
  2458. package/linthost/windows_short_path_windows_test.go +39 -0
  2459. package/linthost/workspace_link_resolves_a_sibling_package_to_its_source_test.go +86 -0
  2460. package/package.json +5 -3
  2461. package/rule/astutil/astutil.go +165 -59
  2462. package/rule/context_decode_options_preserves_defaults_and_decoder_errors_test.go +87 -0
  2463. package/rule/graph.go +82 -16
  2464. package/rule/hint.go +95 -28
  2465. package/rule/new_project_context_preserves_snapshot_ownership_test.go +62 -0
  2466. package/rule/new_project_input_context_preserves_owned_options_test.go +59 -0
  2467. package/rule/new_project_rule_result_preserves_snapshot_ownership_test.go +63 -0
  2468. package/rule/project.go +382 -22
  2469. package/rule/project_input_reader.go +163 -0
  2470. package/rule/rule.go +540 -92
  2471. package/src/createTtscPlugin.ts +3010 -0
  2472. package/src/index.ts +1 -2974
  2473. package/src/internal/configEvaluatorFailure.ts +17 -9
  2474. package/src/internal/lintTrace.ts +106 -0
  2475. package/src/internal/normalizeContributors.ts +79 -0
  2476. package/src/structures/ITtscLintConfig.ts +27 -8
  2477. package/src/structures/ITtscLintPlugin.ts +13 -8
  2478. package/src/structures/ITtscLintPluginConfig.ts +18 -7
  2479. package/src/structures/ITtscLintPluginMeta.ts +10 -7
  2480. package/src/structures/TtscLintRuleSetting.ts +18 -13
  2481. package/src/structures/TtscLintSeverity.ts +5 -0
  2482. package/src/structures/format/ITtscLintFormat.ts +14 -8
  2483. package/src/structures/format/ITtscLintFormatJsDoc.ts +8 -1
  2484. package/src/structures/format/ITtscLintFormatSortImports.ts +14 -8
  2485. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +133 -25
  2486. package/src/structures/rules/ITtscLintBoundariesRules.ts +10 -5
  2487. package/src/structures/rules/ITtscLintContributorRules.ts +20 -13
  2488. package/src/structures/rules/ITtscLintCoreRuleOptions.ts +226 -24
  2489. package/src/structures/rules/ITtscLintCoreRules.ts +92 -72
  2490. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +8 -1
  2491. package/src/structures/rules/ITtscLintCypressRules.ts +24 -21
  2492. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +140 -24
  2493. package/src/structures/rules/ITtscLintFunctionalRules.ts +20 -12
  2494. package/src/structures/rules/ITtscLintJestRules.ts +22 -16
  2495. package/src/structures/rules/ITtscLintJsdocRules.ts +5 -0
  2496. package/src/structures/rules/ITtscLintJsxA11yRules.ts +24 -21
  2497. package/src/structures/rules/ITtscLintNextjsRules.ts +40 -42
  2498. package/src/structures/rules/ITtscLintPlaywrightRules.ts +24 -14
  2499. package/src/structures/rules/ITtscLintPromiseRules.ts +23 -14
  2500. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +8 -1
  2501. package/src/structures/rules/ITtscLintReactPerfRules.ts +18 -15
  2502. package/src/structures/rules/ITtscLintReactRuleOptions.ts +14 -4
  2503. package/src/structures/rules/ITtscLintReactRules.ts +33 -27
  2504. package/src/structures/rules/ITtscLintRegexpRules.ts +18 -4
  2505. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +150 -15
  2506. package/src/structures/rules/ITtscLintRules.ts +13 -9
  2507. package/src/structures/rules/ITtscLintSecurityRules.ts +33 -23
  2508. package/src/structures/rules/ITtscLintSolidRules.ts +57 -47
  2509. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +10 -2
  2510. package/src/structures/rules/ITtscLintStorybookRules.ts +52 -62
  2511. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +34 -30
  2512. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +12 -3
  2513. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +20 -15
  2514. package/src/structures/rules/ITtscLintTypeScriptRuleOptions.ts +116 -16
  2515. package/src/structures/rules/ITtscLintTypeScriptRules.ts +62 -51
  2516. package/src/structures/rules/ITtscLintUnicornRuleOptions.ts +241 -48
  2517. package/src/structures/rules/ITtscLintUnicornRules.ts +97 -44
  2518. package/src/structures/rules/ITtscLintVitestRules.ts +19 -11
  2519. package/src/structures/rules/TtscLintContributorOverlay.ts +40 -0
  2520. package/src/structures/rules/index.ts +1 -0
@@ -16,11 +16,21 @@ import (
16
16
  "sort"
17
17
  "strings"
18
18
  "sync"
19
+ "time"
19
20
 
20
21
  "github.com/samchon/ttsc/packages/ttsc/driver/windowsjunction"
21
22
  )
22
23
 
23
24
  // Severity is the `error | warning | off` ladder.
25
+ //
26
+ // @evidence contracts/common.md#principled-implementation Ordered constants represent disabled, warning and error states; unknown integers remain distinguishable through String.
27
+ // @evidence contracts/common.md#clear-and-simple-design One scalar severity keeps reporting policy independent from each rule's option shape.
28
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The constants define the public severity ladder rather than consumer-specific outcomes.
29
+ // @evidence contracts/common.md#meaningful-documentation The native comment names the three supported states, with prose separated from acknowledgment tags.
30
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation Severity is a declaration of data shape and performs no filesystem, path or process operation.
31
+ // @evidenceExclude contracts/performance.md#efficient-algorithms Severity is a declaration of data shape and chooses no algorithm or processing strategy.
32
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work Severity is a declaration of data shape and coordinates no computation that could be shared.
33
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Severity is a declaration of data shape; the code that holds its values owns their lifetime.
24
34
  type Severity int
25
35
 
26
36
  const (
@@ -29,6 +39,16 @@ const (
29
39
  SeverityError
30
40
  )
31
41
 
42
+ // String returns the configuration spelling, or "unknown" for an unsupported value.
43
+ //
44
+ // @evidence contracts/common.md#principled-implementation The exhaustive supported-state switch maps each severity to its config spelling without treating unknown integers as off.
45
+ // @evidence contracts/common.md#clear-and-simple-design A local switch owns the display mapping and requires no rule-specific formatter.
46
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Literal spellings are the severity protocol, not replacements for evaluated rule results.
47
+ // @evidence contracts/common.md#meaningful-documentation The native comment states both supported conversion and the unknown-value result in a separate paragraph from tags.
48
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation Severity.String performs no filesystem or process operation of its own.
49
+ // @evidenceExclude contracts/performance.md#efficient-algorithms Severity.String has no loop of its own and runs a fixed number of steps.
50
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work Severity.String keeps no cache and shares no in-flight computation.
51
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Severity.String acquires no handle or task and retains nothing beyond the receiver's own fields.
32
52
  func (s Severity) String() string {
33
53
  switch s {
34
54
  case SeverityError:
@@ -45,13 +65,39 @@ func (s Severity) String() string {
45
65
  //
46
66
  // `Config` carries the original tsconfig plugin entry. `Name` and `Stage`
47
67
  // come from the JS plugin descriptor returned to the ttsc host.
68
+ //
69
+ // @evidence contracts/common.md#principled-implementation JSON field names match the compiler's serialized descriptor envelope while Config preserves arbitrary plugin-entry values for boundary validation.
70
+ // @evidence contracts/common.md#clear-and-simple-design The original entry and evaluated descriptor identity remain separate fields because they have different producers.
71
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts This DTO preserves host input and adds no plugin-specific execution or foreign mutation.
72
+ // @evidence contracts/common.md#meaningful-documentation Native prose identifies each field's producer, and spaced field comments explain their roles without property acknowledgments.
73
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation PluginEntry is a declaration of data shape and performs no filesystem, path or process operation.
74
+ // @evidenceExclude contracts/performance.md#efficient-algorithms PluginEntry is a declaration of data shape and chooses no algorithm or processing strategy.
75
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work PluginEntry is a declaration of data shape and coordinates no computation that could be shared.
76
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources PluginEntry is a declaration of data shape; the code that holds its values owns their lifetime.
48
77
  type PluginEntry struct {
78
+ // Config is the original tsconfig plugin entry, including configFile.
49
79
  Config map[string]any `json:"config"`
50
- Name string `json:"name"`
51
- Stage string `json:"stage"`
80
+
81
+ // Name is the identity returned by the evaluated plugin descriptor.
82
+ Name string `json:"name"`
83
+
84
+ // Stage is the descriptor's host execution stage.
85
+ Stage string `json:"stage"`
52
86
  }
53
87
 
54
88
  // ParsePlugins decodes the `--plugins-json` payload.
89
+ // Empty or whitespace-only input means no entries; malformed JSON returns a contextual error.
90
+ // Parsing examines the supplied payload and allocates decoded records and their
91
+ // configuration values. The caller owns the returned records.
92
+ //
93
+ // @evidence contracts/common.md#principled-implementation encoding/json decodes the host envelope into PluginEntry records; the explicit empty-input case represents an absent descriptor list.
94
+ // @evidence contracts/common.md#clear-and-simple-design Parsing and contextual error wrapping form one boundary operation, leaving lint selection to FindLintEntry.
95
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The absence case follows the host protocol and does not fabricate entries to satisfy a consumer.
96
+ // @evidence contracts/common.md#meaningful-documentation Native prose states absence and malformed-input effects, with a blank comment line before tags.
97
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation ParsePlugins performs no filesystem or process operation of its own.
98
+ // @evidence contracts/performance.md#efficient-algorithms Trimming, byte conversion and JSON decoding scale with payload size; decoded entries and configuration values determine result storage. One complete parse is necessary to validate and decode this supplied envelope without a second custom traversal.
99
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work ParsePlugins keeps no cache and shares no in-flight computation.
100
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources ParsePlugins owns no retained state, handle or running task; decoded records are transferred to the caller and temporary results from a failed parse are not retained.
55
101
  func ParsePlugins(text string) ([]PluginEntry, error) {
56
102
  if strings.TrimSpace(text) == "" {
57
103
  return nil, nil
@@ -66,6 +112,16 @@ func ParsePlugins(text string) ([]PluginEntry, error) {
66
112
  // FindLintEntry returns the active lint entry. ttsc orders check plugins before
67
113
  // transform plugins before invoking native sidecars, so lint inspects authored
68
114
  // source even when transform plugins are also configured.
115
+ // The returned pointer refers to the caller's slice; absence returns nil without an error.
116
+ //
117
+ // @evidence contracts/common.md#principled-implementation A declaration-order scan selects the descriptor with the public lint package identity and returns its actual record.
118
+ // @evidence contracts/common.md#clear-and-simple-design Selection uses the descriptor Name and leaves host staging and config evaluation with their existing owners.
119
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The package identity is the supported descriptor protocol; no consumer or fixture name alters selection.
120
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains host ordering, alias ownership and the absent result, separated visibly from tags.
121
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation FindLintEntry compares plugin names and touches no filesystem path or process.
122
+ // @evidence contracts/performance.md#efficient-algorithms A linear scan that stops at the first @ttsc/lint entry, O(entries).
123
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work FindLintEntry keeps no cache and shares no computation.
124
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources FindLintEntry returns a pointer into the caller's slice and allocates nothing.
69
125
  func FindLintEntry(entries []PluginEntry) (*PluginEntry, error) {
70
126
  for i := range entries {
71
127
  if entries[i].Name == "@ttsc/lint" {
@@ -77,53 +133,122 @@ func FindLintEntry(entries []PluginEntry) (*PluginEntry, error) {
77
133
 
78
134
  // RuleConfig captures the resolved per-rule severity. The map is keyed by
79
135
  // rule name (e.g. "no-var").
136
+ // ResolveProjectRules validates duplicate canonical identities before the engine
137
+ // reads this map. Direct metadata consumers must perform that validation first.
138
+ //
139
+ // @evidence contracts/common.md#principled-implementation A name-keyed map represents one severity per rule; ResolveProjectRules rejects colliding canonical identities before engine projections can detach severity from options.
140
+ // @evidence contracts/common.md#clear-and-simple-design The severity-only representation also implements RuleResolver without requiring option or file-scope storage.
141
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The map represents supplied policy rather than cached diagnostics or expected outputs.
142
+ // @evidence contracts/common.md#meaningful-documentation Native prose identifies the severity-only role and the validation prerequisite for direct metadata consumers.
143
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleConfig is a declaration of data shape and performs no filesystem, path or process operation.
144
+ // @evidenceExclude contracts/performance.md#efficient-algorithms RuleConfig is a declaration of data shape and chooses no algorithm or processing strategy.
145
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleConfig is a declaration of data shape and coordinates no computation that could be shared.
146
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources RuleConfig is a declaration of data shape; the code that holds its values owns their lifetime.
80
147
  type RuleConfig map[string]Severity
81
148
 
82
149
  // RuleOptionsMap captures the rule-specific options payload, keyed by rule
83
150
  // name. Severity-only rules never appear here. A single option slot preserves
84
151
  // its JSON shape; multiple positional slots are encoded as an array. Each rule
85
152
  // decodes the payload according to its public option type on demand.
153
+ //
154
+ // @evidence contracts/common.md#principled-implementation Raw JSON preserves each rule's option representation independently from severity storage; the owning rule interprets the payload and owns any option validation it supports.
155
+ // @evidence contracts/common.md#clear-and-simple-design A parallel name-keyed map keeps heterogeneous option types out of the engine-facing severity representation.
156
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Option payloads remain supplied configuration, with no hardcoded result or foreign decoder patch.
157
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains absent options and single-versus-multiple-slot encoding, then separates the acknowledgments.
158
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleOptionsMap is a declaration of data shape and performs no filesystem, path or process operation.
159
+ // @evidenceExclude contracts/performance.md#efficient-algorithms RuleOptionsMap is a declaration of data shape and chooses no algorithm or processing strategy.
160
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleOptionsMap is a declaration of data shape and coordinates no computation that could be shared.
161
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources RuleOptionsMap is a declaration of data shape; the code that holds its values owns their lifetime.
86
162
  type RuleOptionsMap map[string]json.RawMessage
87
163
 
88
164
  // ProjectRuleSetting is the global declaration resolved for one registered
89
165
  // project rule. Declared distinguishes a missing entry from an explicit off.
166
+ //
167
+ // @evidence contracts/common.md#principled-implementation An independent presence bit preserves the distinction between an absent project rule and an explicitly disabled rule.
168
+ // @evidence contracts/common.md#clear-and-simple-design Presence, severity and optional raw options form one resolved project setting without retaining file-specific scope.
169
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The presence distinction models supported config semantics rather than inferring declaration from a severity default.
170
+ // @evidence contracts/common.md#meaningful-documentation The type and spaced member comments explain absence and payload meaning without property tags.
171
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation ProjectRuleSetting is a declaration of data shape and performs no filesystem, path or process operation.
172
+ // @evidenceExclude contracts/performance.md#efficient-algorithms ProjectRuleSetting is a declaration of data shape and chooses no algorithm or processing strategy.
173
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work ProjectRuleSetting is a declaration of data shape and coordinates no computation that could be shared.
174
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources ProjectRuleSetting is a declaration of data shape; the code that holds its values owns their lifetime.
90
175
  type ProjectRuleSetting struct {
176
+ // Declared reports whether a matching global entry explicitly named the rule.
91
177
  Declared bool
178
+
179
+ // Severity is meaningful as a declaration only when Declared is true.
92
180
  Severity Severity
93
- Options json.RawMessage
181
+
182
+ // Options is the resolved raw payload, possibly inherited from an earlier
183
+ // global declaration. It is nil when no payload was contributed.
184
+ Options json.RawMessage
94
185
  }
95
186
 
96
187
  // ResolvedRuleConfig is the complete rule setting that applies to one source
97
- // file. Rules and Options are folded from the same matching config entries so
98
- // an option tuple can never cross a files/ignores boundary independently of
99
- // its severity.
188
+ // file. Built-in config-store resolution folds Rules and Options from the
189
+ // same matching entries. Custom resolvers must preserve that ownership rather
190
+ // than borrowing an option tuple from an entry outside the file's scope.
100
191
  //
101
192
  // `Ignored` means an `ignores`-only config entry matched the file and the
102
193
  // engine should skip linting it entirely. `OutOfScope` means the store has at
103
194
  // least one rule-bearing entry but none applies to this file. Keeping the two
104
195
  // states distinct lets wrappers preserve entry-local ignores: one entry may
105
196
  // reject a file while another matching entry still contributes rules.
197
+ //
198
+ // @evidence contracts/common.md#principled-implementation Paired severity and option maps carry the resolver's matching-entry policy without encoding one field into the other; separate ignored and out-of-scope states distinguish exclusion from no contributing declaration.
199
+ // @evidence contracts/common.md#clear-and-simple-design The value carries a single file's resolution with an explicit authority bit for compatibility with older custom resolvers.
200
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts OptionsResolved distinguishes a real interface capability instead of substituting an empty map for unresolved data.
201
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains scope and compatibility states; each public field has its own spaced comment and no checklist tag.
202
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation ResolvedRuleConfig is a declaration of data shape and performs no filesystem, path or process operation.
203
+ // @evidenceExclude contracts/performance.md#efficient-algorithms ResolvedRuleConfig is a declaration of data shape and chooses no algorithm or processing strategy.
204
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work ResolvedRuleConfig is a declaration of data shape and coordinates no computation that could be shared.
205
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources ResolvedRuleConfig is a declaration of data shape; the code that holds its values owns their lifetime.
106
206
  type ResolvedRuleConfig struct {
107
- Rules RuleConfig
207
+ // Rules contains the severities contributed by matching entries.
208
+ Rules RuleConfig
209
+
210
+ // Options contains payloads inherited only through the same matching entries.
108
211
  Options RuleOptionsMap
212
+
109
213
  // OptionsResolved distinguishes an authoritative empty per-file option map
110
214
  // from a legacy custom resolver that still supplies options exclusively via
111
215
  // RuleResolver.RuleOptions.
112
216
  OptionsResolved bool
113
- Ignored bool
114
- OutOfScope bool
217
+
218
+ // Ignored requests skipping this file entirely after a global ignore match.
219
+ Ignored bool
220
+
221
+ // OutOfScope reports that rule-bearing entries exist but none selects this file.
222
+ OutOfScope bool
115
223
  }
116
224
 
117
225
  // RuleOptions returns the file-resolved option payload for name. Built-in
118
226
  // aliases are normalized on lookup so the same key selects both severity and
119
227
  // options.
228
+ // The returned slice is the stored payload, so callers must treat it as read-only.
229
+ // The supplying resolver must reject colliding canonical keys before execution.
230
+ //
231
+ // @evidence contracts/common.md#principled-implementation Exact, canonical and unique normalized-alias lookup read the file's authoritative option map without falling back to another file's declaration.
232
+ // @evidence contracts/common.md#clear-and-simple-design Lookup remains on the resolved value so execution need not repeat config-entry folding.
233
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Namespace normalization follows the rule naming contract and does not select a payload by consumer identity.
234
+ // @evidence contracts/common.md#meaningful-documentation Native prose states normalization, absence and borrowed slice ownership with tags in a separate comment paragraph.
235
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleOptions looks up option bytes by rule name and touches no filesystem path or process.
236
+ // @evidence contracts/performance.md#efficient-algorithms Exact and canonical keys use an expected constant number of map probes, with hashing and normalization proportional to query-name bytes. Only a miss scans n stored names, paying their normalization/comparison byte costs; option bytes are returned without decoding or copying.
237
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleOptions keeps no cache and shares no computation.
238
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources RuleOptions returns the stored message without copying; the resolved configuration owns it.
120
239
  func (r ResolvedRuleConfig) RuleOptions(name string) json.RawMessage {
121
240
  if raw := r.Options[name]; len(raw) > 0 {
122
241
  return raw
123
242
  }
124
- if raw := r.Options[normalizeBuiltinRuleName(name)]; len(raw) > 0 {
243
+ canonical := normalizeBuiltinRuleName(name)
244
+ if raw := r.Options[canonical]; len(raw) > 0 {
125
245
  return raw
126
246
  }
247
+ for storedName, raw := range r.Options {
248
+ if normalizeBuiltinRuleName(storedName) == canonical {
249
+ return raw
250
+ }
251
+ }
127
252
  return nil
128
253
  }
129
254
 
@@ -132,36 +257,115 @@ func (r ResolvedRuleConfig) RuleOptions(name string) json.RawMessage {
132
257
  // InlineRuleResolver (a severity map plus per-rule options), and *ConfigStore
133
258
  // (a parsed lint config file, with per-file glob resolution for both severity
134
259
  // and options).
260
+ //
261
+ // @evidence contracts/common.md#principled-implementation Separate per-file and global operations express which config decisions have a file identity and which build dispatch or project state.
262
+ // @evidence contracts/common.md#clear-and-simple-design The interface exposes resolution behavior rather than parsed entries, allowing flat and scoped implementations to share the engine boundary.
263
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Compatibility lookup is an explicit supported interface method, not a patch of another resolver's internals.
264
+ // @evidence contracts/common.md#meaningful-documentation Native prose names implementations and method comments describe scope, absence and precedence with blank lines between members.
265
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleResolver is a declaration of data shape and performs no filesystem, path or process operation.
266
+ // @evidenceExclude contracts/performance.md#efficient-algorithms RuleResolver is a declaration of data shape and chooses no algorithm or processing strategy.
267
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleResolver is a declaration of data shape and coordinates no computation that could be shared.
268
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources RuleResolver is a declaration of data shape; the code that holds its values owns their lifetime.
135
269
  type RuleResolver interface {
136
270
  // ResolveRules returns the effective severities and option payloads for the
137
271
  // given source file. Implementations that support `files`/`ignores`
138
272
  // patterns apply both halves of each rule setting here; flat RuleConfig
139
- // always returns all severities unchanged and no options.
273
+ // returns all severities with canonical built-in keys and no options.
274
+ //
275
+ // @evidence contracts/common.md#principled-implementation Returning severity and options together makes one file-selection decision authoritative for both parts of a setting.
276
+ // @evidence contracts/common.md#clear-and-simple-design One resolution call exposes the file-bound value without requiring engine access to entry storage.
277
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The interface delegates scope through a supported method rather than probing concrete resolver internals.
278
+ // @evidence contracts/common.md#meaningful-documentation The native method comment explains flat versus scoped semantics before a separate tag paragraph.
279
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleResolver.ResolveRules is a method signature without a body; each implementation owns any filesystem or process behavior.
280
+ // @evidenceExclude contracts/performance.md#efficient-algorithms RuleResolver.ResolveRules is a method signature without a body; each implementation chooses its own algorithm.
281
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleResolver.ResolveRules is a method signature without a body; each implementation decides what, if anything, to share.
282
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources RuleResolver.ResolveRules is a method signature without a body; each implementation owns any retained state.
140
283
  ResolveRules(fileName string) ResolvedRuleConfig
284
+
141
285
  // ActiveRuleNames returns the sorted names of every rule that is not SeverityOff
142
286
  // in at least one config entry. Used to build the engine's dispatch table.
287
+ //
288
+ // @evidence contracts/common.md#principled-implementation The union of potentially enabled names lets dispatch construction retain rules that apply to only some files.
289
+ // @evidence contracts/common.md#clear-and-simple-design The method supplies ordered identities rather than exposing a second executable config model.
290
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The activity definition follows declarations, not whether a known fixture produced a diagnostic.
291
+ // @evidence contracts/common.md#meaningful-documentation Native prose states sorting, potential activity and the dispatch consumer with separated tags.
292
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleResolver.ActiveRuleNames is a method signature without a body; each implementation owns any filesystem or process behavior.
293
+ // @evidenceExclude contracts/performance.md#efficient-algorithms RuleResolver.ActiveRuleNames is a method signature without a body; each implementation chooses its own algorithm.
294
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleResolver.ActiveRuleNames is a method signature without a body; each implementation decides what, if anything, to share.
295
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources RuleResolver.ActiveRuleNames is a method signature without a body; each implementation owns any retained state.
143
296
  ActiveRuleNames() []string
297
+
144
298
  // EnabledRuleConfig returns the project-wide severity map for rules that are
145
299
  // not SeverityOff. Where multiple entries disagree, SeverityError wins.
300
+ //
301
+ // @evidence contracts/common.md#principled-implementation The aggregate severity map represents potential project reporting, while file execution remains owned by ResolveRules.
302
+ // @evidence contracts/common.md#clear-and-simple-design Global metadata has a named operation distinct from per-file resolution.
303
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Severity aggregation is an explicit interface policy rather than an inferred result from test outputs.
304
+ // @evidence contracts/common.md#meaningful-documentation The method comment states off filtering and error precedence in native prose before tags.
305
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleResolver.EnabledRuleConfig is a method signature without a body; each implementation owns any filesystem or process behavior.
306
+ // @evidenceExclude contracts/performance.md#efficient-algorithms RuleResolver.EnabledRuleConfig is a method signature without a body; each implementation chooses its own algorithm.
307
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleResolver.EnabledRuleConfig is a method signature without a body; each implementation decides what, if anything, to share.
308
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources RuleResolver.EnabledRuleConfig is a method signature without a body; each implementation owns any retained state.
146
309
  EnabledRuleConfig() RuleConfig
310
+
147
311
  // RuleOptions is the file-agnostic compatibility lookup used by flat and
148
312
  // metadata-only consumers. Runtime file binding reads
149
313
  // ResolveRules(fileName).RuleOptions(name), which is authoritative for
150
314
  // scoped resolvers. Returns nil for severity-only and unknown rules.
315
+ //
316
+ // @evidence contracts/common.md#principled-implementation This file-agnostic lookup supports older flat consumers without overriding authoritative per-file option resolution.
317
+ // @evidence contracts/common.md#clear-and-simple-design The compatibility boundary is visible as one method instead of hidden fallback state inside the engine.
318
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Retaining this method addresses supported resolver compatibility rather than compensating for a false scope assumption.
319
+ // @evidence contracts/common.md#meaningful-documentation Native prose identifies the compatibility consumer and nil result, separate from the acknowledgment paragraph.
320
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleResolver.RuleOptions is a method signature without a body; each implementation owns any filesystem or process behavior.
321
+ // @evidenceExclude contracts/performance.md#efficient-algorithms RuleResolver.RuleOptions is a method signature without a body; each implementation chooses its own algorithm.
322
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleResolver.RuleOptions is a method signature without a body; each implementation decides what, if anything, to share.
323
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources RuleResolver.RuleOptions is a method signature without a body; each implementation owns any retained state.
151
324
  RuleOptions(name string) json.RawMessage
325
+
152
326
  // ResolveProjectRules folds global declarations for registered project-rule
153
327
  // names. A mention under a files selector is rejected because project state
154
328
  // has no file identity, except when the same built-in name also owns a file
155
329
  // rule; that scoped declaration remains exclusively file-local.
330
+ //
331
+ // @evidence contracts/common.md#principled-implementation Project settings have no file identity, so the operation rejects file-only declarations except a shared name whose file companion owns that scope.
332
+ // @evidence contracts/common.md#clear-and-simple-design A single project-resolution boundary owns global policy and errors before rule-state construction.
333
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The built-in companion exception represents an actual dual registration, not a consumer-specific whitelist.
334
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains the scope rejection and companion distinction with a separate tag paragraph.
335
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleResolver.ResolveProjectRules is a method signature without a body; each implementation owns any filesystem or process behavior.
336
+ // @evidenceExclude contracts/performance.md#efficient-algorithms RuleResolver.ResolveProjectRules is a method signature without a body; each implementation chooses its own algorithm.
337
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleResolver.ResolveProjectRules is a method signature without a body; each implementation decides what, if anything, to share.
338
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources RuleResolver.ResolveProjectRules is a method signature without a body; each implementation owns any retained state.
156
339
  ResolveProjectRules(names []string) (map[string]ProjectRuleSetting, error)
157
340
  }
158
341
 
159
342
  // RuleOptionsVariantsResolver is an optional extension for resolvers that can
160
- // declare more than one option payload for a rule. Engine construction uses
161
- // it to validate every files/extends variant before any file is visited.
343
+ // expose more than one option payload a rule may receive. Engine construction
344
+ // checks each distinct payload through the rule's supported option-validation
345
+ // capability before any file is visited. Scoped resolvers expose declarations;
346
+ // command adapters may substitute reachable defaults for absent payloads.
162
347
  // Custom resolvers that omit this interface remain compatible through the
163
348
  // single RuleResolver.RuleOptions fallback.
349
+ //
350
+ // @evidence contracts/common.md#principled-implementation Optional structural interface satisfaction exposes the option variants reachable through each resolver's policy without requiring every existing resolver to implement it.
351
+ // @evidence contracts/common.md#clear-and-simple-design One capability method extends validation independently from the required engine resolver interface.
352
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Go interface assertion uses a supported extension boundary, not foreign method replacement.
353
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains supported eager checks, scoped declarations, command defaults and legacy fallback before tags; the member documents returned ownership.
354
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleOptionsVariantsResolver is a declaration of data shape and performs no filesystem, path or process operation.
355
+ // @evidenceExclude contracts/performance.md#efficient-algorithms RuleOptionsVariantsResolver is a declaration of data shape and chooses no algorithm or processing strategy.
356
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleOptionsVariantsResolver is a declaration of data shape and coordinates no computation that could be shared.
357
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources RuleOptionsVariantsResolver is a declaration of data shape; the code that holds its values owns their lifetime.
164
358
  type RuleOptionsVariantsResolver interface {
359
+ // RuleOptionsVariants returns independently owned payloads name may receive.
360
+ //
361
+ // @evidence contracts/common.md#principled-implementation Enumerating resolver-policy variants permits eager checks of scoped tuples and reachable command defaults before any file execution.
362
+ // @evidence contracts/common.md#clear-and-simple-design The operation returns raw payloads for the existing rule decoder rather than adding another option schema.
363
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Variant discovery follows declarations and does not manufacture payloads to match observed diagnostics.
364
+ // @evidence contracts/common.md#meaningful-documentation Native member prose states population and slice ownership separately from tags.
365
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleOptionsVariantsResolver.RuleOptionsVariants is a method signature without a body; each implementation owns any filesystem or process behavior.
366
+ // @evidenceExclude contracts/performance.md#efficient-algorithms RuleOptionsVariantsResolver.RuleOptionsVariants is a method signature without a body; each implementation chooses its own algorithm.
367
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleOptionsVariantsResolver.RuleOptionsVariants is a method signature without a body; each implementation decides what, if anything, to share.
368
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources RuleOptionsVariantsResolver.RuleOptionsVariants is a method signature without a body; each implementation owns any retained state.
165
369
  RuleOptionsVariants(name string) []json.RawMessage
166
370
  }
167
371
 
@@ -183,6 +387,7 @@ func resolvedRuleOptionsVariants(resolver RuleResolver, name string) []json.RawM
183
387
  type boundProjectRuleResolver struct {
184
388
  RuleResolver
185
389
  settings map[string]ProjectRuleSetting
390
+ patterns *userPatternCache
186
391
  }
187
392
 
188
393
  func bindProjectRuleResolver(resolver RuleResolver) (RuleResolver, error) {
@@ -193,7 +398,11 @@ func bindProjectRuleResolver(resolver RuleResolver) (RuleResolver, error) {
193
398
  if err != nil {
194
399
  return nil, err
195
400
  }
196
- return boundProjectRuleResolver{RuleResolver: resolver, settings: settings}, nil
401
+ return boundProjectRuleResolver{
402
+ RuleResolver: resolver,
403
+ settings: settings,
404
+ patterns: patternCacheForResolver(resolver),
405
+ }, nil
197
406
  }
198
407
 
199
408
  func (r boundProjectRuleResolver) ResolveProjectRules(names []string) (map[string]ProjectRuleSetting, error) {
@@ -237,7 +446,17 @@ func (r boundProjectRuleResolver) residentRuleConfigState() residentRuleConfigSt
237
446
  }
238
447
 
239
448
  // ResolveRules implements RuleResolver. A flat RuleConfig has no glob scoping,
240
- // so every file receives the full map unchanged.
449
+ // so every file receives the full map with canonical built-in names.
450
+ // Call ResolveProjectRules first to reject colliding canonical identities.
451
+ //
452
+ // @evidence contracts/common.md#principled-implementation After project-boundary identity validation, canonicalizing the severity map gives every file the same global policy and marks the absence of options as authoritative.
453
+ // @evidence contracts/common.md#clear-and-simple-design A flat adapter constructs one resolved value and delegates key policy to the shared normalization helper.
454
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts No file name or diagnostic result changes the global map; normalization only implements supported rule aliases.
455
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains flat scope, normalization and prerequisite identity validation before separate tags.
456
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleConfig.ResolveRules performs no filesystem or process operation of its own.
457
+ // @evidence contracts/performance.md#efficient-algorithms Canonicalization scans n severity entries into a new map, requiring O(n) map operations plus name normalization/hashing bytes and O(n) result entries. Empty maps are returned without rebuilding.
458
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This stateless projection reads a caller-owned map for one call; it owns no cross-call identity or invalidation protocol for sharing projections after caller mutations.
459
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources No handle, task or historical state is retained. The caller owns the nonempty canonical map returned by this projection; an empty receiver may be reused.
241
460
  func (c RuleConfig) ResolveRules(string) ResolvedRuleConfig {
242
461
  return ResolvedRuleConfig{
243
462
  Rules: normalizeRuleConfigKeys(c),
@@ -247,12 +466,30 @@ func (c RuleConfig) ResolveRules(string) ResolvedRuleConfig {
247
466
 
248
467
  // ActiveRuleNames implements RuleResolver. Returns rule names whose severity
249
468
  // is not SeverityOff, sorted for deterministic engine dispatch-table construction.
469
+ //
470
+ // @evidence contracts/common.md#principled-implementation Normalization followed by non-off filtering and sorting produces the potential dispatch identities under the no-duplicate-alias premise.
471
+ // @evidence contracts/common.md#clear-and-simple-design Shared key normalization and name sorting keep identity policy outside the dispatch consumer.
472
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Enabled names come from declared severities, without fixture-specific activation.
473
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains off filtering and deterministic order, with a separate acknowledgment paragraph.
474
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleConfig.ActiveRuleNames performs no filesystem or process operation of its own.
475
+ // @evidence contracts/performance.md#efficient-algorithms Normalization and filtering scan n entries, then sort k active names: O(n+k log k) name operations plus normalization, hashing and comparison bytes. The temporary normalized map and returned slice reserve O(n) entries.
476
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This stateless projection reads current caller-owned severities and owns no cross-call identity or invalidation protocol for sharing results after caller mutations.
477
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources No handle, task or historical state is retained; the normalized temporary map is local and the caller owns the returned name slice.
250
478
  func (c RuleConfig) ActiveRuleNames() []string {
251
479
  return sortedRuleNames(normalizeRuleConfigKeys(c), func(sev Severity) bool { return sev != SeverityOff })
252
480
  }
253
481
 
254
482
  // EnabledRuleConfig implements RuleResolver. Returns a copy containing only the
255
483
  // non-off entries; used to populate engine state and diagnostic reporting.
484
+ //
485
+ // @evidence contracts/common.md#principled-implementation A fresh canonical-key map retains each non-off global severity; direct maps must avoid colliding aliases.
486
+ // @evidence contracts/common.md#clear-and-simple-design One map projection supplies metadata without mutating the caller's severity map.
487
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Filtering follows the explicit disabled state rather than recorded diagnostics or consumer identities.
488
+ // @evidence contracts/common.md#meaningful-documentation Native prose states copy ownership, filtering and the metadata consumer before separated tags.
489
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation EnabledRuleConfig filters rule severities and touches no filesystem path or process.
490
+ // @evidence contracts/performance.md#efficient-algorithms One pass over n severity entries writes k non-off canonical keys, O(n) entry operations plus name normalization/hashing bytes and O(k) returned entries.
491
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This call projects current caller-owned severities and owns no cross-call mutation identity for sharing results after caller changes.
492
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The returned map is new and owned by the caller; no handle or task is acquired.
256
493
  func (c RuleConfig) EnabledRuleConfig() RuleConfig {
257
494
  out := RuleConfig{}
258
495
  for name, sev := range c {
@@ -263,13 +500,34 @@ func (c RuleConfig) EnabledRuleConfig() RuleConfig {
263
500
  return out
264
501
  }
265
502
 
266
- // RuleOptions on a bare RuleConfig is always nil — this form is the
267
- // severity-only path used by Go unit tests and rule constructors that
268
- // predate option support.
503
+ // RuleOptions on a bare RuleConfig is always nil because this representation
504
+ // contains severities only. Use InlineRuleResolver for supplied option payloads.
505
+ //
506
+ // @evidence contracts/common.md#principled-implementation Returning nil expresses the absence of option storage in a severity-only map.
507
+ // @evidence contracts/common.md#clear-and-simple-design The method adapts the existing flat representation without allocating unused option maps.
508
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The empty result follows the representation's production contract rather than a test-only execution path.
509
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains absence and the option-bearing alternative with a blank line before tags.
510
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleConfig.RuleOptions performs no filesystem or process operation of its own.
511
+ // @evidenceExclude contracts/performance.md#efficient-algorithms RuleConfig.RuleOptions has no loop of its own and runs a fixed number of steps.
512
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleConfig.RuleOptions keeps no cache and shares no in-flight computation.
513
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources RuleConfig.RuleOptions acquires no handle or task and retains nothing beyond the receiver's own fields.
269
514
  func (RuleConfig) RuleOptions(string) json.RawMessage { return nil }
270
515
 
271
516
  // ResolveProjectRules treats a flat RuleConfig as one global declaration.
517
+ // It rejects distinct keys for the same canonical rule even when their values agree.
518
+ //
519
+ // @evidence contracts/common.md#principled-implementation Whole-map identity validation rejects alias collisions before canonical lookup; membership remains independent from severity, so explicit off stays declared.
520
+ // @evidence contracts/common.md#clear-and-simple-design Requested project names are projected from one normalized flat map without introducing file scope.
521
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Alias collisions return an error rather than arbitrary iteration-order precedence; missing names remain absent rather than fabricated defaults.
522
+ // @evidence contracts/common.md#meaningful-documentation Native prose states global interpretation; ProjectRuleSetting documents absence and option meaning used by the return value.
523
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation ResolveProjectRules reads rule names and severities and touches no filesystem path or process.
524
+ // @evidence contracts/performance.md#efficient-algorithms Validation sorts n stored names, then normalization and p requested lookups require O(n log n+p) name operations plus normalization, hashing and comparison bytes. Temporary maps/name lists scale with n and the result map with p.
525
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This call validates and projects current caller-owned severities; it owns no cross-call mutation identity. The native loadRules boundary separately binds one project resolution for reuse during engine construction.
526
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The returned map is new and owned by the caller; no handle or task is acquired.
272
527
  func (c RuleConfig) ResolveProjectRules(names []string) (map[string]ProjectRuleSetting, error) {
528
+ if err := validateCanonicalRuleNames(c); err != nil {
529
+ return nil, err
530
+ }
273
531
  normalized := normalizeRuleConfigKeys(c)
274
532
  out := make(map[string]ProjectRuleSetting, len(names))
275
533
  for _, name := range names {
@@ -290,16 +548,61 @@ func normalizeRuleConfigKeys(c RuleConfig) RuleConfig {
290
548
  return out
291
549
  }
292
550
 
293
- // InlineRuleResolver pairs a severity map with an options map. The fields
294
- // are public so tests can construct one without going through
295
- // ParseRulesWithOptions.
551
+ // validateCanonicalRuleNames rejects distinct spellings of the same rule in
552
+ // one map before canonicalization can detach a severity from its option tuple.
553
+ // Sorting only the keys makes the reported conflicting pair deterministic.
554
+ func validateCanonicalRuleNames[V any](entries map[string]V) error {
555
+ names := make([]string, 0, len(entries))
556
+ for name := range entries {
557
+ names = append(names, name)
558
+ }
559
+ sort.Strings(names)
560
+ seen := make(map[string]string, len(names))
561
+ for _, name := range names {
562
+ canonical := normalizeBuiltinRuleName(name)
563
+ if previous, duplicate := seen[canonical]; duplicate {
564
+ return fmt.Errorf(
565
+ "@ttsc/lint: rule keys %q and %q both resolve to %q; declare each rule once",
566
+ previous, name, canonical,
567
+ )
568
+ }
569
+ seen[canonical] = name
570
+ }
571
+ return nil
572
+ }
573
+
574
+ // InlineRuleResolver pairs global severities with raw option payloads.
575
+ // Callers may construct it directly for an already-resolved flat configuration;
576
+ // ResolveProjectRules validates both maps before engine use or direct metadata
577
+ // projection; alias duplicates are rejected even when their payloads agree.
578
+ //
579
+ // @evidence contracts/common.md#principled-implementation Parallel maps represent global identities with distinct severity and payload types; project-boundary validation rejects duplicate canonical identities in either map before engine projection.
580
+ // @evidence contracts/common.md#clear-and-simple-design The flat resolver adds options to RuleConfig without carrying unused file-pattern or extends state.
581
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Public construction supports engine integrations and is not a special path for tests.
582
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains direct construction, required validation and ownership with spaced member comments and no property tags.
583
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation InlineRuleResolver is a declaration of data shape and performs no filesystem, path or process operation.
584
+ // @evidenceExclude contracts/performance.md#efficient-algorithms InlineRuleResolver is a declaration of data shape and chooses no algorithm or processing strategy.
585
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work InlineRuleResolver is a declaration of data shape and coordinates no computation that could be shared.
586
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources InlineRuleResolver is a declaration of data shape; the code that holds its values owns their lifetime.
296
587
  type InlineRuleResolver struct {
297
- Rules RuleConfig
588
+ // Rules supplies global severities and remains owned by the caller.
589
+ Rules RuleConfig
590
+
591
+ // Options supplies global raw JSON payloads; callers must not mutate them during use.
298
592
  Options RuleOptionsMap
299
593
  }
300
594
 
301
595
  // ResolveRules implements RuleResolver. Inline rules have no glob scoping;
302
596
  // the full map applies to every file.
597
+ //
598
+ // @evidence contracts/common.md#principled-implementation Shared canonicalization projects both maps into an authoritative global resolution, copying raw option bytes and requiring nonconflicting aliases.
599
+ // @evidence contracts/common.md#clear-and-simple-design The adapter delegates map policy to existing helpers and avoids recreating file-scoping logic.
600
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Every file uses supplied global policy, with no source-name special cases or diagnostic-driven defaults.
601
+ // @evidence contracts/common.md#meaningful-documentation Native prose states global scope; the owning type documents input ownership and alias assumptions before its tags.
602
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation InlineRuleResolver.ResolveRules performs no filesystem or process operation of its own.
603
+ // @evidence contracts/performance.md#efficient-algorithms Both maps are normalized in one pass each over n severity and m option entries, plus name normalization/hashing and b copied payload bytes. Result storage scales with n+m+b; empty option storage stays nil and an empty severity map may be reused.
604
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This call projects current caller-owned maps and owns no cross-call identity or invalidation protocol for sharing results after caller mutations.
605
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources No handle, task or historical state is retained. Nonempty normalized maps and copied option bytes are transferred to the caller; an empty severity receiver may remain shared.
303
606
  func (r InlineRuleResolver) ResolveRules(string) ResolvedRuleConfig {
304
607
  return ResolvedRuleConfig{
305
608
  Rules: normalizeRuleConfigKeys(r.Rules),
@@ -320,11 +623,29 @@ func normalizeRuleOptionsKeys(options RuleOptionsMap) RuleOptionsMap {
320
623
  }
321
624
 
322
625
  // ActiveRuleNames implements RuleResolver by delegating to the inner RuleConfig.
626
+ //
627
+ // @evidence contracts/common.md#principled-implementation Delegation preserves the severity map's non-off, canonical and sorted dispatch-name policy.
628
+ // @evidence contracts/common.md#clear-and-simple-design The wrapper reuses the severity owner instead of duplicating activity selection beside the options map.
629
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Option presence does not fabricate activity for a rule disabled by supplied severity.
630
+ // @evidence contracts/common.md#meaningful-documentation Native prose identifies the policy owner; RuleConfig documents filtering and sorting, and tags remain separate.
631
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation InlineRuleResolver.ActiveRuleNames performs no filesystem or process operation of its own.
632
+ // @evidence contracts/performance.md#efficient-algorithms Delegation normalizes and filters n severity entries, then sorts k active names, O(n+k log k) name operations plus name bytes. The normalized temporary map and returned slice reserve O(n) entries; options are not traversed.
633
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work Activity is a projection of the caller's current severity map, not a shared producer with a cross-call mutation identity.
634
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Delegation returns a caller-owned name slice and retains no historical state, handle or task in this wrapper.
323
635
  func (r InlineRuleResolver) ActiveRuleNames() []string {
324
636
  return r.Rules.ActiveRuleNames()
325
637
  }
326
638
 
327
639
  // EnabledRuleConfig implements RuleResolver by delegating to the inner RuleConfig.
640
+ //
641
+ // @evidence contracts/common.md#principled-implementation Delegating to Rules preserves the non-off global severity projection regardless of optional payload presence.
642
+ // @evidence contracts/common.md#clear-and-simple-design Severity aggregation has one implementation and the wrapper adds no redundant map state.
643
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Options cannot activate a disabled rule through a compatibility exception.
644
+ // @evidence contracts/common.md#meaningful-documentation The native delegation comment makes the behavior owner apparent, with a blank comment line before tags.
645
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation InlineRuleResolver.EnabledRuleConfig performs no filesystem or process operation of its own.
646
+ // @evidence contracts/performance.md#efficient-algorithms Delegation scans n severity entries and writes k non-off canonical keys, O(n) entry operations plus normalization/hashing bytes and O(k) returned entries. The options map is not inspected.
647
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This call projects current caller-owned severities; the wrapper does not coordinate a shared result or cross-call mutation identity.
648
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Delegation returns a new caller-owned severity map and retains no historical state, handle or task in this wrapper.
328
649
  func (r InlineRuleResolver) EnabledRuleConfig() RuleConfig {
329
650
  return r.Rules.EnabledRuleConfig()
330
651
  }
@@ -332,6 +653,16 @@ func (r InlineRuleResolver) EnabledRuleConfig() RuleConfig {
332
653
  // RuleOptions implements RuleResolver. Returns the raw JSON options blob for
333
654
  // `name`, or nil when the rule was configured without options or the name is
334
655
  // unknown.
656
+ // The returned slice is borrowed from Options and must remain read-only.
657
+ //
658
+ // @evidence contracts/common.md#principled-implementation Exact, canonical and unique normalized-alias lookup return only the supplied global payload and preserve nil for missing option storage after identity validation.
659
+ // @evidence contracts/common.md#clear-and-simple-design One lookup method adapts the options map without merging or decoding rule-specific payloads.
660
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Alias normalization is supported naming policy and does not select options from expected diagnostics.
661
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains nil results and borrowed byte ownership before separated tags.
662
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleOptions looks up option bytes by rule name and touches no filesystem path or process.
663
+ // @evidence contracts/performance.md#efficient-algorithms Exact and canonical keys use an expected constant number of map probes, with hashing and normalization proportional to query-name bytes. Only a miss scans n stored names, paying their normalization/comparison byte costs; option bytes are borrowed without decoding or copying.
664
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleOptions keeps no cache and shares no computation.
665
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources RuleOptions returns the stored message without copying; the resolver owns it.
335
666
  func (r InlineRuleResolver) RuleOptions(name string) json.RawMessage {
336
667
  if r.Options == nil {
337
668
  return nil
@@ -343,13 +674,34 @@ func (r InlineRuleResolver) RuleOptions(name string) json.RawMessage {
343
674
  if raw := r.Options[canonical]; len(raw) > 0 {
344
675
  return raw
345
676
  }
677
+ for storedName, raw := range r.Options {
678
+ if normalizeBuiltinRuleName(storedName) == canonical {
679
+ return raw
680
+ }
681
+ }
346
682
  return nil
347
683
  }
348
684
 
349
685
  // ResolveProjectRules treats inline rules as global and preserves their
350
686
  // explicit options tuple.
687
+ // Both maps are validated for duplicate canonical identities before any setting folds.
688
+ //
689
+ // @evidence contracts/common.md#principled-implementation Both maps reject canonical identity collisions before severity declaration bits and defensive payload copies are folded into requested global settings.
690
+ // @evidence contracts/common.md#clear-and-simple-design Severity resolution is reused and only the option-bearing part is added by this wrapper.
691
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The global adapter introduces no file-dependent project state or special consumer branch.
692
+ // @evidence contracts/common.md#meaningful-documentation Native prose states global interpretation and tuple preservation, with acknowledgments in a separate paragraph.
693
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation ResolveProjectRules reads rule names, severities and option bytes and touches no filesystem path or process.
694
+ // @evidence contracts/performance.md#efficient-algorithms Validation sorts n severity names and m option names before p requested lookups. Exact/canonical option keys need one lookup and fallback can scan m names per request, giving O(n log n+m log m+p(1+m)) name operations in the worst case plus name bytes and copied payload bytes. Temporary/result containers scale with n+m+p and returned payload size.
695
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This call validates and projects current caller-owned maps; it owns no cross-call mutation identity. The native loadRules boundary separately binds one project resolution for reuse during engine construction.
696
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Each option message is copied into the returned settings so they do not alias resolver memory; no handle or task is acquired.
351
697
  func (r InlineRuleResolver) ResolveProjectRules(names []string) (map[string]ProjectRuleSetting, error) {
352
- settings, _ := r.Rules.ResolveProjectRules(names)
698
+ if err := validateCanonicalRuleNames(r.Options); err != nil {
699
+ return nil, err
700
+ }
701
+ settings, err := r.Rules.ResolveProjectRules(names)
702
+ if err != nil {
703
+ return nil, err
704
+ }
353
705
  for _, name := range names {
354
706
  setting := settings[name]
355
707
  setting.Options = append(json.RawMessage(nil), r.RuleOptions(name)...)
@@ -367,10 +719,24 @@ func (r InlineRuleResolver) ResolveProjectRules(names []string) (map[string]Proj
367
719
  // https://eslint.org/docs/latest/use/configure/rules#using-configuration-files
368
720
  //
369
721
  // A config file is a single `ITtscLintConfig` object. Its `extends` field
370
- // names another config file to fold in first; the extends chain produces one
371
- // ConfigEntry per file, the extends-target entries declared before the
372
- // extending file's own entry so local rules win on collision.
722
+ // names another config file to fold in first. A file may contribute a
723
+ // global-ignore entry and a scoped rule entry, or no entry when it has neither.
724
+ // Extends-target entries precede the extending file's entries so local rules
725
+ // win on collision; format settings join the same scoped rule entry.
726
+ // Duplicate aliases within one rules object are rejected before entries are stored.
727
+ // Parsed stores share an option-regex cache through a pointer, so read-only
728
+ // value copies preserve reuse without copying synchronization state.
729
+ //
730
+ // @evidence contracts/common.md#principled-implementation Ordered entries preserve extends precedence and matching-file ownership of severities and options; global-ignore entries distinguish whole-file exclusion from local selection.
731
+ // @evidence contracts/common.md#clear-and-simple-design Parsed entries are the policy source of truth, while paths and fingerprints separately carry watch and resident-cache provenance.
732
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Compatibility option lookup derives from entries rather than a second flattened state; the parser rejects duplicate canonical identities instead of choosing map-order precedence.
733
+ // @evidence contracts/common.md#meaningful-documentation Native paragraphs explain matching, inheritance, ignores and alias limits; public methods document copy ownership and metadata-only semantics.
734
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation ConfigStore is a declaration of data shape and performs no filesystem, path or process operation.
735
+ // @evidenceExclude contracts/performance.md#efficient-algorithms ConfigStore is a declaration of data shape and chooses no algorithm or processing strategy.
736
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work ConfigStore is a declaration of data shape and coordinates no computation that could be shared.
737
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources ConfigStore is a declaration of data shape; the code that holds its values owns their lifetime.
373
738
  type ConfigStore struct {
739
+ patterns *userPatternCache
374
740
  cacheDependencies []configDependencyFingerprint
375
741
  cacheFiles []string
376
742
  directories []string
@@ -379,9 +745,20 @@ type ConfigStore struct {
379
745
  resolutionRoot string
380
746
  }
381
747
 
382
- // ConfigPaths returns the config and extends files that produced this store.
748
+ // ConfigPaths returns the config, extends and evaluated public dependency files
749
+ // that produced this store. Private resident-cache fingerprints remain separate.
383
750
  // The paths are retained as exact dependencies even when no rule declares
384
751
  // additional project inputs.
752
+ // The returned slice is a copy, so callers can change its membership.
753
+ //
754
+ // @evidence contracts/common.md#principled-implementation Copying the stored path slice preserves config provenance while preventing callers from changing store membership.
755
+ // @evidence contracts/common.md#clear-and-simple-design Watch-input exposure is separate from entry resolution and private executable-cache fingerprints.
756
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Paths come from actual config evaluation and inheritance, not a fixture-specific watch list.
757
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains retained provenance and defensive slice ownership with separated tags.
758
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation ConfigPaths returns config path strings the store already holds; it opens no file and compares no path.
759
+ // @evidence contracts/performance.md#efficient-algorithms One slice copy, O(paths).
760
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work ConfigPaths keeps no cache and shares no computation.
761
+ // @evidence contracts/performance.md#bound-retention-and-release-resources The store retains its path list for its own lifetime and ConfigPaths returns a copy, so a caller cannot mutate or extend the retained slice.
385
762
  func (s *ConfigStore) ConfigPaths() []string {
386
763
  if s == nil {
387
764
  return nil
@@ -392,6 +769,16 @@ func (s *ConfigStore) ConfigPaths() []string {
392
769
  // ConfigDirectories returns resolution-topology directories whose immediate
393
770
  // entries can change which executable-config module Node selects. Consumers
394
771
  // watch these as cold configuration inputs rather than ordinary rule data.
772
+ // The returned slice is a copy; a nil store has no directory inputs.
773
+ //
774
+ // @evidence contracts/common.md#principled-implementation Exposing copied topology directories permits consumers to observe resolution changes without mutating store state.
775
+ // @evidence contracts/common.md#clear-and-simple-design Module-selection inputs have a distinct accessor because they are not source files or rule data.
776
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Directories are tracked resolver inputs rather than assumed fixed Node search locations.
777
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains topology relevance, nil behavior and copy ownership before tags.
778
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation ConfigDirectories returns directory strings the store already holds; it opens no file and compares no path.
779
+ // @evidence contracts/performance.md#efficient-algorithms One slice copy, O(directories).
780
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work ConfigDirectories keeps no cache and shares no computation.
781
+ // @evidence contracts/performance.md#bound-retention-and-release-resources The store retains its directory list for its own lifetime and ConfigDirectories returns a copy, so a caller cannot mutate or extend the retained slice.
395
782
  func (s *ConfigStore) ConfigDirectories() []string {
396
783
  if s == nil {
397
784
  return nil
@@ -403,7 +790,8 @@ func (s *ConfigStore) ConfigDirectories() []string {
403
790
  // that produced this store. Executable configs retain their complete dependency
404
791
  // fingerprints, including package implementation files that must invalidate a
405
792
  // resident answer without becoming public project-watch inputs. JSON configs
406
- // retain only their own files because they have no executable module graph.
793
+ // retain the actual raw-byte fingerprint captured by their decoding read; no
794
+ // later hash substitutes for the consumed input.
407
795
  func (s *ConfigStore) residentRuleConfigState() residentRuleConfigState {
408
796
  if s == nil {
409
797
  return residentRuleConfigState{}
@@ -424,6 +812,16 @@ func (s *ConfigStore) residentRuleConfigState() residentRuleConfigState {
424
812
  // carries the matching file's options. Callers that only understand the older
425
813
  // interface observe the final declared tuple, preserving the former flat
426
814
  // resolver behavior without storing a second source of truth.
815
+ // The returned bytes are copied and remain independent of the stored payload.
816
+ //
817
+ // @evidence contracts/common.md#principled-implementation Declaration-order traversal selects the final explicit tuple for metadata compatibility without claiming that it applies to a particular file.
818
+ // @evidence contracts/common.md#clear-and-simple-design The representative payload is derived from entries instead of maintained in a duplicate flattened option map.
819
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The fallback exists for supported file-agnostic consumers and cannot override ResolveRules execution scope.
820
+ // @evidence contracts/common.md#meaningful-documentation Native prose distinguishes metadata compatibility from file execution and documents copied ownership with separated tags.
821
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleOptions selects option bytes by rule name and touches no filesystem path or process.
822
+ // @evidence contracts/performance.md#efficient-algorithms Normalize the input name, then scan entries for its last nonempty payload and copy the winner; work includes name normalization and hashing plus O(entries + winning payload bytes), with output storage proportional to the copied payload.
823
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work RuleOptions keeps no cache; every call reads the store's entries.
824
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The winning message is copied so the caller cannot mutate store memory; no handle or task is acquired.
427
825
  func (s *ConfigStore) RuleOptions(name string) json.RawMessage {
428
826
  if s == nil {
429
827
  return nil
@@ -455,10 +853,20 @@ func (s *ConfigStore) flattenOptions() RuleOptionsMap {
455
853
  return options
456
854
  }
457
855
 
458
- // RuleOptionsVariants exposes every entry-local payload (including a nil
459
- // severity-only declaration) so engine construction validates the full
460
- // files/extends surface rather than whichever tuple happened to be parsed
461
- // last.
856
+ // RuleOptionsVariants exposes each non-ignore entry's declared payload,
857
+ // including nil for a severity-only declaration. Engine construction can check
858
+ // all files/extends variants through the rule's supported validation capability
859
+ // rather than selecting only the last parsed tuple.
860
+ // Returned payloads are independent byte copies; nil marks a severity-only declaration.
861
+ //
862
+ // @evidence contracts/common.md#principled-implementation Every non-ignore entry declaring the canonical name contributes its own payload, including nil, so eager validation does not skip scoped variants.
863
+ // @evidence contracts/common.md#clear-and-simple-design The optional capability projects existing entries and reuses the rule decoder rather than introducing another configuration model.
864
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Variant enumeration uses declared settings, not which examples happened to execute a rule.
865
+ // @evidence contracts/common.md#meaningful-documentation Native prose states full declaration population, severity-only nil and independent byte ownership before tags.
866
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation RuleOptionsVariants selects option bytes by rule name and touches no filesystem path or process.
867
+ // @evidence contracts/performance.md#efficient-algorithms One pass over e entries probes the canonical name and copies b bytes across v declared variants, O(e) map probes plus name hashing and b copy work, with O(v+b) result storage. The declaration list is the source of truth, so eager discovery must inspect entries even when their file selectors differ.
868
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This projection owns no shared producer or invalidation identity. Engine construction separately deduplicates identical payload bytes before invoking supported validation.
869
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The returned slice and nonempty payload copies belong to the caller; nil payloads carry no bytes. This call retains no historical result, handle or task in the store.
462
870
  func (s *ConfigStore) RuleOptionsVariants(name string) []json.RawMessage {
463
871
  if s == nil {
464
872
  return nil
@@ -477,25 +885,57 @@ func (s *ConfigStore) RuleOptionsVariants(name string) []json.RawMessage {
477
885
  return variants
478
886
  }
479
887
 
480
- // ConfigEntry is the parsed form of one config file in the extends chain.
888
+ // ConfigEntry is one parsed selection or global-ignore entry from a config file.
481
889
  // BaseDir anchors glob resolution; Files and Ignores are the pattern lists.
482
- // IgnoreOnly marks entries that carry only `ignores` (no `files`, no `rules`)
483
- // — these are evaluated first in ResolveRules and short-circuit the walk when
484
- // matched.
890
+ // IgnoreOnly represents a global-ignore entry derived from an ignores list
891
+ // without a nonempty files restriction. These entries are evaluated first in
892
+ // ResolveRules and short-circuit the walk when matched.
893
+ //
894
+ // @evidence contracts/common.md#principled-implementation One entry binds relative patterns and paired rule maps to the config file that owns them, while selector presence remains distinct from an empty pattern list.
895
+ // @evidence contracts/common.md#clear-and-simple-design Entry-local scope and global-ignore state are explicit fields, avoiding parallel flattened policy.
896
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Presence bits model actual config syntax instead of guessing scope from a nonempty collection.
897
+ // @evidence contracts/common.md#meaningful-documentation Native prose and spaced field comments explain pattern anchoring, presence and ignore meaning without property tags.
898
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation ConfigEntry is a declaration of data shape and performs no filesystem, path or process operation.
899
+ // @evidenceExclude contracts/performance.md#efficient-algorithms ConfigEntry is a declaration of data shape and chooses no algorithm or processing strategy.
900
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work ConfigEntry is a declaration of data shape and coordinates no computation that could be shared.
901
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources ConfigEntry is a declaration of data shape; the code that holds its values owns their lifetime.
485
902
  type ConfigEntry struct {
486
- BaseDir string
487
- Files []string
903
+ // BaseDir anchors this config file's relative selectors.
904
+ BaseDir string
905
+
906
+ // Files lists positive patterns; an empty list imposes no file restriction.
907
+ Files []string
908
+
909
+ // HasFilesSelector preserves explicit selector syntax for project-rule validation.
488
910
  HasFilesSelector bool
489
- Ignores []string
490
- Rules RuleConfig
491
- Options RuleOptionsMap
492
- IgnoreOnly bool
911
+
912
+ // Ignores subtracts files from this entry, or globally when IgnoreOnly is true.
913
+ Ignores []string
914
+
915
+ // Rules contains this entry's declarations, including explicit off states.
916
+ Rules RuleConfig
917
+
918
+ // Options contains this entry's option tuples, folded with its matching severities.
919
+ Options RuleOptionsMap
920
+
921
+ // IgnoreOnly makes a matching ignore skip the file before ordinary entries fold.
922
+ IgnoreOnly bool
493
923
  }
494
924
 
495
925
  // ResolveRules implements RuleResolver. Ignore-only entries are checked first;
496
926
  // if one matches, the file is marked Ignored and linting is skipped entirely.
497
927
  // Otherwise the entries are walked in declaration order and the last matching
498
928
  // entry wins (later entries shadow earlier ones for the same rule name).
929
+ // A later severity-only declaration retains the most recent options from a matching entry.
930
+ //
931
+ // @evidence contracts/common.md#principled-implementation Global ignores precede ordered entry matching; paired maps are folded only from matching entries, retaining inherited tuples when a later matching declaration has no options.
932
+ // @evidence contracts/common.md#clear-and-simple-design A global-ignore phase precedes the ordered file-scope fold; ConfigEntry owns pattern predicates and the result distinguishes ignored from out-of-scope.
933
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts No options are borrowed from nonmatching entries and no consumer name bypasses selection.
934
+ // @evidence contracts/common.md#meaningful-documentation Native prose documents global-ignore ordering, precedence and severity-only inheritance before a separate tag paragraph.
935
+ // @evidence contracts/portability.md#os-neutral-implementation Selector helpers use native filepath identities and symlink/junction ancestor resolution, then slash-normalized glob spelling. Stored-case fallback requires the actual path to exist and a unique on-disk case-fold match; it does not infer case policy from the OS name. Relative paths escaping the resolved base are rejected; resolution failures preserve lexical spelling, and a failed relative-path calculation disables stored-case fallback.
936
+ // @evidence contracts/performance.md#efficient-algorithms Up to two passes inspect e entries and merge q matching rule declarations, with name hashing/normalization and b copied payload bytes. Selector work includes pattern matching, native ancestor resolution and eligible stored-case directory scans; output holds u distinct rules and their final payload bytes. Global ignores return early.
937
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This call projects current entries and filesystem identities; it has no cross-call invalidation proof for memoizing matching after native topology changes.
938
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The returned maps are new and owned by the caller and option bytes are copied; no handle or task is acquired.
499
939
  func (s *ConfigStore) ResolveRules(fileName string) ResolvedRuleConfig {
500
940
  if s == nil {
501
941
  return ResolvedRuleConfig{Rules: RuleConfig{}, OptionsResolved: true}
@@ -538,6 +978,15 @@ func (s *ConfigStore) ResolveRules(fileName string) ResolvedRuleConfig {
538
978
  // names that are not SeverityOff across every non-ignore-only config entry,
539
979
  // regardless of which files they apply to. The engine uses this to build the
540
980
  // per-rule dispatch table before file iteration begins.
981
+ //
982
+ // @evidence contracts/common.md#principled-implementation Unioning non-off declarations from every ordinary entry retains potentially active rules regardless of current file scope, then sorts their canonical identities.
983
+ // @evidence contracts/common.md#clear-and-simple-design Dispatch metadata is derived from entries without executing file matching or caching a duplicate activity list.
984
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Activity follows supported config declarations instead of sampled source diagnostics.
985
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains ignore-only exclusion, potential activity and the pre-file dispatch consumer before tags.
986
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation ActiveRuleNames collects rule names and touches no filesystem path or process.
987
+ // @evidence contracts/performance.md#efficient-algorithms Scanning e entries and q ordinary rule declarations builds u distinct active names, then sorts them: O(e+q+u log u) entry/name operations plus normalization, hashing and comparison bytes. The temporary union and returned slice hold O(u) entries; no file selectors or option payloads are evaluated.
988
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This metadata projection owns no shared producer or cross-call invalidation identity; engine construction separately uses its result to build dispatch once.
989
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The temporary union is local and the caller owns the returned name slice. No historical metadata, handle or task is retained by this call.
541
990
  func (s *ConfigStore) ActiveRuleNames() []string {
542
991
  if s == nil {
543
992
  return nil
@@ -559,6 +1008,15 @@ func (s *ConfigStore) ActiveRuleNames() []string {
559
1008
  // EnabledRuleConfig implements RuleResolver. Returns the project-wide severity
560
1009
  // map for non-off rules. Where multiple entries configure the same rule,
561
1010
  // SeverityError is sticky — it cannot be downgraded by a later warning entry.
1011
+ //
1012
+ // @evidence contracts/common.md#principled-implementation Aggregating non-off entries with sticky error severity conservatively represents potential project reporting without replacing file-specific resolution.
1013
+ // @evidence contracts/common.md#clear-and-simple-design The metadata projection is computed from the same entries rather than stored as independent execution policy.
1014
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Error precedence is the documented aggregate policy, not a special case for a diagnostic fixture.
1015
+ // @evidence contracts/common.md#meaningful-documentation Native prose states global aggregation and sticky error semantics with a separate acknowledgment paragraph.
1016
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation EnabledRuleConfig merges rule severities and touches no filesystem path or process.
1017
+ // @evidence contracts/performance.md#efficient-algorithms Scanning e entries and q ordinary rule declarations writes u distinct non-off canonical names, O(e+q) entry/name operations plus normalization/hashing bytes and O(u) returned entries. No file selectors or payload bytes are evaluated.
1018
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This metadata projection owns no shared producer or cross-call invalidation identity; engine construction separately retains the aggregate reporting state it needs.
1019
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The caller owns the new severity map, including the empty nil-store result. This call retains no historical metadata, handle or task.
562
1020
  func (s *ConfigStore) EnabledRuleConfig() RuleConfig {
563
1021
  out := RuleConfig{}
564
1022
  if s == nil {
@@ -586,6 +1044,15 @@ func (s *ConfigStore) EnabledRuleConfig() RuleConfig {
586
1044
  // invalid configuration, including off declarations and option tuples. A
587
1045
  // built-in companion sharing a file-rule name ignores that scoped declaration
588
1046
  // so the file rule can retain its existing per-file configuration.
1047
+ //
1048
+ // @evidence contracts/common.md#principled-implementation Base-first global folding preserves declaration presence and inherited options; file-only project declarations are rejected unless a registered file companion owns that scoped mention.
1049
+ // @evidence contracts/common.md#clear-and-simple-design Requested identities form a lookup set and project validation stays with the store that knows entry scope.
1050
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The companion exception checks actual LookupRule registration rather than a hand-maintained consumer whitelist.
1051
+ // @evidence contracts/common.md#meaningful-documentation Native prose states project-scope rejection and the registered-companion distinction before separated tags.
1052
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation ResolveProjectRules resolves rule names and option bytes and touches no filesystem path or process.
1053
+ // @evidence contracts/performance.md#efficient-algorithms A wanted-name index is built for p requests, e entries are visited and q configured rules in participating entries are scanned once. This costs O(p+e+q) entry/name operations plus normalization/hashing bytes and the total option bytes copied by matching inherited updates; lookup/result maps reserve O(p) entries and results retain the final resolved payloads.
1054
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This method owns one fold of the current store. The native loadRules boundary binds its project resolution into boundProjectRuleResolver so engine construction can reuse the settings instead of folding the store again.
1055
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The returned map is new and owned by the caller and option bytes are copied; no handle or task is acquired.
589
1056
  func (s *ConfigStore) ResolveProjectRules(names []string) (map[string]ProjectRuleSetting, error) {
590
1057
  out := make(map[string]ProjectRuleSetting, len(names))
591
1058
  wanted := make(map[string]string, len(names))
@@ -631,9 +1098,18 @@ func (s *ConfigStore) ResolveProjectRules(names []string) (map[string]ProjectRul
631
1098
  return out, nil
632
1099
  }
633
1100
 
634
- // Flatten returns the unconstrained union of all non-ignore-only entries,
1101
+ // Flatten returns a new severity map for all non-ignore-only entries,
635
1102
  // including SeverityOff rules. Used by LoadRuleConfig (callers that expect a
636
1103
  // plain RuleConfig). Later entries shadow earlier ones for the same rule name.
1104
+ //
1105
+ // @evidence contracts/common.md#principled-implementation Declaration-order folding retains explicit off states and intentionally discards file scope to represent the documented unconstrained union.
1106
+ // @evidence contracts/common.md#clear-and-simple-design A derived map adapts legacy severity consumers without becoming another source of execution truth.
1107
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Flattening is an explicit metadata API and is not substituted for scoped engine execution.
1108
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains the loss of scope, inclusion of off and precedence before a separate tag paragraph.
1109
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation Flatten merges rule severities and touches no filesystem path or process.
1110
+ // @evidence contracts/performance.md#efficient-algorithms One fold visits e entries and q rules in participating entries, with O(e+q) entry/map operations plus rule-name trimming, normalization and hashing bytes. A full fold is needed for the unconstrained union and later-entry precedence. The returned map holds u distinct canonical names and severities in O(u) map entries; normalized names can share their source string backing storage.
1111
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work Flatten owns one severity projection of the store, not a cross-request computation coordinator. Its fresh writable result gives each caller independent map membership; callers establish equivalence and ownership before reusing a projection.
1112
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The returned map is new and owned by the caller; no handle or task is acquired.
637
1113
  func (s *ConfigStore) Flatten() RuleConfig {
638
1114
  out := RuleConfig{}
639
1115
  if s == nil {
@@ -664,15 +1140,24 @@ func (e ConfigEntry) matchesIgnores(fileName string) bool {
664
1140
  return len(e.Ignores) > 0 && matchAnyPattern(e.BaseDir, e.Ignores, fileName)
665
1141
  }
666
1142
 
667
- // ParseRules normalizes a rule severity map.
1143
+ // ParseRules projects a decoded rule object to a severity map, preserving
1144
+ // supplied key spelling and rejecting duplicate canonical aliases.
1145
+ //
1146
+ // Nil means no rules. Entries accept "off", "warn"/"warning", "error" or
1147
+ // JSON-decoded float64 values 0, 1, 2, either bare or in a severity/options tuple.
1148
+ // Unsupported severities, empty tuples and unencodable options return an error.
668
1149
  //
669
- // Severity values:
670
- // - `"off"` → SeverityOff
671
- // - `"warning"` → SeverityWarn
672
- // - `"error"` → SeverityError
1150
+ // Tuples are checked and option payloads encoded by the shared parser, then
1151
+ // discarded from this severity-only result; use ParseRulesWithOptions to retain them.
673
1152
  //
674
- // Anything else returns an error (no silent fallback — typos in a rule
675
- // severity should be loud).
1153
+ // @evidence contracts/common.md#principled-implementation Delegating to the tuple-aware parser preserves severity validation while intentionally discarding option storage for this severity-only API.
1154
+ // @evidence contracts/common.md#clear-and-simple-design One parser owns entry decoding; this wrapper only projects the severity result.
1155
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Invalid severity is returned as an error rather than silently disabled to satisfy a consumer.
1156
+ // @evidence contracts/common.md#meaningful-documentation Native prose describes decoded input, nil, complete severity vocabulary, tuple errors, key spelling and the option-bearing alternative before separate tags.
1157
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation ParseRules performs no filesystem or process operation of its own.
1158
+ // @evidence contracts/performance.md#efficient-algorithms The shared parser sorts n stored names, scans entries and encodes supplied option bytes, O(n log n) name comparisons plus name and payload bytes. Delegation preserves the same strict tuple/error semantics; only the severity map is transferred, while temporary option maps and bytes become reclaimable after return.
1159
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This decoded-value projection owns no shared producer or cross-call identity for mutable caller inputs.
1160
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The caller owns the new severity map; temporary discarded option storage is not retained by this wrapper. No handle or task is acquired.
676
1161
  func ParseRules(raw any) (RuleConfig, error) {
677
1162
  cfg, _, err := ParseRulesWithOptions(raw)
678
1163
  return cfg, err
@@ -682,6 +1167,19 @@ func ParseRules(raw any) (RuleConfig, error) {
682
1167
  // `[severity, ...options]` tuple per rule and returns the severity map
683
1168
  // alongside an options map keyed by rule name. The options map only
684
1169
  // contains entries for rules whose configuration carries option slots.
1170
+ // Keys retain their supplied spelling. Distinct keys for one canonical rule are
1171
+ // rejected, including duplicate aliases with equal severities or payloads.
1172
+ // JSON-loaded option slots retain nested object-entry order; an ordinary Go map
1173
+ // has no authored member order for this boundary to recover.
1174
+ //
1175
+ // @evidence contracts/common.md#principled-implementation Canonical identity validation rejects ambiguous maps before entry decoding separates severity and JSON option slots, preserving each tuple and one-slot shape.
1176
+ // @evidence contracts/common.md#clear-and-simple-design The boundary validates a raw object once and returns paired maps for existing severity and option consumers.
1177
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Ambiguous aliases are errors regardless of equal values, rather than iteration-order precedence; invalid entries do not receive fabricated defaults.
1178
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains tuple shape, option-map population and preserved key spelling with a blank line before tags.
1179
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation ParseRulesWithOptions decodes an already-loaded rules value and touches no filesystem path or process.
1180
+ // @evidence contracts/performance.md#efficient-algorithms Canonical-name validation sorts n rule names before a linear entry pass, requiring O(n log n) name comparisons plus hashing/name-byte work. Option encoding examines the supplied payload bytes and allocates the returned JSON; result maps scale with rule and option counts.
1181
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work ParseRulesWithOptions keeps no cache; every call decodes its argument.
1182
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The returned maps are new and owned by the caller; no handle or task is acquired.
685
1183
  func ParseRulesWithOptions(raw any) (RuleConfig, RuleOptionsMap, error) {
686
1184
  if raw == nil {
687
1185
  return RuleConfig{}, RuleOptionsMap{}, nil
@@ -690,6 +1188,9 @@ func ParseRulesWithOptions(raw any) (RuleConfig, RuleOptionsMap, error) {
690
1188
  if !ok {
691
1189
  return nil, nil, fmt.Errorf("@ttsc/lint: \"rules\" must be an object, got %T", raw)
692
1190
  }
1191
+ if err := validateCanonicalRuleNames(dict); err != nil {
1192
+ return nil, nil, err
1193
+ }
693
1194
  cfg := make(RuleConfig, len(dict))
694
1195
  opts := make(RuleOptionsMap)
695
1196
  for name, value := range dict {
@@ -771,7 +1272,10 @@ func collectConfigStoreWithin(
771
1272
  rootPath string,
772
1273
  resolutionRoot string,
773
1274
  ) (*ConfigStore, error) {
774
- store := &ConfigStore{resolutionRoot: filepath.Clean(resolutionRoot)}
1275
+ store := &ConfigStore{
1276
+ patterns: &userPatternCache{},
1277
+ resolutionRoot: filepath.Clean(resolutionRoot),
1278
+ }
775
1279
  var chain []string
776
1280
  if rootPath != "" {
777
1281
  rootPath = filepath.Clean(rootPath)
@@ -932,16 +1436,21 @@ func collectConfigObject(store *ConfigStore, raw any, baseDir, path string, chai
932
1436
  if !ok {
933
1437
  return fmt.Errorf("@ttsc/lint: %s.rules must be a rule severity map, got %T", path, rulesValue)
934
1438
  }
1439
+ if err := validateCanonicalRuleNames(typedMap); err != nil {
1440
+ return fmt.Errorf("%s.rules: %w", path, err)
1441
+ }
935
1442
  // `format/*` rules are configured exclusively through the `format`
936
1443
  // block; they are never valid keys in `rules`. Silently drop any that
937
1444
  // appear, the same way an unknown rule name is ignored (see
938
1445
  // parseExternalRuleMapInto): a config must not carry a formatter
939
1446
  // setting in two places, and a stray `format/*` here is simply not the
940
1447
  // formatting surface, so it has no effect rather than erroring.
941
- rulesMap = typedMap
942
- for key := range rulesMap {
943
- if isFormatRuleName(key) {
944
- delete(rulesMap, key)
1448
+ // Evaluated objects can be shared by concurrent cache readers. Filter
1449
+ // into owned storage instead of deleting from the cached source map.
1450
+ rulesMap = make(map[string]any, len(typedMap))
1451
+ for key, value := range typedMap {
1452
+ if !isFormatRuleName(normalizeBuiltinRuleName(key)) {
1453
+ rulesMap[key] = value
945
1454
  }
946
1455
  }
947
1456
  }
@@ -984,6 +1493,9 @@ func collectExternalRuleMapWithOptions(out RuleConfig, opts RuleOptionsMap, raw
984
1493
  if !ok {
985
1494
  return fmt.Errorf("@ttsc/lint: %s must be a rules object, got %T", path, raw)
986
1495
  }
1496
+ if err := validateCanonicalRuleNames(dict); err != nil {
1497
+ return fmt.Errorf("%s: %w", path, err)
1498
+ }
987
1499
  for name, value := range dict {
988
1500
  sev, ruleOpts, err := parseExternalRuleEntry(value)
989
1501
  if err != nil {
@@ -1050,8 +1562,17 @@ func parsePatternList(raw any, path string) ([]string, error) {
1050
1562
  }
1051
1563
 
1052
1564
  // LoadRuleConfig resolves the lint config for one plugin entry and flattens it
1053
- // to a plain RuleConfig (no glob scoping). Used by callers and tests that only
1054
- // need a project-wide severity map.
1565
+ // to a plain RuleConfig (no glob scoping). Metadata consumers can use the
1566
+ // unconstrained severity union; file execution should use LoadConfigResolver.
1567
+ //
1568
+ // @evidence contracts/common.md#principled-implementation The loader delegates config evaluation and projects the resolver's supported severity view, preserving store off declarations through Flatten.
1569
+ // @evidence contracts/common.md#clear-and-simple-design One adapter owns the legacy severity-only return shape while the scoped loader owns discovery and parsing.
1570
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Resolver type handling corresponds to real supported representations and does not bypass per-file execution policy.
1571
+ // @evidence contracts/common.md#meaningful-documentation Native prose identifies metadata use and directs file execution to the scoped resolver, with separated tags.
1572
+ // @evidence contracts/portability.md#os-neutral-implementation LoadRuleConfig carries native cwd/tsconfig/config paths through LoadConfigResolver. That boundary uses filepath-based project anchoring and native discovery/evaluation helpers, while file URLs and executable argument forms belong to their loader owners; this projection introduces no case-folding or shell command text.
1573
+ // @evidence contracts/performance.md#efficient-algorithms LoadRuleConfig includes the delegated discovery, config-byte parsing/evaluation, dependency validation and store construction costs of LoadConfigResolver. Store projection adds Flatten entry/rule/name work and a fresh severity map; alternate resolver representations supply their own severity view. A fixed type switch does not make the owning load constant-cost.
1574
+ // @evidence contracts/performance.md#reuse-equivalent-work Executable config evaluation reuses the dependency-validated memory/disk producer reached through LoadConfigResolver; this adapter adds no projection cache. The ConfigStore branch returns fresh writable severity membership, so evaluation reuse does not imply sharing caller-mutable projection maps.
1575
+ // @evidence contracts/performance.md#bound-retention-and-release-resources The delegated loader owns temporary files and synchronous evaluator children; its shared evaluation cache outlives this adapter. The returned severity map belongs to the caller: ConfigStore produces new membership while a RuleConfig resolver is returned directly. Temporary parsed store metadata becomes reclaimable when otherwise unreferenced; this function imposes no cache eviction or result-size bound.
1055
1576
  func LoadRuleConfig(entry *PluginEntry, cwd, tsconfigPath string) (RuleConfig, error) {
1056
1577
  resolver, err := LoadConfigResolver(entry, cwd, tsconfigPath)
1057
1578
  if err != nil {
@@ -1074,10 +1595,25 @@ func LoadRuleConfig(entry *PluginEntry, cwd, tsconfigPath string) (RuleConfig, e
1074
1595
  // `configFile`, a path (relative to the tsconfig directory, or absolute) to
1075
1596
  // the lint config file. When `configFile` is set, that file is loaded; when it
1076
1597
  // is absent, a `lint.config.*` / `ttsc-lint.config.*` file is discovered by
1077
- // walking upward from the tsconfig directory.
1598
+ // walking upward from the tsconfig directory and then from the working
1599
+ // directory (see discoveryConfigBaseDirs for the embedder-declared origin).
1078
1600
  //
1079
1601
  // All rules, format options, and contributor plugins live in the config file
1080
- // itself — the tsconfig entry has no inline rule/format/plugin surface.
1602
+ // itself; the tsconfig entry has no inline rule/format/plugin surface.
1603
+ //
1604
+ // Executable configs are cached against their recorded module dependencies,
1605
+ // not arbitrary environment, network or user-performed filesystem reads.
1606
+ // Set TTSC_LINT_DISABLE_CONFIG_CACHE for configs that depend on such inputs.
1607
+ // Extends chains are bounded to 32 files; dependency tracking is not a sandbox.
1608
+ //
1609
+ // @evidence contracts/common.md#principled-implementation Explicit or discovered config paths use the project-root channel and extension-specific evaluator; base-first entry collection preserves inheritance and file scope under the documented dependency and depth limits.
1610
+ // @evidence contracts/common.md#clear-and-simple-design The public boundary validates configFile and delegates discovery, evaluation and entry folding to their owners rather than supporting parallel inline policy.
1611
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Node's supported hooks track module resolution without replacing foreign fs methods; the bounded extends guard is a documented limit, while cache use for untracked external inputs must be disabled.
1612
+ // @evidence contracts/common.md#meaningful-documentation Native paragraphs explain project anchoring, config ownership, cache premises and limits, with a blank comment line before tags.
1613
+ // @evidence contracts/portability.md#os-neutral-implementation LoadConfigResolver owns native config discovery/loading through its helpers. The launcher project-root channel wins over wrapper tsconfig origins; filepath preserves native path spelling and discovery probes actual candidates without assuming case policy from OS names. JSON uses native reads, JS uses explicit Node arguments/stdin, and TS uses loader-owned file URLs, argument vectors and platform temp/module-link boundaries rather than shell interpolation.
1614
+ // @evidence contracts/performance.md#efficient-algorithms Discovery probes fourteen names per visited ancestor directory across the selected origins. Loading includes config bytes, executable evaluator work when needed, dependency digest validation, recursive extends and parsed entries/rules/options; each extends lineage is capped at thirty-two files, not total branch population. Provenance helpers perform membership scans and sorting of stored paths/directories, so additional work can be quadratic in their population plus comparison/path bytes. Returned store and temporary evaluation space scale with these inputs; no fixed total time or unmeasured speedup is claimed.
1615
+ // @evidence contracts/performance.md#reuse-equivalent-work Executable evaluation delegates to a memory/disk cache keyed by version, absolute entry path/content and resolution-root namespace, with recorded dependency fingerprints revalidated on hits. Failed evaluations are not stored; dependency changes cause new work. JSON is read directly, and entry folding is performed for each load. Environment, network and arbitrary user filesystem effects are outside tracked equivalence and require the documented cache opt-out; no single-flight coordination is claimed.
1616
+ // @evidence contracts/performance.md#bound-retention-and-release-resources The returned parsed store owns entries/options and public/resident dependency provenance until its consumer releases it. Loader helpers wait for each evaluator child and defer temporary-directory cleanup on success/error; their background contexts provide no caller deadline or external cancellation, and cleanup errors are not surfaced. Memory evaluation entries live for the process and disk entries have no eviction policy here, growing with distinct versioned content/dependency payloads. This loader imposes no total config-byte, branch-population or evaluator-runtime bound.
1081
1617
  func LoadConfigResolver(entry *PluginEntry, cwd, tsconfigPath string) (RuleResolver, error) {
1082
1618
  if entry == nil {
1083
1619
  return RuleConfig{}, nil
@@ -1150,7 +1686,12 @@ func appendResidentConfigEvaluation(
1150
1686
  cloned.Realpath = cloneConfigDependencyRealpath(dependency.Realpath)
1151
1687
  store.cacheDependencies = append(store.cacheDependencies, cloned)
1152
1688
  }
1153
- return
1689
+ // JSON retains its existing timestamp-window resident guard as well as
1690
+ // the new consumed-byte proof. Executable evaluations keep their own
1691
+ // dependency population and never acquire this JSON-only path guard.
1692
+ if !strings.EqualFold(filepath.Ext(location), ".json") {
1693
+ return
1694
+ }
1154
1695
  }
1155
1696
  location = filepath.Clean(location)
1156
1697
  if !containsPath(store.cacheFiles, location) {
@@ -1300,18 +1841,15 @@ func discoveryConfigBaseDirs(cwd, tsconfigPath string) []string {
1300
1841
  return origins
1301
1842
  }
1302
1843
 
1303
- // containsPath reports whether `paths` already holds `candidate` after
1304
- // cleaning, comparing case-insensitively on Windows (where two spellings of
1305
- // the same directory differ only by drive-letter or path case).
1844
+ // containsPath reports whether paths already holds candidate's cleaned spelling.
1845
+ // Preserve distinct spellings even on Windows: directory case sensitivity and
1846
+ // alias topology cannot be inferred from the operating system alone.
1306
1847
  func containsPath(paths []string, candidate string) bool {
1307
1848
  cleaned := filepath.Clean(candidate)
1308
1849
  for _, existing := range paths {
1309
1850
  if existing == cleaned {
1310
1851
  return true
1311
1852
  }
1312
- if runtime.GOOS == "windows" && strings.EqualFold(existing, cleaned) {
1313
- return true
1314
- }
1315
1853
  }
1316
1854
  return false
1317
1855
  }
@@ -1371,6 +1909,8 @@ type evaluatedConfigFile struct {
1371
1909
  dependencyDirectories []string
1372
1910
  dependencyDigests []configDependencyFingerprint
1373
1911
  dependenciesTracked bool
1912
+ // Private correlation only; cachedConfigEvaluation serializes none of it.
1913
+ traceInvocation *lintTraceInvocation
1374
1914
  }
1375
1915
 
1376
1916
  type cachedConfigEvaluation struct {
@@ -1397,8 +1937,7 @@ func loadConfigFileEvaluationWithin(
1397
1937
  ext := strings.ToLower(filepath.Ext(location))
1398
1938
  switch ext {
1399
1939
  case ".json":
1400
- value, err := loadJSONConfigFile(location)
1401
- return evaluatedConfigFile{value: value}, err
1940
+ return loadJSONConfigEvaluation(location)
1402
1941
  case ".js", ".cjs", ".mjs":
1403
1942
  return loadCachedConfigEvaluationForRoot(
1404
1943
  location,
@@ -1421,12 +1960,16 @@ func loadConfigFileEvaluationWithin(
1421
1960
  }
1422
1961
 
1423
1962
  // configCacheVersion namespaces the on-disk config cache. Bump it whenever
1424
- // the shape of a cached config object changes so that entries written by an
1425
- // older @ttsc/lint binary are treated as a miss rather than silently reused.
1426
- // v8 also rejects content-restoring A-B-A replacement during evaluation. A v7
1427
- // cache can otherwise pair output from the transient state with the restored
1428
- // state's equal digest and physical path.
1429
- const configCacheVersion = "v8"
1963
+ // the cached shape or dependency interpretation changes, so entries written
1964
+ // by an older @ttsc/lint binary are misses rather than silently reused.
1965
+ // v8 rechecks recorded dependencies after evaluation. A recorded transient
1966
+ // digest or path that differs from the final observation prevents caching;
1967
+ // equal observations do not prove absence of intervening replacements.
1968
+ // v9 invalidates module graphs whose identity and package-boundary decisions
1969
+ // used lexical case folding instead of actual filesystem identity.
1970
+ // v11 preserves rule option object-entry order through evaluation and disk reuse.
1971
+ // v12 makes the JS contributor evaluator preserve typed-base project ownership.
1972
+ const configCacheVersion = "v12"
1430
1973
 
1431
1974
  // configEvalCache memoizes evaluated .ts/.js lint config objects for the
1432
1975
  // lifetime of one process; the on-disk cache (configCacheDir) extends the
@@ -1516,7 +2059,12 @@ func loadCachedConfigEvaluationWithPolicy(
1516
2059
  cacheNamespace string,
1517
2060
  ) (evaluatedConfigFile, error) {
1518
2061
  if configCacheDisabled() {
1519
- return eval(location)
2062
+ evaluated, err := eval(location)
2063
+ evaluated.traceInvocation.record("config-cache-outcome", map[string]any{
2064
+ "location": location, "outcome": "disabled", "success": err == nil,
2065
+ "dependencies": evaluated.dependencyDigests,
2066
+ })
2067
+ return evaluated, err
1520
2068
  }
1521
2069
  content, err := os.ReadFile(location)
1522
2070
  if err != nil {
@@ -1541,6 +2089,10 @@ func loadCachedConfigEvaluationWithPolicy(
1541
2089
  if ok &&
1542
2090
  cached.DependenciesTracked == dependenciesRequired &&
1543
2091
  cachedConfigEvaluationIsCurrent(cached) {
2092
+ newLintTraceInvocation().record("config-cache-outcome", map[string]any{
2093
+ "location": location, "key": key, "outcome": "memory-hit",
2094
+ "dependencies": cached.Dependencies, "dependenciesTracked": cached.DependenciesTracked,
2095
+ })
1544
2096
  return evaluatedConfigFileFromCache(cached), nil
1545
2097
  }
1546
2098
  if disk, hit := readConfigDiskCache(key); hit &&
@@ -1549,6 +2101,10 @@ func loadCachedConfigEvaluationWithPolicy(
1549
2101
  configEvalCacheMu.Lock()
1550
2102
  configEvalCache[key] = disk
1551
2103
  configEvalCacheMu.Unlock()
2104
+ newLintTraceInvocation().record("config-cache-outcome", map[string]any{
2105
+ "location": location, "key": key, "outcome": "disk-hit",
2106
+ "dependencies": disk.Dependencies, "dependenciesTracked": disk.DependenciesTracked,
2107
+ })
1552
2108
  return evaluatedConfigFileFromCache(disk), nil
1553
2109
  }
1554
2110
 
@@ -1556,9 +2112,18 @@ func loadCachedConfigEvaluationWithPolicy(
1556
2112
  for attempt := 0; attempt < 3; attempt++ {
1557
2113
  evaluated, err = eval(location)
1558
2114
  if err != nil {
2115
+ evaluated.traceInvocation.record("config-cache-outcome", map[string]any{
2116
+ "location": location, "key": key, "attempt": attempt + 1,
2117
+ "outcome": "evaluation-error", "error": err.Error(),
2118
+ })
1559
2119
  return evaluatedConfigFile{}, err
1560
2120
  }
1561
2121
  if evaluated.dependenciesTracked != dependenciesRequired {
2122
+ evaluated.traceInvocation.record("config-cache-outcome", map[string]any{
2123
+ "location": location, "key": key, "attempt": attempt + 1,
2124
+ "outcome": "tracking-policy-mismatch", "dependenciesTracked": evaluated.dependenciesTracked,
2125
+ "dependenciesRequired": dependenciesRequired,
2126
+ })
1562
2127
  return evaluatedConfigFile{}, fmt.Errorf(
1563
2128
  "@ttsc/lint: config evaluator for %s returned dependenciesTracked=%t, want %t",
1564
2129
  location,
@@ -1578,8 +2143,18 @@ func loadCachedConfigEvaluationWithPolicy(
1578
2143
  configEvalCache[key] = cached
1579
2144
  configEvalCacheMu.Unlock()
1580
2145
  writeConfigDiskCache(key, cached)
2146
+ evaluated.traceInvocation.record("config-cache-outcome", map[string]any{
2147
+ "location": location, "key": key, "attempt": attempt + 1,
2148
+ "outcome": "memory-published", "diskWriteAttempted": true,
2149
+ "dependencies": cached.Dependencies, "dependenciesTracked": cached.DependenciesTracked,
2150
+ })
1581
2151
  return evaluated, nil
1582
2152
  }
2153
+ evaluated.traceInvocation.record("config-cache-outcome", map[string]any{
2154
+ "location": location, "key": key, "attempt": attempt + 1,
2155
+ "outcome": "not-current", "returnedUncached": attempt == 2,
2156
+ "dependencies": evaluated.dependencyDigests, "dependenciesTracked": evaluated.dependenciesTracked,
2157
+ })
1583
2158
  }
1584
2159
  return evaluated, nil
1585
2160
  }
@@ -1768,10 +2343,23 @@ func readConfigDiskCache(key string) (cachedConfigEvaluation, bool) {
1768
2343
  if err != nil {
1769
2344
  return cachedConfigEvaluation{}, false
1770
2345
  }
1771
- var cached cachedConfigEvaluation
1772
- if err := json.Unmarshal(body, &cached); err != nil {
2346
+ var envelope struct {
2347
+ Value json.RawMessage `json:"value"`
2348
+ Dependencies []configDependencyFingerprint `json:"dependencies"`
2349
+ DependenciesTracked bool `json:"dependenciesTracked"`
2350
+ }
2351
+ if err := json.Unmarshal(body, &envelope); err != nil {
1773
2352
  return cachedConfigEvaluation{}, false
1774
2353
  }
2354
+ value, err := decodeConfigJSON(envelope.Value)
2355
+ if err != nil {
2356
+ return cachedConfigEvaluation{}, false
2357
+ }
2358
+ cached := cachedConfigEvaluation{
2359
+ Value: value,
2360
+ Dependencies: envelope.Dependencies,
2361
+ DependenciesTracked: envelope.DependenciesTracked,
2362
+ }
1775
2363
  if !isConfigObject(cached.Value) {
1776
2364
  return cachedConfigEvaluation{}, false
1777
2365
  }
@@ -1823,23 +2411,45 @@ func writeConfigDiskCache(key string, cached cachedConfigEvaluation) {
1823
2411
  // loadJSONConfigFile reads and JSON-parses a lint config file. A leading UTF-8
1824
2412
  // BOM is stripped before parsing so files saved by Windows editors are accepted.
1825
2413
  func loadJSONConfigFile(location string) (any, error) {
1826
- body, err := os.ReadFile(location)
2414
+ evaluated, err := loadJSONConfigEvaluation(location)
2415
+ return evaluated.value, err
2416
+ }
2417
+
2418
+ // loadJSONConfigEvaluation retains the raw bytes actually decoded by this call
2419
+ // beside its native identity. The BOM affects the byte witness even though JSON
2420
+ // decoding strips it. Read failures never produce a complete config proof.
2421
+ func loadJSONConfigEvaluation(location string) (evaluatedConfigFile, error) {
2422
+ beforePhysical := configDependencyRealpath(location)
2423
+ file, err := os.Open(location)
1827
2424
  if err != nil {
1828
- return nil, fmt.Errorf("@ttsc/lint: read config file %s: %w", location, err)
2425
+ return evaluatedConfigFile{}, fmt.Errorf("@ttsc/lint: read config file %s: %w", location, err)
1829
2426
  }
1830
- // Strip a leading UTF-8 BOM so files saved by Windows editors round
1831
- // trip through `json.Unmarshal` without an opaque "invalid character"
1832
- // failure. Mirrors the equivalent JS-side guard in
1833
- // `packages/lint/src/index.ts::readJsonConfigPlugins`.
2427
+ before, beforeErr := file.Stat()
2428
+ body, readErr := io.ReadAll(file)
2429
+ after, afterErr := file.Stat()
2430
+ closeErr := file.Close()
2431
+ if readErr != nil {
2432
+ return evaluatedConfigFile{}, fmt.Errorf("@ttsc/lint: read config file %s: %w", location, readErr)
2433
+ }
2434
+ if closeErr != nil {
2435
+ return evaluatedConfigFile{}, fmt.Errorf("@ttsc/lint: close config file %s: %w", location, closeErr)
2436
+ }
2437
+ digest := sha256.Sum256(body)
2438
+ selected, selectedErr := os.Stat(location)
2439
+ physical := configDependencyRealpath(location)
2440
+ stable := beforeErr == nil && afterErr == nil && selectedErr == nil && os.SameFile(before, after) && os.SameFile(after, selected) &&
2441
+ before.Mode() == after.Mode() && before.Size() == after.Size() && before.ModTime().Equal(after.ModTime()) &&
2442
+ sameConfigDependencyRealpath(beforePhysical, physical)
1834
2443
  body = bytes.TrimPrefix(body, []byte{0xEF, 0xBB, 0xBF})
1835
- var out any
1836
- if err := json.Unmarshal(body, &out); err != nil {
1837
- return nil, fmt.Errorf("@ttsc/lint: parse config file %s: %w", location, err)
2444
+ out, err := decodeConfigJSON(body)
2445
+ if err != nil {
2446
+ return evaluatedConfigFile{}, fmt.Errorf("@ttsc/lint: parse config file %s: %w", location, err)
1838
2447
  }
1839
2448
  if !isConfigObject(out) {
1840
- return nil, fmt.Errorf("@ttsc/lint: config file %s must export an ITtscLintConfig object", location)
2449
+ return evaluatedConfigFile{}, fmt.Errorf("@ttsc/lint: config file %s must export an ITtscLintConfig object", location)
1841
2450
  }
1842
- return out, nil
2451
+ return evaluatedConfigFile{value: out, dependencies: []string{location}, dependenciesTracked: true,
2452
+ dependencyDigests: []configDependencyFingerprint{{Path: filepath.Clean(location), Digest: hex.EncodeToString(digest[:]), IdentityStable: stable, Kind: configDependencyFile, Realpath: physical, Scope: configDependencyWatch}}}, nil
1843
2453
  }
1844
2454
 
1845
2455
  // serializableConfigKeys is the single source of truth for the ITtscLintConfig
@@ -1869,43 +2479,125 @@ func serializableConfigKeysLiteral() string {
1869
2479
  // path for error messages; `label` is the human-readable subject (e.g. "config
1870
2480
  // file" or "TypeScript config file") spliced into the load/parse error
1871
2481
  // prefixes so each loader keeps its own wording.
2482
+ // Opt-in observation retains the exact bytes read and the actual normalized
2483
+ // dependencies under one invocation. It never supplies a replacement result.
1872
2484
  func runConfigLoaderCommand(
1873
2485
  cmd *exec.Cmd,
1874
2486
  location string,
1875
2487
  label string,
1876
2488
  outputPath string,
1877
- ) (evaluatedConfigFile, error) {
2489
+ ) (evaluated evaluatedConfigFile, resultErr error) {
1878
2490
  // The child's stderr is human output and goes straight to this process's
1879
2491
  // stderr as it is written. Collecting it only to replay it afterwards is what
1880
2492
  // made a long evaluation print nothing at all, and what would make a loud one
1881
2493
  // grow this process's memory without bound.
1882
2494
  cmd.Stdout = io.Discard
1883
2495
  cmd.Stderr = os.Stderr
2496
+ observation := newLintTraceInvocation()
2497
+ var rawCapture map[string]any
2498
+ readOutcome := "not-read"
2499
+ normalizationAttempted := false
2500
+ normalizationAccepted := false
2501
+ if observation != nil {
2502
+ defer func() {
2503
+ data := map[string]any{
2504
+ "location": location,
2505
+ "label": label,
2506
+ "raw": rawCapture,
2507
+ "readOutcome": readOutcome,
2508
+ "normalizationAttempted": normalizationAttempted,
2509
+ "normalizationAccepted": normalizationAccepted,
2510
+ "dependencies": evaluated.dependencyDigests,
2511
+ "dependenciesTracked": evaluated.dependenciesTracked,
2512
+ "success": resultErr == nil,
2513
+ }
2514
+ if resultErr != nil {
2515
+ data["error"] = resultErr.Error()
2516
+ }
2517
+ evaluated.traceInvocation = observation
2518
+ observation.record("config-loader-result", data)
2519
+ }()
2520
+ }
2521
+ var lower time.Time
2522
+ if observation != nil {
2523
+ lower = time.Now().UTC()
2524
+ observation.record("process-attempt", map[string]any{
2525
+ "pid": 0, "argv": cmd.Args, "cwd": cmd.Dir, "cwdInherited": cmd.Dir == "",
2526
+ "startLowerBound": lower.Format(time.RFC3339Nano), "owner": "lint-config-loader",
2527
+ })
2528
+ }
1884
2529
  err := cmd.Run()
2530
+ if observation != nil {
2531
+ upper := time.Now().UTC()
2532
+ pid := 0
2533
+ if cmd.Process != nil {
2534
+ pid = cmd.Process.Pid
2535
+ }
2536
+ data := map[string]any{
2537
+ "pid": pid, "started": pid > 0, "exitObserved": cmd.ProcessState != nil,
2538
+ "argv": cmd.Args, "cwd": cmd.Dir, "cwdInherited": cmd.Dir == "",
2539
+ "startLowerBound": lower.Format(time.RFC3339Nano),
2540
+ "startUpperBound": upper.Format(time.RFC3339Nano), "owner": "lint-config-loader",
2541
+ "method": "Run", "success": err == nil,
2542
+ }
2543
+ if cmd.ProcessState != nil {
2544
+ data["exitCode"] = cmd.ProcessState.ExitCode()
2545
+ data["stateSuccess"] = cmd.ProcessState.Success()
2546
+ data["state"] = cmd.ProcessState.String()
2547
+ }
2548
+ if err != nil {
2549
+ data["error"] = err.Error()
2550
+ }
2551
+ observation.record("process-result", data)
2552
+ }
1885
2553
  if err != nil {
1886
2554
  // The loader's stack already reached the user's stderr as it was written.
1887
2555
  // What it could not put there is a reason a caller can act on, so that
1888
2556
  // arrives through the result file instead.
1889
- if reason := loaderFailureReason(outputPath); reason != "" {
2557
+ if reason := loaderFailureReason(outputPath, func(raw []byte, readErr error) {
2558
+ if observation != nil {
2559
+ readOutcome = "complete"
2560
+ if readErr != nil {
2561
+ readOutcome = "IO-failed"
2562
+ }
2563
+ rawCapture = observation.capture("loader-raw", raw)
2564
+ }
2565
+ }); reason != "" {
1890
2566
  return evaluatedConfigFile{}, fmt.Errorf("@ttsc/lint: load %s %s: %s", label, location, reason)
1891
2567
  }
1892
2568
  return evaluatedConfigFile{}, fmt.Errorf("@ttsc/lint: load %s %s: %w", label, location, err)
1893
2569
  }
1894
2570
  output, err := os.ReadFile(outputPath)
2571
+ if observation != nil {
2572
+ readOutcome = "complete"
2573
+ if err != nil {
2574
+ readOutcome = "IO-failed"
2575
+ }
2576
+ rawCapture = observation.capture("loader-raw", output)
2577
+ }
1895
2578
  if err != nil {
1896
2579
  return evaluatedConfigFile{}, fmt.Errorf("@ttsc/lint: read %s %s result: %w", label, location, err)
1897
2580
  }
1898
2581
  var envelope struct {
1899
2582
  Dependencies []configDependencyFingerprint `json:"dependencies"`
1900
- Value any `json:"value"`
2583
+ Value json.RawMessage `json:"value"`
1901
2584
  }
1902
2585
  if err := json.Unmarshal(output, &envelope); err != nil {
1903
2586
  return evaluatedConfigFile{}, fmt.Errorf("@ttsc/lint: parse %s %s output: %w", label, location, err)
1904
2587
  }
1905
- if !isConfigObject(envelope.Value) {
2588
+ var value any
2589
+ if len(envelope.Value) != 0 {
2590
+ value, err = decodeConfigJSON(envelope.Value)
2591
+ if err != nil {
2592
+ return evaluatedConfigFile{}, fmt.Errorf("@ttsc/lint: parse %s %s output: %w", label, location, err)
2593
+ }
2594
+ }
2595
+ if !isConfigObject(value) {
1906
2596
  return evaluatedConfigFile{}, fmt.Errorf("@ttsc/lint: config file %s must export an ITtscLintConfig object", location)
1907
2597
  }
1908
2598
  normalized, ok := normalizeConfigDependencyFingerprints(envelope.Dependencies)
2599
+ normalizationAttempted = true
2600
+ normalizationAccepted = ok
1909
2601
  if !ok {
1910
2602
  return evaluatedConfigFile{}, fmt.Errorf("@ttsc/lint: %s %s returned malformed dependency fingerprints", label, location)
1911
2603
  }
@@ -1921,7 +2613,7 @@ func runConfigLoaderCommand(
1921
2613
  }
1922
2614
  }
1923
2615
  return evaluatedConfigFile{
1924
- value: envelope.Value,
2616
+ value: value,
1925
2617
  dependencies: dependencies,
1926
2618
  dependencyDirectories: directories,
1927
2619
  dependencyDigests: normalized,
@@ -2997,35 +3689,43 @@ function modulePackageName(specifier) {
2997
3689
  function resolvedPackageContains(modules, packageName, childLocation) {
2998
3690
  try {
2999
3691
  const packageRoot = fs.realpathSync(path.join(modules, packageName));
3000
- const relative = path.relative(
3001
- packageRoot,
3002
- fs.realpathSync(childLocation),
3003
- );
3004
- return (
3005
- relative === "" ||
3006
- (relative !== ".." &&
3007
- !relative.startsWith(".." + path.sep) &&
3008
- !path.isAbsolute(relative))
3009
- );
3692
+ const child = fs.realpathSync(childLocation);
3693
+ const relative = path.relative(packageRoot, child);
3694
+ if (relative === "") return sameResolutionPath(packageRoot, child);
3695
+ if (
3696
+ relative === ".." ||
3697
+ relative.startsWith(".." + path.sep) ||
3698
+ path.isAbsolute(relative)
3699
+ ) return false;
3700
+ let ancestor = child;
3701
+ for (let remaining = relative.split(path.sep).length; remaining !== 0; --remaining)
3702
+ ancestor = path.dirname(ancestor);
3703
+ return sameResolutionPath(packageRoot, ancestor);
3010
3704
  } catch {
3011
3705
  return false;
3012
3706
  }
3013
3707
  }
3014
3708
 
3015
3709
  function sameResolutionPath(left, right) {
3016
- return path.relative(left, right) === "";
3710
+ const resolvedLeft = path.resolve(left);
3711
+ const resolvedRight = path.resolve(right);
3712
+ if (resolvedLeft === resolvedRight) return true;
3713
+ if (path.relative(resolvedLeft, resolvedRight) !== "") return false;
3714
+ try {
3715
+ const leftIdentity = fs.statSync(resolvedLeft, { bigint: true });
3716
+ const rightIdentity = fs.statSync(resolvedRight, { bigint: true });
3717
+ return leftIdentity.ino !== 0n &&
3718
+ leftIdentity.dev === rightIdentity.dev &&
3719
+ leftIdentity.ino === rightIdentity.ino;
3720
+ } catch {
3721
+ return false;
3722
+ }
3017
3723
  }
3018
3724
 
3019
3725
  function samePhysicalPath(left, right) {
3020
3726
  try {
3021
3727
  return sameResolutionPath(realPath(left), realPath(right));
3022
3728
  } catch {
3023
- // Fall back to the spellings themselves, folding case the way the platform
3024
- // does. On the entry gate a false negative is catastrophic — the config
3025
- // stops being recognized and its whole graph collapses — while a false
3026
- // positive only over-includes, so the degradation has to lean toward "same
3027
- // file". A drive-letter or component case difference is the ordinary
3028
- // Windows situation; a per-directory case-sensitive tree is the rare one.
3029
3729
  return sameResolutionPath(left, right);
3030
3730
  }
3031
3731
  }
@@ -4321,35 +5021,43 @@ function resolvedPackageContains(
4321
5021
  ): boolean {
4322
5022
  try {
4323
5023
  const packageRoot = fs.realpathSync(path.join(modules, packageName));
4324
- const relative = path.relative(
4325
- packageRoot,
4326
- fs.realpathSync(childLocation),
4327
- );
4328
- return (
4329
- relative === "" ||
4330
- (relative !== ".." &&
4331
- !relative.startsWith(".." + path.sep) &&
4332
- !path.isAbsolute(relative))
4333
- );
5024
+ const child = fs.realpathSync(childLocation);
5025
+ const relative = path.relative(packageRoot, child);
5026
+ if (relative === "") return sameResolutionPath(packageRoot, child);
5027
+ if (
5028
+ relative === ".." ||
5029
+ relative.startsWith(".." + path.sep) ||
5030
+ path.isAbsolute(relative)
5031
+ ) return false;
5032
+ let ancestor = child;
5033
+ for (let remaining = relative.split(path.sep).length; remaining !== 0; --remaining)
5034
+ ancestor = path.dirname(ancestor);
5035
+ return sameResolutionPath(packageRoot, ancestor);
4334
5036
  } catch {
4335
5037
  return false;
4336
5038
  }
4337
5039
  }
4338
5040
 
4339
5041
  function sameResolutionPath(left: string, right: string): boolean {
4340
- return path.relative(left, right) === "";
5042
+ const resolvedLeft = path.resolve(left);
5043
+ const resolvedRight = path.resolve(right);
5044
+ if (resolvedLeft === resolvedRight) return true;
5045
+ if (path.relative(resolvedLeft, resolvedRight) !== "") return false;
5046
+ try {
5047
+ const leftIdentity = fs.statSync(resolvedLeft, { bigint: true });
5048
+ const rightIdentity = fs.statSync(resolvedRight, { bigint: true });
5049
+ return leftIdentity.ino !== 0n &&
5050
+ leftIdentity.dev === rightIdentity.dev &&
5051
+ leftIdentity.ino === rightIdentity.ino;
5052
+ } catch {
5053
+ return false;
5054
+ }
4341
5055
  }
4342
5056
 
4343
5057
  function samePhysicalPath(left: string, right: string): boolean {
4344
5058
  try {
4345
5059
  return sameResolutionPath(realPath(left), realPath(right));
4346
5060
  } catch {
4347
- // Fall back to the spellings themselves, folding case the way the platform
4348
- // does. On the entry gate a false negative is catastrophic — the config
4349
- // stops being recognized and its whole graph collapses — while a false
4350
- // positive only over-includes, so the degradation has to lean toward "same
4351
- // file". A drive-letter or component case difference is the ordinary
4352
- // Windows situation; a per-directory case-sensitive tree is the rare one.
4353
5061
  return sameResolutionPath(left, right);
4354
5062
  }
4355
5063
  }
@@ -4562,11 +5270,8 @@ func typeScriptConfigLoaderTsconfig(loader, location, outDir string) string {
4562
5270
  // packages/banner/driver/banner.go and packages/strip/driver/config.go. #1169
4563
5271
  // decided against extracting it — the only home the three modules could share
4564
5272
  // is the public `packages/ttsc/driver` seam, and packages/lint's go.mod
4565
- // deliberately requires no in-tree ttsc module — and replaced the checklist
4566
- // with a gate: `scripts/ci/config-loader-copies.cjs` compares every function
4567
- // between these markers across all three copies on every pull request, so
4568
- // editing one and not the others fails by name. That file's header carries the
4569
- // full decision and the rules for changing this block.
5273
+ // deliberately requires no in-tree ttsc module — so a change to one copy must
5274
+ // be made to all three.
4570
5275
  //
4571
5276
  // The code between the markers must stay identical. Comments may differ, the
4572
5277
  // `@ttsc/<pkg>:` error prefix may differ, and @ttsc/strip spells each name with
@@ -4707,12 +5412,13 @@ func resolveDirLink(dir string) string {
4707
5412
  // project being linted, with an explicit environment variable winning and a
4708
5413
  // last resort that invents no path.
4709
5414
  //
4710
- // The three Go copies are held identical by the gate named at the top of this
4711
- // block. The JS original — `resolveConfigTsgo` / `resolveTtsxLauncher` in
4712
- // packages/lint/src/index.ts — is a fourth copy in another language that no Go
4713
- // gate can reach; the two evaluators must keep one policy, because it was a
4714
- // divergence between them that made a TypeScript lint config unevaluable
4715
- // outside a `ttsx`-launched host.
5415
+ // No automated check holds the three Go copies identical: a change lands in
5416
+ // all three by hand, and each package's own config-loader tests exercise it.
5417
+ // The JS original — `resolveConfigTsgo` / `resolveTtsxLauncher` in
5418
+ // packages/lint/src/index.ts — is a fourth copy in another language; the two
5419
+ // evaluators must keep one policy, because it was a divergence between them
5420
+ // that made a TypeScript lint config unevaluable outside a `ttsx`-launched
5421
+ // host.
4716
5422
  //
4717
5423
  // The environment alone is the wrong place to ask. `ttsx` exports
4718
5424
  // TTSC_TSGO_BINARY and TTSC_TTSX_BINARY to its own descendants, so a host
@@ -5101,8 +5807,9 @@ func sortedRuleNames(config RuleConfig, include func(Severity) bool) []string {
5101
5807
  // with "..").
5102
5808
  func matchAnyPattern(baseDir string, patterns []string, fileName string) bool {
5103
5809
  rel := filepath.ToSlash(fileName)
5810
+ base := ""
5104
5811
  if baseDir != "" {
5105
- base := baseDir
5812
+ base = baseDir
5106
5813
  if abs, err := filepath.Abs(base); err == nil {
5107
5814
  base = abs
5108
5815
  }
@@ -5117,9 +5824,29 @@ func matchAnyPattern(baseDir string, patterns []string, fileName string) bool {
5117
5824
  return false
5118
5825
  }
5119
5826
  rel = filepath.ToSlash(candidate)
5827
+ } else {
5828
+ base = ""
5120
5829
  }
5121
5830
  }
5122
5831
  rel = strings.TrimPrefix(rel, "./")
5832
+ if matchAnyGlob(patterns, rel) {
5833
+ return true
5834
+ }
5835
+ if base == "" {
5836
+ return false
5837
+ }
5838
+ // Most glob misses cannot become matches by changing only case. Rule
5839
+ // overrides test every file, so avoid a directory walk for those misses.
5840
+ // Character classes, escapes, and Unicode use the full on-disk decision:
5841
+ // lowercasing a class range can change which punctuation it admits.
5842
+ if !mayMatchStoredCase(patterns, rel) {
5843
+ return false
5844
+ }
5845
+ stored := storedRelativeSpelling(base, rel)
5846
+ return stored != rel && matchAnyGlob(patterns, stored)
5847
+ }
5848
+
5849
+ func matchAnyGlob(patterns []string, rel string) bool {
5123
5850
  for _, pattern := range patterns {
5124
5851
  if matchGlob(normalizeGlobPattern(pattern), rel) {
5125
5852
  return true
@@ -5128,161 +5855,111 @@ func matchAnyPattern(baseDir string, patterns []string, fileName string) bool {
5128
5855
  return false
5129
5856
  }
5130
5857
 
5131
- // normalizeGlobPattern normalizes a user-supplied glob pattern to forward
5132
- // slashes and strips a leading "./". Patterns that contain no slash are treated
5133
- // as basename-only globs by prepending "**/" so that `*.ts` matches any
5134
- // TypeScript file regardless of directory depth, matching ESLint's behavior.
5135
- func normalizeGlobPattern(pattern string) string {
5136
- pattern = filepath.ToSlash(pattern)
5137
- pattern = strings.TrimPrefix(pattern, "./")
5138
- if !strings.Contains(pattern, "/") {
5139
- return "**/" + pattern
5858
+ // mayMatchStoredCase is only a negative filter. A simple ASCII glob that
5859
+ // cannot match rel even without case has no stored-case match to discover.
5860
+ // Anything whose case folding or glob grammar needs more than ASCII is read
5861
+ // from the tree instead of risking a false negative.
5862
+ func mayMatchStoredCase(patterns []string, rel string) bool {
5863
+ if !isASCII(rel) {
5864
+ return true
5140
5865
  }
5141
- return pattern
5142
- }
5143
-
5144
- // matchGlob tests whether `name` matches `pattern` using the ESLint-compatible
5145
- // glob semantics implemented by matchGlobParts. Both strings are trimmed of
5146
- // leading/trailing slashes before splitting on "/" so that empty segments do
5147
- // not appear in the part slices. Brace alternatives (`{a,b,c}`) are expanded
5148
- // before matching so patterns like `src/foo/{a.ts,b.ts}` reach every branch —
5149
- // Go's `filepath.Match` does not honor brace expansion natively.
5150
- func matchGlob(pattern, name string) bool {
5151
- pattern = strings.Trim(pattern, "/")
5152
- name = strings.Trim(name, "/")
5153
- if pattern == "" {
5154
- return name == ""
5155
- }
5156
- nameParts := []string{}
5157
- if name != "" {
5158
- nameParts = strings.Split(name, "/")
5159
- }
5160
- for _, expanded := range expandBraces(pattern) {
5161
- if matchGlobParts(strings.Split(expanded, "/"), nameParts) {
5866
+ folded := strings.ToLower(rel)
5867
+ for _, pattern := range patterns {
5868
+ if !isASCII(pattern) || strings.ContainsAny(pattern, "[]\\") {
5869
+ return true
5870
+ }
5871
+ if matchGlob(strings.ToLower(normalizeGlobPattern(pattern)), folded) {
5162
5872
  return true
5163
5873
  }
5164
5874
  }
5165
5875
  return false
5166
5876
  }
5167
5877
 
5168
- // expandBraces expands shell-style brace alternatives (`{a,b,c}`) in `pattern`
5169
- // into the equivalent flat list of patterns. The expansion is recursive: a
5170
- // pattern with multiple brace groups produces the Cartesian product across all
5171
- // groups. Patterns with no braces, or with an unmatched opening `{`, are
5172
- // returned unchanged so that callers can treat the result as an authoritative
5173
- // list of every concrete alternative the user wrote.
5174
- //
5175
- // Only top-level braces are recognized; nested braces inside another brace
5176
- // group's alternative are honored by the recursion in alternative expansion,
5177
- // but escaped braces (`\{`, `\}`) are not currently supported because lint
5178
- // config patterns have no reason to embed literal braces. If a user ever needs
5179
- // one, the simplest workaround is to author the glob without the brace group.
5180
- func expandBraces(pattern string) []string {
5181
- open := strings.IndexByte(pattern, '{')
5182
- if open < 0 {
5183
- return []string{pattern}
5184
- }
5185
- // Find the matching close brace, accounting for nested groups so the
5186
- // outermost group is split first. A pattern with no matching close brace
5187
- // is treated as a literal — return it unchanged. `closeIdx` shadows no
5188
- // builtin (unlike the natural `close` name), which keeps `go vet` quiet.
5189
- depth := 0
5190
- closeIdx := -1
5191
- for i := open; i < len(pattern); i++ {
5192
- switch pattern[i] {
5193
- case '{':
5194
- depth++
5195
- case '}':
5196
- depth--
5197
- if depth == 0 {
5198
- closeIdx = i
5199
- }
5200
- }
5201
- if closeIdx >= 0 {
5202
- break
5203
- }
5204
- }
5205
- if closeIdx < 0 {
5206
- return []string{pattern}
5207
- }
5208
- prefix := pattern[:open]
5209
- suffix := pattern[closeIdx+1:]
5210
- // Split the brace body on top-level commas so nested groups remain
5211
- // intact for the recursive expansion below.
5212
- body := pattern[open+1 : closeIdx]
5213
- alternatives := splitBraceAlternatives(body)
5214
- // Expand each alternative against the suffix; the suffix may itself
5215
- // contain further brace groups, which the recursive call handles.
5216
- suffixExpansions := expandBraces(suffix)
5217
- out := make([]string, 0, len(alternatives)*len(suffixExpansions))
5218
- for _, alt := range alternatives {
5219
- for _, altExpanded := range expandBraces(alt) {
5220
- for _, suf := range suffixExpansions {
5221
- out = append(out, prefix+altExpanded+suf)
5222
- }
5878
+ func isASCII(value string) bool {
5879
+ for index := 0; index < len(value); index++ {
5880
+ if value[index] >= 0x80 {
5881
+ return false
5223
5882
  }
5224
5883
  }
5225
- return out
5884
+ return true
5226
5885
  }
5227
5886
 
5228
- // splitBraceAlternatives splits the body of a brace group on top-level commas.
5229
- // Commas inside a nested `{...}` are not separators — the matching close brace
5230
- // is tracked so `a,{b,c},d` splits into three alternatives, not four.
5231
- func splitBraceAlternatives(body string) []string {
5232
- out := []string{}
5233
- depth := 0
5234
- start := 0
5235
- for i := 0; i < len(body); i++ {
5236
- switch body[i] {
5237
- case '{':
5238
- depth++
5239
- case '}':
5240
- if depth > 0 {
5241
- depth--
5242
- }
5243
- case ',':
5244
- if depth == 0 {
5245
- out = append(out, body[start:i])
5246
- start = i + 1
5247
- }
5887
+ // storedRelativeSpelling returns `rel`, a slash-separated path below `base`,
5888
+ // spelled the way each directory stores its names. A Program can name a file
5889
+ // the way an import spelled it, and on a volume that ignores case (macOS's
5890
+ // default) `SRC/DIRECTORY/index.ts` reaches `src/directory/index.ts` while
5891
+ // `filepath.EvalSymlinks` keeps the import's spelling, so a glob written
5892
+ // against the tree missed it (samchon/ttsc#1589). Each component its parent
5893
+ // does not list exactly is replaced by the one entry equal to it ignoring
5894
+ // case; a path that does not exist, or a component with no single such entry,
5895
+ // keeps the given spelling.
5896
+ func storedRelativeSpelling(base, rel string) string {
5897
+ if _, err := os.Stat(filepath.Join(base, filepath.FromSlash(rel))); err != nil {
5898
+ return rel
5899
+ }
5900
+ current := base
5901
+ components := strings.Split(rel, "/")
5902
+ for index, component := range components {
5903
+ if component == "" || component == "." {
5904
+ continue
5248
5905
  }
5906
+ components[index] = storedEntryName(current, component)
5907
+ current = filepath.Join(current, components[index])
5249
5908
  }
5250
- out = append(out, body[start:])
5251
- return out
5909
+ return strings.Join(components, "/")
5252
5910
  }
5253
5911
 
5254
- // matchGlobParts recursively matches path segments against pattern segments.
5255
- // A "**" segment matches zero or more path segments (greedy: tries zero first,
5256
- // then each successive prefix) so that `**/*.ts` matches both `a.ts` and
5257
- // `dir/a.ts`.
5258
- func matchGlobParts(patternParts, nameParts []string) bool {
5259
- if len(patternParts) == 0 {
5260
- return len(nameParts) == 0
5912
+ // storedEntryName is the name `directory` stores for `name`: `name` itself when
5913
+ // the directory lists it, else its single entry equal to it ignoring case.
5914
+ func storedEntryName(directory, name string) string {
5915
+ entries, err := os.ReadDir(directory)
5916
+ if err != nil {
5917
+ return name
5261
5918
  }
5262
- head := patternParts[0]
5263
- if head == "**" {
5264
- if matchGlobParts(patternParts[1:], nameParts) {
5265
- return true
5919
+ match := ""
5920
+ for _, entry := range entries {
5921
+ if entry.Name() == name {
5922
+ return name
5266
5923
  }
5267
- for i := range nameParts {
5268
- if matchGlobParts(patternParts[1:], nameParts[i+1:]) {
5269
- return true
5924
+ if strings.EqualFold(entry.Name(), name) {
5925
+ if match != "" {
5926
+ return name
5270
5927
  }
5928
+ match = entry.Name()
5271
5929
  }
5272
- return false
5273
5930
  }
5274
- if len(nameParts) == 0 {
5275
- return false
5931
+ if match == "" {
5932
+ return name
5276
5933
  }
5277
- ok, err := filepath.Match(head, nameParts[0])
5278
- if err != nil || !ok {
5279
- return false
5934
+ return match
5935
+ }
5936
+
5937
+ // normalizeGlobPattern normalizes a user-supplied glob pattern to forward
5938
+ // slashes and strips a leading "./". Patterns that contain no slash are treated
5939
+ // as basename-only globs by prepending "**/" so that `*.ts` matches any
5940
+ // TypeScript file regardless of directory depth, matching ESLint's behavior.
5941
+ func normalizeGlobPattern(pattern string) string {
5942
+ pattern = filepath.ToSlash(pattern)
5943
+ pattern = strings.TrimPrefix(pattern, "./")
5944
+ if !strings.Contains(pattern, "/") {
5945
+ return "**/" + pattern
5280
5946
  }
5281
- return matchGlobParts(patternParts[1:], nameParts[1:])
5947
+ return pattern
5282
5948
  }
5283
5949
 
5284
5950
  // Severity returns the configured level for a rule, defaulting to
5285
5951
  // `SeverityOff`. Rules opt in explicitly — silent on missing entries.
5952
+ // Lookup accepts either canonical or eslint-prefixed stored keys after map
5953
+ // identity validation through ResolveProjectRules.
5954
+ //
5955
+ // @evidence contracts/common.md#principled-implementation Exact, canonical and unique normalized-alias lookup preserve explicit off values and default only absent names to off after identity validation.
5956
+ // @evidence contracts/common.md#clear-and-simple-design One scalar lookup owns absence behavior without constructing a normalized map for each rule query.
5957
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Missing declarations remain disabled by documented policy rather than a fixture-specific activation fallback.
5958
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains opt-in absence and the direction of alias lookup, separated from the acknowledgment tags.
5959
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation Severity looks up a rule severity by name and touches no filesystem path or process.
5960
+ // @evidence contracts/performance.md#efficient-algorithms Exact and canonical keys use an expected constant number of map probes, with hashing and normalization proportional to query-name bytes. Only a miss scans n stored names, paying their normalization/comparison byte costs; no normalized map or cached snapshot is built.
5961
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work Severity keeps no cache and shares no computation.
5962
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Severity acquires no handle or task and retains nothing.
5286
5963
  func (c RuleConfig) Severity(name string) Severity {
5287
5964
  if c == nil {
5288
5965
  return SeverityOff
@@ -5294,6 +5971,11 @@ func (c RuleConfig) Severity(name string) Severity {
5294
5971
  if sev, ok := c[canonical]; ok {
5295
5972
  return sev
5296
5973
  }
5974
+ for storedName, sev := range c {
5975
+ if normalizeBuiltinRuleName(storedName) == canonical {
5976
+ return sev
5977
+ }
5978
+ }
5297
5979
  return SeverityOff
5298
5980
  }
5299
5981
 
@@ -5310,8 +5992,11 @@ func (c RuleConfig) Severity(name string) Severity {
5310
5992
  // writes, and namespaced so it cannot collide with a payload field. This file
5311
5993
  // spends "error" on rule severity, which is exactly the confusion a shared,
5312
5994
  // prefixed key avoids.
5313
- func loaderFailureReason(outputPath string) string {
5995
+ // observe receives this same read's bytes and error before envelope decoding;
5996
+ // it cannot substitute bytes or alter the returned failure reason.
5997
+ func loaderFailureReason(outputPath string, observe func([]byte, error)) string {
5314
5998
  raw, err := os.ReadFile(outputPath)
5999
+ observe(raw, err)
5315
6000
  if err != nil {
5316
6001
  return ""
5317
6002
  }