rigortype 0.4.6 → 0.4.8

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 (550) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -2
  3. data/data/core_overlay/bigdecimal.rbs +33 -0
  4. data/data/core_overlay/resolv.rbs +30 -0
  5. data/data/gem_overlay/activesupport/core_ext.rbs +45 -13
  6. data/data/gem_overlay/addressable/addressable.rbs +40 -0
  7. data/data/vendored_gem_sigs/bundler/bundler.rbs +1 -1
  8. data/data/vendored_gem_sigs/rubygems/rubygems_extras.rbs +4 -3
  9. data/docs/handbook/01-getting-started.md +6 -3
  10. data/docs/handbook/11-sig-gen.md +85 -3
  11. data/docs/handbook/appendix-phpstan.md +4 -4
  12. data/docs/install.md +20 -0
  13. data/docs/manual/01-installation.md +67 -26
  14. data/docs/manual/02-cli-reference.md +455 -113
  15. data/docs/manual/03-configuration.md +76 -5
  16. data/docs/manual/04-diagnostics.md +5 -4
  17. data/docs/manual/06-baseline.md +6 -4
  18. data/docs/manual/08-skills.md +11 -0
  19. data/docs/manual/09-editor-integration.md +21 -2
  20. data/docs/manual/10-mcp-server.md +38 -2
  21. data/docs/manual/12-caching.md +4 -3
  22. data/docs/manual/14-rails-quickstart.md +1 -1
  23. data/docs/manual/19-effect-labels.md +3 -4
  24. data/docs/manual/plugins/rigor-actionpack.md +32 -15
  25. data/docs/manual/plugins/rigor-activesupport-core-ext.md +23 -1
  26. data/docs/manual/plugins/rigor-sorbet.md +17 -3
  27. data/lib/rigor/analysis/baseline.rb +24 -27
  28. data/lib/rigor/analysis/check_rules/always_raises_shield.rb +147 -0
  29. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +5 -6
  30. data/lib/rigor/analysis/check_rules/call_facts.rb +58 -0
  31. data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +2 -2
  32. data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +12 -4
  33. data/lib/rigor/analysis/check_rules/duplicate_hash_key_collector.rb +2 -2
  34. data/lib/rigor/analysis/check_rules/inferred_param_guard.rb +85 -13
  35. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +16 -4
  36. data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +6 -1
  37. data/lib/rigor/analysis/check_rules/main_pass_collector.rb +5 -8
  38. data/lib/rigor/analysis/check_rules/plugin_api_surface.rb +195 -0
  39. data/lib/rigor/analysis/check_rules/published_constant_guard.rb +41 -12
  40. data/lib/rigor/analysis/check_rules/rbs_receiver_surface.rb +27 -1
  41. data/lib/rigor/analysis/check_rules/rebinding_block_callees.rb +3 -3
  42. data/lib/rigor/analysis/check_rules/replaced_singleton_defs.rb +96 -0
  43. data/lib/rigor/analysis/check_rules/return_in_ensure_collector.rb +1 -2
  44. data/lib/rigor/analysis/check_rules/rule_ids.rb +9 -2
  45. data/lib/rigor/analysis/check_rules/rule_walk.rb +9 -7
  46. data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +3 -4
  47. data/lib/rigor/analysis/check_rules/special_global_setters.rb +3 -3
  48. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +2 -2
  49. data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +2 -2
  50. data/lib/rigor/analysis/check_rules.rb +720 -141
  51. data/lib/rigor/analysis/crash_signature.rb +45 -3
  52. data/lib/rigor/analysis/dependency_recorder.rb +237 -80
  53. data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +14 -3
  54. data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +1 -1
  55. data/lib/rigor/analysis/dependency_source_inference/index.rb +6 -8
  56. data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
  57. data/lib/rigor/analysis/edit_replay.rb +93 -6
  58. data/lib/rigor/analysis/fact_store.rb +3 -3
  59. data/lib/rigor/analysis/incremental.rb +11 -1
  60. data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +4 -3
  61. data/lib/rigor/analysis/incremental_run_slot.rb +2 -2
  62. data/lib/rigor/analysis/incremental_session.rb +306 -53
  63. data/lib/rigor/analysis/reachability/plugin_roots.rb +6 -3
  64. data/lib/rigor/analysis/rule_catalog.rb +39 -3
  65. data/lib/rigor/analysis/run_cache_key.rb +27 -3
  66. data/lib/rigor/analysis/run_disclosure_credit.rb +26 -6
  67. data/lib/rigor/analysis/run_stats.rb +2 -2
  68. data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +6 -2
  69. data/lib/rigor/analysis/runner/declaration_position.rb +8 -8
  70. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +264 -112
  71. data/lib/rigor/analysis/runner/effect_envelope_pass.rb +4 -9
  72. data/lib/rigor/analysis/runner/pool_coordinator.rb +173 -328
  73. data/lib/rigor/analysis/runner/project_pre_passes.rb +4 -37
  74. data/lib/rigor/analysis/runner/run_level_facts.rb +304 -0
  75. data/lib/rigor/analysis/runner/run_snapshots.rb +44 -54
  76. data/lib/rigor/analysis/runner/worker_payload.rb +36 -0
  77. data/lib/rigor/analysis/runner.rb +298 -109
  78. data/lib/rigor/analysis/self_call_resolution_recorder.rb +62 -23
  79. data/lib/rigor/analysis/template_unit_positions.rb +2 -3
  80. data/lib/rigor/analysis/template_units.rb +9 -1
  81. data/lib/rigor/analysis/worker_session.rb +65 -71
  82. data/lib/rigor/bleeding_edge.rb +22 -10
  83. data/lib/rigor/builtins/imported_refinements.rb +6 -8
  84. data/lib/rigor/builtins/predefined_constant_refinements.rb +1 -1
  85. data/lib/rigor/builtins/regex_refinement.rb +4 -6
  86. data/lib/rigor/cache/descriptor.rb +6 -5
  87. data/lib/rigor/cache/file_digest.rb +39 -31
  88. data/lib/rigor/cache/incremental_snapshot.rb +95 -17
  89. data/lib/rigor/cache/rbs_cache_producer.rb +2 -2
  90. data/lib/rigor/cache/rbs_class_ancestor_table.rb +1 -1
  91. data/lib/rigor/cache/rbs_class_type_param_names.rb +2 -2
  92. data/lib/rigor/cache/rbs_constant_table.rb +1 -1
  93. data/lib/rigor/cache/rbs_descriptor.rb +90 -4
  94. data/lib/rigor/cache/rbs_environment.rb +8 -1
  95. data/lib/rigor/cache/rbs_environment_marshal_patch.rb +2 -2
  96. data/lib/rigor/cache/rbs_known_class_names.rb +1 -1
  97. data/lib/rigor/cache/store.rb +11 -10
  98. data/lib/rigor/ci_detector.rb +1 -1
  99. data/lib/rigor/cli/annotate_command.rb +24 -19
  100. data/lib/rigor/cli/baseline_command.rb +160 -57
  101. data/lib/rigor/cli/catalogue.rb +256 -0
  102. data/lib/rigor/cli/check_command.rb +112 -104
  103. data/lib/rigor/cli/check_runner_factory.rb +2 -2
  104. data/lib/rigor/cli/command.rb +15 -1
  105. data/lib/rigor/cli/coverage_command.rb +21 -8
  106. data/lib/rigor/cli/coverage_mutation.rb +5 -7
  107. data/lib/rigor/cli/coverage_renderer.rb +2 -1
  108. data/lib/rigor/cli/coverage_scan.rb +3 -5
  109. data/lib/rigor/cli/diff_command.rb +25 -20
  110. data/lib/rigor/cli/docs_command.rb +1 -2
  111. data/lib/rigor/cli/doctor_command.rb +12 -12
  112. data/lib/rigor/cli/effects_command.rb +50 -40
  113. data/lib/rigor/cli/effects_diff_renderer.rb +18 -17
  114. data/lib/rigor/cli/effects_explain_renderer.rb +13 -12
  115. data/lib/rigor/cli/effects_renderer.rb +2 -1
  116. data/lib/rigor/cli/effects_snapshot_command.rb +26 -18
  117. data/lib/rigor/cli/explain_command.rb +18 -8
  118. data/lib/rigor/cli/fused_protection_renderer.rb +2 -1
  119. data/lib/rigor/cli/json_document.rb +41 -0
  120. data/lib/rigor/cli/lens_command.rb +29 -10
  121. data/lib/rigor/cli/lsp_command.rb +250 -23
  122. data/lib/rigor/cli/mcp_command.rb +12 -7
  123. data/lib/rigor/cli/mutation_fork_scan.rb +1 -1
  124. data/lib/rigor/cli/mutation_protection_renderer.rb +3 -2
  125. data/lib/rigor/cli/options.rb +40 -1
  126. data/lib/rigor/cli/plugin_command.rb +93 -46
  127. data/lib/rigor/cli/plugins_command.rb +17 -18
  128. data/lib/rigor/cli/plugins_renderer.rb +10 -6
  129. data/lib/rigor/cli/protection_fork_scan.rb +2 -2
  130. data/lib/rigor/cli/protection_renderer.rb +2 -1
  131. data/lib/rigor/cli/show_bleedingedge_command.rb +21 -15
  132. data/lib/rigor/cli/sig_gen_command.rb +92 -27
  133. data/lib/rigor/cli/skill_command.rb +32 -3
  134. data/lib/rigor/cli/skill_deep_probe.rb +1 -1
  135. data/lib/rigor/cli/skill_describe.rb +2 -1
  136. data/lib/rigor/cli/trace_command.rb +14 -9
  137. data/lib/rigor/cli/triage_command.rb +10 -11
  138. data/lib/rigor/cli/triage_renderer.rb +2 -1
  139. data/lib/rigor/cli/type_of_command.rb +16 -11
  140. data/lib/rigor/cli/type_of_project_scope.rb +1 -4
  141. data/lib/rigor/cli/type_of_renderer.rb +4 -1
  142. data/lib/rigor/cli/type_scan_command.rb +14 -9
  143. data/lib/rigor/cli/type_scan_renderer.rb +2 -1
  144. data/lib/rigor/cli/unused_command.rb +27 -17
  145. data/lib/rigor/cli/upgrade_command.rb +5 -0
  146. data/lib/rigor/cli.rb +214 -56
  147. data/lib/rigor/config_audit.rb +33 -19
  148. data/lib/rigor/configuration/severity_profile.rb +14 -5
  149. data/lib/rigor/configuration.rb +104 -35
  150. data/lib/rigor/effects/collector.rb +53 -21
  151. data/lib/rigor/effects/definition_context.rb +0 -2
  152. data/lib/rigor/effects/envelope.rb +1 -1
  153. data/lib/rigor/effects/framework_units.rb +1 -1
  154. data/lib/rigor/effects/mutation_classifier.rb +4 -7
  155. data/lib/rigor/effects/propagator.rb +1 -1
  156. data/lib/rigor/effects/registry.rb +2 -2
  157. data/lib/rigor/effects/snapshot.rb +1 -1
  158. data/lib/rigor/effects/taint_cause.rb +0 -2
  159. data/lib/rigor/effects/unit_scan.rb +9 -13
  160. data/lib/rigor/environment/bundle_sig_discovery.rb +64 -33
  161. data/lib/rigor/environment/class_registry.rb +3 -3
  162. data/lib/rigor/environment/constant_type_cache_holder.rb +5 -0
  163. data/lib/rigor/environment/core_root.rb +77 -0
  164. data/lib/rigor/environment/default_libraries.rb +18 -1
  165. data/lib/rigor/environment/deferred_signature_plan.rb +381 -0
  166. data/lib/rigor/environment/gated_signature_guard.rb +1 -1
  167. data/lib/rigor/environment/gated_signature_plan.rb +5 -2
  168. data/lib/rigor/environment/hkt_registry_holder.rb +6 -0
  169. data/lib/rigor/environment/lockfile_resolver.rb +28 -12
  170. data/lib/rigor/environment/member_consistency/comparator.rb +18 -1
  171. data/lib/rigor/environment/member_consistency.rb +56 -7
  172. data/lib/rigor/environment/missing_gem_constant_index.rb +3 -2
  173. data/lib/rigor/environment/project_path_gems.rb +124 -0
  174. data/lib/rigor/environment/rbs_collection_discovery.rb +123 -8
  175. data/lib/rigor/environment/rbs_coverage_report.rb +12 -11
  176. data/lib/rigor/environment/rbs_hierarchy.rb +12 -15
  177. data/lib/rigor/environment/rbs_loader.rb +772 -110
  178. data/lib/rigor/environment/reflection.rb +7 -7
  179. data/lib/rigor/environment/required_features.rb +0 -3
  180. data/lib/rigor/environment/ruby_library_roots.rb +1 -1
  181. data/lib/rigor/environment/vendored_signature_plan.rb +153 -0
  182. data/lib/rigor/environment.rb +169 -42
  183. data/lib/rigor/flow_contribution/merger.rb +4 -4
  184. data/lib/rigor/inference/acceptance.rb +136 -40
  185. data/lib/rigor/inference/alias_mutation_floor/foreign_locals.rb +117 -0
  186. data/lib/rigor/inference/alias_mutation_floor/memos.rb +85 -0
  187. data/lib/rigor/inference/alias_mutation_floor/reach.rb +119 -0
  188. data/lib/rigor/inference/alias_mutation_floor/site_collector.rb +252 -0
  189. data/lib/rigor/inference/alias_mutation_floor.rb +339 -0
  190. data/lib/rigor/inference/anonymous_meta_class.rb +18 -0
  191. data/lib/rigor/inference/block_auto_splat.rb +1 -1
  192. data/lib/rigor/inference/block_parameter_binder.rb +2 -3
  193. data/lib/rigor/inference/block_run_count.rb +185 -0
  194. data/lib/rigor/inference/budget_trace.rb +8 -2
  195. data/lib/rigor/inference/builtins/array_catalog.rb +2 -2
  196. data/lib/rigor/inference/builtins/exception_catalog.rb +2 -2
  197. data/lib/rigor/inference/builtins/numeric_catalog.rb +2 -5
  198. data/lib/rigor/inference/builtins/random_catalog.rb +2 -2
  199. data/lib/rigor/inference/callee_mutation_chain.rb +88 -77
  200. data/lib/rigor/inference/callee_write_census.rb +815 -0
  201. data/lib/rigor/inference/captured_locals.rb +2 -0
  202. data/lib/rigor/inference/census_foreign_block.rb +354 -0
  203. data/lib/rigor/inference/clause_widening.rb +1 -1
  204. data/lib/rigor/inference/closure_escape_analyzer.rb +11 -4
  205. data/lib/rigor/inference/construction_escape.rb +258 -0
  206. data/lib/rigor/inference/declaration_walk/traversal.rb +1 -1
  207. data/lib/rigor/inference/declaration_walk.rb +4 -0
  208. data/lib/rigor/inference/deep_erasure.rb +39 -7
  209. data/lib/rigor/inference/def_handle.rb +1 -1
  210. data/lib/rigor/inference/def_node_resolver.rb +33 -15
  211. data/lib/rigor/inference/def_return_typer.rb +47 -5
  212. data/lib/rigor/inference/definer_resolution.rb +19 -9
  213. data/lib/rigor/inference/definers_index.rb +162 -0
  214. data/lib/rigor/inference/direct_ivar_writes.rb +300 -0
  215. data/lib/rigor/inference/element_read_widening.rb +49 -3
  216. data/lib/rigor/inference/error_info.rb +16 -0
  217. data/lib/rigor/inference/expression_typer.rb +1559 -320
  218. data/lib/rigor/inference/external_ancestor_resolution.rb +3 -4
  219. data/lib/rigor/inference/flow_tracer.rb +31 -14
  220. data/lib/rigor/inference/fork_map.rb +3 -0
  221. data/lib/rigor/inference/fresh_frame_blocks.rb +52 -1
  222. data/lib/rigor/inference/global_write_census.rb +81 -5
  223. data/lib/rigor/inference/global_writer_reach.rb +260 -0
  224. data/lib/rigor/inference/hkt_body.rb +1 -2
  225. data/lib/rigor/inference/hkt_body_parser.rb +3 -5
  226. data/lib/rigor/inference/hkt_reducer.rb +2 -2
  227. data/lib/rigor/inference/hkt_registry.rb +3 -5
  228. data/lib/rigor/inference/in_effect_refinements.rb +7 -0
  229. data/lib/rigor/inference/indexed_narrowing.rb +61 -15
  230. data/lib/rigor/inference/intervening_ivar_reset.rb +26 -4
  231. data/lib/rigor/inference/ivar_writer_census.rb +154 -8
  232. data/lib/rigor/inference/key_presence_guard.rb +51 -24
  233. data/lib/rigor/inference/last_line/self_evidence.rb +30 -0
  234. data/lib/rigor/inference/last_line.rb +5 -2
  235. data/lib/rigor/inference/loop_value_record.rb +66 -14
  236. data/lib/rigor/inference/match_rebinding/frame.rb +57 -0
  237. data/lib/rigor/inference/match_rebinding/yielding_match.rb +101 -0
  238. data/lib/rigor/inference/match_rebinding.rb +28 -5
  239. data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +1 -1
  240. data/lib/rigor/inference/method_dispatcher/argument_distribution.rb +40 -0
  241. data/lib/rigor/inference/method_dispatcher/block_folding.rb +44 -30
  242. data/lib/rigor/inference/method_dispatcher/class_keyed_block_params.rb +65 -0
  243. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +3 -3
  244. data/lib/rigor/inference/method_dispatcher/contested_overloads.rb +89 -0
  245. data/lib/rigor/inference/method_dispatcher/core_enumerable_receiver.rb +44 -0
  246. data/lib/rigor/inference/method_dispatcher/declared_constructor.rb +151 -0
  247. data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +1 -1
  248. data/lib/rigor/inference/method_dispatcher/imprecise_argument.rb +2 -2
  249. data/lib/rigor/inference/method_dispatcher/interface_shape.rb +181 -0
  250. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +1 -1
  251. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +1 -1
  252. data/lib/rigor/inference/method_dispatcher/no_match_fallback.rb +54 -0
  253. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +51 -27
  254. data/lib/rigor/inference/method_dispatcher/random_folding.rb +1 -1
  255. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +606 -78
  256. data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +1 -1
  257. data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +2 -2
  258. data/lib/rigor/inference/method_dispatcher/self_substitute.rb +3 -3
  259. data/lib/rigor/inference/method_dispatcher/set_folding.rb +9 -7
  260. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +467 -84
  261. data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +0 -1
  262. data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +50 -17
  263. data/lib/rigor/inference/method_dispatcher/singleton_type_params.rb +104 -0
  264. data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -5
  265. data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +4 -6
  266. data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
  267. data/lib/rigor/inference/method_dispatcher.rb +123 -25
  268. data/lib/rigor/inference/method_parameter_binder.rb +136 -56
  269. data/lib/rigor/inference/module_function_state/spellings.rb +2 -2
  270. data/lib/rigor/inference/module_function_state.rb +24 -3
  271. data/lib/rigor/inference/multi_target_binder.rb +2 -2
  272. data/lib/rigor/inference/mutation_rejoin.rb +240 -4
  273. data/lib/rigor/inference/mutation_widening.rb +199 -29
  274. data/lib/rigor/inference/narrowing.rb +238 -50
  275. data/lib/rigor/inference/operand_effects.rb +43 -2
  276. data/lib/rigor/inference/optimistic_origin.rb +134 -9
  277. data/lib/rigor/inference/origin_lookup.rb +1 -1
  278. data/lib/rigor/inference/out_buffer_mutation.rb +72 -0
  279. data/lib/rigor/inference/parameter_inference_collector.rb +5 -6
  280. data/lib/rigor/inference/pre_eval_constants.rb +1 -1
  281. data/lib/rigor/inference/precision_scanner.rb +1 -1
  282. data/lib/rigor/inference/project_method_ownership.rb +30 -9
  283. data/lib/rigor/inference/project_patched_methods.rb +65 -13
  284. data/lib/rigor/inference/project_patched_scanner.rb +120 -25
  285. data/lib/rigor/inference/project_patched_visibility.rb +39 -3
  286. data/lib/rigor/inference/project_yielder.rb +11 -17
  287. data/lib/rigor/inference/rbs_type_translator.rb +68 -15
  288. data/lib/rigor/inference/receiver_alias.rb +20 -0
  289. data/lib/rigor/inference/receiver_writer_call.rb +67 -0
  290. data/lib/rigor/inference/recursion_rebinding.rb +157 -0
  291. data/lib/rigor/inference/refined_dispatch/constructed_class.rb +57 -17
  292. data/lib/rigor/inference/refined_dispatch/own_method.rb +51 -16
  293. data/lib/rigor/inference/refined_dispatch.rb +13 -0
  294. data/lib/rigor/inference/reflective_ivar_write.rb +19 -11
  295. data/lib/rigor/inference/remover_holder_scan.rb +287 -0
  296. data/lib/rigor/inference/remover_narrowing.rb +224 -0
  297. data/lib/rigor/inference/rewrite_mutation.rb +53 -2
  298. data/lib/rigor/inference/scope_indexer/certainty.rb +0 -1
  299. data/lib/rigor/inference/scope_indexer/class_cvars_collector.rb +13 -6
  300. data/lib/rigor/inference/scope_indexer/constant_ivar_value.rb +93 -0
  301. data/lib/rigor/inference/scope_indexer/declared_param_writes.rb +70 -26
  302. data/lib/rigor/inference/scope_indexer/derived_param_value.rb +112 -0
  303. data/lib/rigor/inference/scope_indexer/empty_seed.rb +99 -0
  304. data/lib/rigor/inference/scope_indexer/ivar_contributions.rb +295 -0
  305. data/lib/rigor/inference/scope_indexer/mixin_accumulator.rb +136 -9
  306. data/lib/rigor/inference/scope_indexer.rb +2213 -226
  307. data/lib/rigor/inference/self_call_ivar_writes.rb +103 -12
  308. data/lib/rigor/inference/self_preserving_block.rb +87 -0
  309. data/lib/rigor/inference/set_mutation.rb +189 -0
  310. data/lib/rigor/inference/singleton_hook_decline.rb +42 -8
  311. data/lib/rigor/inference/singleton_object_constant.rb +32 -2
  312. data/lib/rigor/inference/statement_evaluator.rb +3268 -358
  313. data/lib/rigor/inference/string_mutation.rb +14 -0
  314. data/lib/rigor/inference/struct_fold_safety.rb +4 -6
  315. data/lib/rigor/inference/synthetic_method_scanner.rb +40 -17
  316. data/lib/rigor/inference/toplevel_def_census.rb +67 -0
  317. data/lib/rigor/inference/unknown_store_widening.rb +103 -4
  318. data/lib/rigor/inference/unthreaded_rebinds.rb +2 -3
  319. data/lib/rigor/inference/untyped_rejoin.rb +1 -1
  320. data/lib/rigor/inference/void_tail_summary.rb +29 -9
  321. data/lib/rigor/language_server/buffer_table.rb +3 -3
  322. data/lib/rigor/language_server/completion_provider.rb +26 -20
  323. data/lib/rigor/language_server/config_warning_announcer.rb +28 -0
  324. data/lib/rigor/language_server/diagnostic_publisher.rb +8 -3
  325. data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
  326. data/lib/rigor/language_server/folding_range_provider.rb +1 -2
  327. data/lib/rigor/language_server/hover_provider.rb +1 -7
  328. data/lib/rigor/language_server/hover_renderer.rb +6 -8
  329. data/lib/rigor/language_server/project_context.rb +39 -1
  330. data/lib/rigor/language_server/publish_batcher.rb +3 -4
  331. data/lib/rigor/language_server/selection_range_provider.rb +2 -4
  332. data/lib/rigor/language_server/server.rb +7 -3
  333. data/lib/rigor/language_server/signature_help_provider.rb +4 -4
  334. data/lib/rigor/lens/claims/comparison.rb +78 -0
  335. data/lib/rigor/lens/claims/request.rb +131 -0
  336. data/lib/rigor/lens/claims/type_reader.rb +216 -0
  337. data/lib/rigor/lens/claims.rb +208 -0
  338. data/lib/rigor/lens/contract_reader.rb +5 -0
  339. data/lib/rigor/lens/document.rb +1 -1
  340. data/lib/rigor/lens/file_reader.rb +21 -8
  341. data/lib/rigor/lens/plugins.rb +1 -1
  342. data/lib/rigor/lens/run.rb +8 -0
  343. data/lib/rigor/lens.rb +1 -1
  344. data/lib/rigor/library_probe.rb +68 -0
  345. data/lib/rigor/mcp/server.rb +73 -2
  346. data/lib/rigor/mcp.rb +1 -1
  347. data/lib/rigor/memo_audit.rb +282 -0
  348. data/lib/rigor/plugin/access_denied_error.rb +1 -2
  349. data/lib/rigor/plugin/base.rb +15 -2
  350. data/lib/rigor/plugin/bundled_catalog.rb +1 -12
  351. data/lib/rigor/plugin/io_boundary.rb +26 -4
  352. data/lib/rigor/plugin/loader.rb +25 -8
  353. data/lib/rigor/plugin/macro/heredoc_template.rb +7 -8
  354. data/lib/rigor/plugin/macro/trait_registry.rb +6 -9
  355. data/lib/rigor/plugin/manifest.rb +16 -16
  356. data/lib/rigor/plugin/registry.rb +16 -5
  357. data/lib/rigor/plugin/services.rb +2 -3
  358. data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -0
  359. data/lib/rigor/plugin/trust_policy.rb +48 -2
  360. data/lib/rigor/plugin/type_node_resolver.rb +2 -4
  361. data/lib/rigor/plugin.rb +6 -8
  362. data/lib/rigor/plugin_gap_advisory.rb +5 -1
  363. data/lib/rigor/project_environment.rb +16 -2
  364. data/lib/rigor/protection/analysis_guard.rb +1 -1
  365. data/lib/rigor/protection/discovery_seed.rb +44 -5
  366. data/lib/rigor/protection/mutation_cache.rb +4 -1
  367. data/lib/rigor/protection/mutator.rb +1 -1
  368. data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
  369. data/lib/rigor/rbs_extended/hkt_directives.rb +6 -10
  370. data/lib/rigor/rbs_extended/reporter.rb +27 -3
  371. data/lib/rigor/rbs_extended.rb +2 -3
  372. data/lib/rigor/reflection/constant_ancestors.rb +81 -22
  373. data/lib/rigor/reflection/declaration_collectors.rb +55 -0
  374. data/lib/rigor/reflection/declarations.rb +58 -0
  375. data/lib/rigor/reflection/project_method.rb +177 -0
  376. data/lib/rigor/reflection.rb +2 -0
  377. data/lib/rigor/rooted_glob.rb +32 -1
  378. data/lib/rigor/run_scoped_slots.rb +38 -0
  379. data/lib/rigor/runtime/jit.rb +1 -1
  380. data/lib/rigor/scope/discovery_index.rb +168 -8
  381. data/lib/rigor/scope/resolution_chain/relevance.rb +14 -1
  382. data/lib/rigor/scope/resolution_chain.rb +901 -54
  383. data/lib/rigor/scope.rb +644 -37
  384. data/lib/rigor/sig_gen/bot_proposal_guard.rb +306 -0
  385. data/lib/rigor/sig_gen/classification.rb +18 -1
  386. data/lib/rigor/sig_gen/effect_annotation.rb +3 -3
  387. data/lib/rigor/sig_gen/generator.rb +588 -66
  388. data/lib/rigor/sig_gen/generic_header_scan.rb +189 -0
  389. data/lib/rigor/sig_gen/inline_declarations.rb +2 -2
  390. data/lib/rigor/sig_gen/layout_index.rb +3 -3
  391. data/lib/rigor/sig_gen/method_candidate.rb +37 -4
  392. data/lib/rigor/sig_gen/observation_collector.rb +14 -7
  393. data/lib/rigor/sig_gen/observed_call.rb +1 -1
  394. data/lib/rigor/sig_gen/path_mapper.rb +6 -0
  395. data/lib/rigor/sig_gen/platform_guarded_files.rb +184 -0
  396. data/lib/rigor/sig_gen/renderer.rb +15 -9
  397. data/lib/rigor/sig_gen/skip_reason_catalog.rb +62 -2
  398. data/lib/rigor/sig_gen/type_name_qualification.rb +69 -0
  399. data/lib/rigor/sig_gen/write_reporter.rb +63 -14
  400. data/lib/rigor/sig_gen/write_result.rb +23 -12
  401. data/lib/rigor/sig_gen/writer.rb +238 -37
  402. data/lib/rigor/sig_gen.rb +1 -0
  403. data/lib/rigor/source/forwardable_delegators.rb +122 -0
  404. data/lib/rigor/source/node_children.rb +13 -0
  405. data/lib/rigor/type/acceptance_router.rb +2 -2
  406. data/lib/rigor/type/accepts_result.rb +1 -1
  407. data/lib/rigor/type/app.rb +4 -6
  408. data/lib/rigor/type/combinator.rb +173 -21
  409. data/lib/rigor/type/constant.rb +4 -5
  410. data/lib/rigor/type/hash_shape.rb +21 -40
  411. data/lib/rigor/type/interface.rb +60 -0
  412. data/lib/rigor/type/union.rb +1 -1
  413. data/lib/rigor/type.rb +1 -0
  414. data/lib/rigor/type_node/identifier.rb +1 -2
  415. data/lib/rigor/type_node/resolver_chain.rb +1 -1
  416. data/lib/rigor/type_node/string_literal.rb +1 -2
  417. data/lib/rigor/type_node/symbol_literal.rb +1 -2
  418. data/lib/rigor/type_node/union.rb +3 -6
  419. data/lib/rigor/type_of_memo/serving.rb +99 -0
  420. data/lib/rigor/type_of_memo/stats.rb +43 -0
  421. data/lib/rigor/type_of_memo.rb +337 -0
  422. data/lib/rigor/typing_state.rb +1094 -0
  423. data/lib/rigor/value_semantics.rb +1 -10
  424. data/lib/rigor/version.rb +1 -1
  425. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +2 -2
  426. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +2 -3
  427. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +1 -1
  428. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +38 -36
  429. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +4 -2
  430. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +6 -4
  431. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +1 -1
  432. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -5
  433. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +0 -1
  434. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +2 -1
  435. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +3 -3
  436. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +115 -36
  437. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +3 -6
  438. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +25 -1
  439. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -1
  440. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +16 -6
  441. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +4 -2
  442. data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +4 -3
  443. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +2 -1
  444. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/association_roots.rb +3 -2
  445. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +2 -2
  446. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +21 -31
  447. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +10 -16
  448. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +132 -33
  449. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +20 -6
  450. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +7 -4
  451. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +54 -17
  452. data/plugins/rigor-activerecord/sig/active_record/relation.rbs +19 -5
  453. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +3 -4
  454. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +1 -1
  455. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +11 -14
  456. data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +1 -1
  457. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +1 -1
  458. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/symbolize_keys.rb +102 -0
  459. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +30 -9
  460. data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +55 -13
  461. data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_collector.rb +15 -21
  462. data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_discoverer.rb +1 -6
  463. data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_index.rb +3 -3
  464. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +1 -3
  465. data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +6 -6
  466. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +5 -6
  467. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +1 -1
  468. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/params_shape.rb +2 -3
  469. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +5 -8
  470. data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +0 -1
  471. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +1 -1
  472. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +10 -18
  473. data/plugins/rigor-ffi/lib/rigor/plugin/ffi/analyzer.rb +0 -1
  474. data/plugins/rigor-ffi/lib/rigor/plugin/ffi/discoverer.rb +0 -2
  475. data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +8 -7
  476. data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +0 -2
  477. data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +6 -7
  478. data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +12 -2
  479. data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +2 -4
  480. data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +2 -5
  481. data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +8 -2
  482. data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +6 -6
  483. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +2 -1
  484. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +3 -8
  485. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +2 -3
  486. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +5 -8
  487. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +200 -4
  488. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +2 -3
  489. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +1 -1
  490. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +4 -11
  491. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +4 -3
  492. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +2 -1
  493. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +5 -5
  494. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +2 -2
  495. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +3 -4
  496. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +6 -8
  497. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +3 -2
  498. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +4 -5
  499. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +6 -7
  500. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +210 -3
  501. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +146 -7
  502. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +2 -2
  503. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +52 -34
  504. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +97 -24
  505. data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +2 -3
  506. data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_collector.rb +16 -16
  507. data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_discoverer.rb +4 -8
  508. data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_index.rb +4 -4
  509. data/sig/rigor/analysis/baseline.rbs +0 -3
  510. data/sig/rigor/analysis/check_rules/rule_walk.rbs +6 -0
  511. data/sig/rigor/analysis/fact_store.rbs +2 -2
  512. data/sig/rigor/analysis/reachability/scan_cache.rbs +1 -1
  513. data/sig/rigor/cache/descriptor.rbs +14 -0
  514. data/sig/rigor/cli/diff_command.rbs +1 -1
  515. data/sig/rigor/cli/explain_command.rbs +1 -1
  516. data/sig/rigor/effects/registry.rbs +2 -2
  517. data/sig/rigor/environment.rbs +4 -1
  518. data/sig/rigor/inference.rbs +4 -1
  519. data/sig/rigor/plugin/additional_initializer.rbs +0 -5
  520. data/sig/rigor/plugin/base.rbs +53 -18
  521. data/sig/rigor/plugin/effect_attribution.rbs +3 -3
  522. data/sig/rigor/plugin/effect_edge.rbs +1 -1
  523. data/sig/rigor/plugin/effect_entry_points.rbs +3 -3
  524. data/sig/rigor/plugin/interfaces.rbs +51 -0
  525. data/sig/rigor/plugin/io_boundary.rbs +3 -3
  526. data/sig/rigor/plugin/manifest.rbs +9 -9
  527. data/sig/rigor/plugin/node_context.rbs +21 -0
  528. data/sig/rigor/plugin/protocol_contract.rbs +3 -7
  529. data/sig/rigor/reflection.rbs +37 -0
  530. data/sig/rigor/scope.rbs +43 -4
  531. data/sig/rigor/trinary.rbs +1 -0
  532. data/sig/rigor/type.rbs +9 -3
  533. data/sig/rigor.rbs +3 -2
  534. data/skills/rigor-ask/SKILL.md +1 -0
  535. data/skills/rigor-plugin-author/SKILL.md +4 -4
  536. data/skills/rigor-plugin-author/references/02-walker-and-types.md +5 -5
  537. data/skills/rigor-plugin-review/SKILL.md +3 -3
  538. data/skills/rigor-project-init/references/01-detect.md +1 -0
  539. data/skills/rigor-project-init/references/03-baseline-and-bugs.md +17 -2
  540. data/skills/rigor-project-init/references/06-agent-contract.md +4 -4
  541. data/skills/rigor-rbs-contract/SKILL.md +147 -0
  542. data/skills/rigor-rbs-contract/references/01-finding-candidates.md +212 -0
  543. data/skills/rigor-rbs-contract/references/02-contract-rules.md +157 -0
  544. data/skills/rigor-rbs-contract/references/03-target-own-code.md +90 -0
  545. data/skills/rigor-rbs-contract/references/04-target-gem-rbs-collection.md +210 -0
  546. data/skills/rigor-rbs-contract/references/05-declaration-mutants.md +182 -0
  547. data/skills/rigor-rbs-setup/SKILL.md +3 -1
  548. data/skills/rigor-type-oracle/SKILL.md +26 -1
  549. data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +4 -3
  550. metadata +82 -3
@@ -3,6 +3,7 @@
3
3
  require_relative "../check_rules/rule_ids"
4
4
  require_relative "../crash_signature"
5
5
  require_relative "../diagnostic"
6
+ require_relative "../run_cache_key"
6
7
  require_relative "../severity_stamp"
7
8
 
8
9
  module Rigor
@@ -29,35 +30,24 @@ module Rigor
29
30
  # @param pool_mode — reader returning the pool-mode flag.
30
31
  # @param cached_plugin_prepare_diagnostics — reader returning the prepare-diagnostic snapshot.
31
32
  # @param pre_eval_diagnostics_from_scanner — reader returning the pre-eval scanner diagnostics.
32
- # @param synthesized_namespaces_snapshot — reader.
33
- # @param quarantined_signatures_snapshot — reader returning the `signature_paths:` files skipped
34
- # because they do not parse (`[path, first_error_line]` pairs).
35
- # @param signature_standdowns_snapshot — reader returning the plugin-contributed signature files
36
- # that stood down against a colliding generic arity (#610), as
37
- # `[path, class_name, existing_arity, incoming_arity, existing_file]` tuples. Defaults to none so
38
- # a caller that snapshots nothing of the kind need not say so.
39
- # @param vendored_standdowns_snapshot — issue #1713 — reader returning what each required-feature-gated
40
- # vendored directory left out (`Environment::RbsLoader#vendored_standdowns`). Defaults to none.
41
- # @param env_build_failure_snapshot — reader returning the total RBS env-build failure tuple
42
- # (`[error_class, first_error_line, conflicting_buffer_names]`) or nil when the env built.
43
- # @param definition_build_failures_snapshot — issue #696 — reader returning the per-class
44
- # `RBS::DefinitionBuilder` failures the run observed, as `[class_name, error_class, member,
45
- # conflicting_buffer_names, unresolved_type_name_detail]` tuples (issue #997 added the fifth
46
- # element — `[token, location, refinement_hint]`, `nil` unless `error_class` is
47
- # `RBS::NoTypeFoundError`). Empty for a healthy sig set.
48
- # @param hkt_scan_failure_snapshot — issue #784 — reader returning the `[error_class_name,
49
- # first_message_line, raw_frame_or_nil, stage]` tuple whichever stage of the HKT-registry build
50
- # raised, or nil when both built (or were never demanded). `stage` is `:scan` (the RBS `type`-alias
51
- # scan) or `:overlay` (the plugin-manifest aggregation, #791), and picks the row's wording.
52
- # @param conformance_results_snapshot — reader.
33
+ # @param snapshots — the run's {RunSnapshots} store (ADR-116 WD3), read at row-build time. Its slots'
34
+ # shapes, as the rows below read them:
35
+ # - `quarantined_signatures` — the `signature_paths:` files skipped because they do not parse
36
+ # (`[path, first_error_line]` pairs);
37
+ # - `signature_standdowns` (#610) — `[path, class_name, existing_arity, incoming_arity,
38
+ # existing_file]` tuples, then (#2422) `[path, declaration, nil, nil, cause_file, :member]` ones;
39
+ # - `vendored_standdowns` (#1713) — `Environment::RbsLoader#vendored_standdowns`;
40
+ # - `env_build_failure` — `[error_class, first_error_line, conflicting_buffer_names]`, or nil;
41
+ # - `definition_build_failures` (#696) — `[class_name, error_class, member,
42
+ # conflicting_buffer_names, unresolved_type_name_detail, mixin_count]` tuples (#997 added the fifth
43
+ # element — `[token, location, refinement_hint]`, `nil` unless `error_class` is
44
+ # `RBS::NoTypeFoundError`; #2440 the sixth, {Environment::RbsLoader#variable_mixin_count});
45
+ # - `hkt_scan_failure` (#784) — `[error_class_name, first_message_line, raw_frame_or_nil, stage]`,
46
+ # or nil; `stage` is `:scan` or `:overlay` (#791) and picks the row's wording.
53
47
  def initialize(configuration:, rbs_extended_reporter:, boundary_cross_reporter:, # rubocop:disable Metrics/ParameterLists
54
48
  source_rbs_synthesis_reporter:, plugin_registry:, dependency_source_index:,
55
49
  pool_mode:, cached_plugin_prepare_diagnostics:,
56
- pre_eval_diagnostics_from_scanner:, synthesized_namespaces_snapshot:,
57
- quarantined_signatures_snapshot:, env_build_failure_snapshot:,
58
- definition_build_failures_snapshot:, hkt_scan_failure_snapshot:,
59
- conformance_results_snapshot:, signature_standdowns_snapshot: -> { [] },
60
- vendored_standdowns_snapshot: -> { [] }, pooled_run_disclosures: -> { [] },
50
+ pre_eval_diagnostics_from_scanner:, snapshots:, pooled_run_disclosures: -> { [] },
61
51
  served_run_disclosures: -> { [] }, pooled_trust_refusals: -> { [] })
62
52
  @configuration = configuration
63
53
  @rbs_extended_reporter = rbs_extended_reporter
@@ -68,14 +58,7 @@ module Rigor
68
58
  @pool_mode_reader = pool_mode
69
59
  @cached_plugin_prepare_diagnostics_reader = cached_plugin_prepare_diagnostics
70
60
  @pre_eval_diagnostics_from_scanner_reader = pre_eval_diagnostics_from_scanner
71
- @synthesized_namespaces_snapshot_reader = synthesized_namespaces_snapshot
72
- @quarantined_signatures_snapshot_reader = quarantined_signatures_snapshot
73
- @signature_standdowns_snapshot_reader = signature_standdowns_snapshot
74
- @vendored_standdowns_snapshot_reader = vendored_standdowns_snapshot
75
- @env_build_failure_snapshot_reader = env_build_failure_snapshot
76
- @definition_build_failures_snapshot_reader = definition_build_failures_snapshot
77
- @hkt_scan_failure_snapshot_reader = hkt_scan_failure_snapshot
78
- @conformance_results_snapshot_reader = conformance_results_snapshot
61
+ @snapshots = snapshots
79
62
  # Issue #1051 — reader for the pool coordinator's de-duplicated run-scoped disclosure table.
80
63
  # Empty on a sequential run, where `plugin_registry`'s own instances are the ones that registered.
81
64
  @pooled_run_disclosures_reader = pooled_run_disclosures
@@ -86,6 +69,14 @@ module Rigor
86
69
  @pooled_trust_refusals_reader = pooled_trust_refusals
87
70
  end
88
71
 
72
+ # ADR-116 WD3 — every post-analysis run-level row, in the contract order {RunLevelFacts.row_builders}
73
+ # declares: the `rbs.coverage.*` build-failure ladder widest consequence first, its `:info` notices,
74
+ # the conformance rows, the reporter streams, then the plugin run disclosures and the trust-refusal
75
+ # envelope, read last so every per-file plugin call has recorded its refusals.
76
+ def run_level_diagnostics
77
+ RunLevelFacts.row_builders.flat_map { |builder| public_send(builder) }
78
+ end
79
+
89
80
  # Pre-file diagnostic streams that fire once per run rather than per analyzed file: plugin load /
90
81
  # prepare envelopes, the ADR-10 dependency-source resolution surface, and the `expand_paths` errors
91
82
  # for `paths:` entries that don't exist or aren't `.rb`. Aggregated here so `#run` stays under the
@@ -94,9 +85,9 @@ module Rigor
94
85
  # ADR-15 Phase 4b — `plugin_prepare_diagnostics` runs on the coordinator's plugin registry under
95
86
  # sequential mode; under pool mode each worker re-runs `prepare` against its own plugin instances,
96
87
  # so the pool path drains the first worker's prepare-diagnostic snapshot into the aggregated
97
- # diagnostic stream instead (see {#analyze_files_in_pool}). Skipping the coordinator prepare in pool
98
- # mode avoids double-running `#prepare` against the coordinator-side plugin instances (which the
99
- # pool path never consults for per-file analysis).
88
+ # diagnostic stream instead (see {PoolCoordinator#analyze_files_in_pool}). Skipping the coordinator
89
+ # prepare in pool mode avoids double-running `#prepare` against the coordinator-side plugin instances
90
+ # (which the pool path never consults for per-file analysis).
100
91
  def pre_file_diagnostics(expansion)
101
92
  # ADR-18 slice 3 — prepare diagnostics are captured earlier in #run (before the synthetic-method
102
93
  # scanner) so cross-plugin facts are available to the scanner. We re-surface the captured
@@ -109,6 +100,7 @@ module Rigor
109
100
  dependency_source_budget_diagnostics +
110
101
  dependency_source_config_conflict_diagnostics +
111
102
  rbs_coverage_diagnostics +
103
+ rbs_collection_setup_hint_diagnostics +
112
104
  rbs_inline_annotation_hint_diagnostics(expansion) +
113
105
  expansion.fetch(:errors)
114
106
  end
@@ -125,7 +117,7 @@ module Rigor
125
117
  next if File.file?(path)
126
118
 
127
119
  Diagnostic.new(
128
- path: ".rigor.yml", line: 1, column: 1,
120
+ path: @configuration.config_display_path, line: 1, column: 1,
129
121
  message: "pre_eval entry not found: #{path.inspect}. " \
130
122
  "Pre-evaluation requires the file to exist on disk; remove the entry " \
131
123
  "or create the file before re-running analysis.",
@@ -173,7 +165,7 @@ module Rigor
173
165
  def plugin_load_diagnostics
174
166
  plugin_registry.load_errors.map do |error|
175
167
  Diagnostic.new(
176
- path: ".rigor.yml",
168
+ path: @configuration.config_display_path,
177
169
  line: 1,
178
170
  column: 1,
179
171
  message: plugin_load_error_message(error),
@@ -202,7 +194,7 @@ module Rigor
202
194
  def dependency_source_diagnostics
203
195
  dependency_source_index.unresolvable.map do |entry|
204
196
  Diagnostic.new(
205
- path: ".rigor.yml",
197
+ path: @configuration.config_display_path,
206
198
  line: 1,
207
199
  column: 1,
208
200
  message: "dependencies.source_inference[].gem #{entry.gem_name.inspect} could not be " \
@@ -227,7 +219,7 @@ module Rigor
227
219
  def dependency_source_config_conflict_diagnostics
228
220
  @configuration.dependencies.warnings.map do |message|
229
221
  Diagnostic.new(
230
- path: ".rigor.yml",
222
+ path: @configuration.config_display_path,
231
223
  line: 1,
232
224
  column: 1,
233
225
  message: message,
@@ -242,7 +234,7 @@ module Rigor
242
234
  budget = @configuration.dependencies.budget_per_gem
243
235
  dependency_source_index.budget_exceeded.map do |gem_name|
244
236
  Diagnostic.new(
245
- path: ".rigor.yml",
237
+ path: @configuration.config_display_path,
246
238
  line: 1,
247
239
  column: 1,
248
240
  message: "dependencies.source_inference[].gem #{gem_name.inspect} exceeded the per-gem " \
@@ -258,7 +250,8 @@ module Rigor
258
250
 
259
251
  # O4 Layer 3 slice 3 — graceful-degradation coverage report. When the project has a `Gemfile.lock`
260
252
  # (slice 1) and one or more locked gems are not covered by ANY of the four RBS resolution paths
261
- # (`DEFAULT_LIBRARIES`, `data/vendored_gem_sigs/`, slice-1 bundle-shipped `sig/`, slice-2
253
+ # (the resolved library list — `DEFAULT_LIBRARIES` + `libraries:` + the collection lockfile's stdlib
254
+ # entries, `data/vendored_gem_sigs/`, slice-1 bundle-shipped `sig/`, slice-2
262
255
  # `rbs_collection.lock.yaml`), emit a single `:info` diagnostic summarising the uncovered set so the
263
256
  # user can act on it (run `rbs collection install`, opt the gem into `dependencies.source_inference:`,
264
257
  # or accept the `Dynamic[T]` fallback).
@@ -271,6 +264,9 @@ module Rigor
271
264
  project_root: Dir.pwd,
272
265
  auto_detect: @configuration.bundler_auto_detect
273
266
  )
267
+ # Issue #2441 — the project's own path gems are not dependencies missing RBS; the environment skips
268
+ # their collection copy, so the same set leaves the report here.
269
+ locked = locked.except(*project_own_gem_names(locked))
274
270
  return [] if locked.empty?
275
271
 
276
272
  bundle_sig_paths = Environment::BundleSigDiscovery.discover(
@@ -286,7 +282,7 @@ module Rigor
286
282
  )
287
283
  rows = Environment::RbsCoverageReport.classify(
288
284
  locked_gems: locked,
289
- default_libraries: Environment::DEFAULT_LIBRARIES,
285
+ default_libraries: resolved_default_libraries,
290
286
  bundle_sig_paths: bundle_sig_paths,
291
287
  rbs_collection_paths: collection_paths
292
288
  )
@@ -296,6 +292,65 @@ module Rigor
296
292
  [build_rbs_coverage_missing_diagnostic(missing)]
297
293
  end
298
294
 
295
+ # Issue #3030 — one `:info` when the run found no `rbs_collection.lock.yaml` but the directory looks set up for
296
+ # one ({Environment::RbsCollectionDiscovery.missing_lockfile_hint}): the dependency RBS a collection would
297
+ # load is absent, and Rigor does not resolve it from `manifest.yaml` or a gemspec itself.
298
+ def rbs_collection_setup_hint_diagnostics
299
+ # The run-result key and the `--incremental` fingerprint carry the same answer ({RunCacheKey}).
300
+ hint = RunCacheKey.collection_setup_hint(@configuration)
301
+ return [] if hint.nil?
302
+
303
+ [build_rbs_collection_setup_hint_diagnostic(hint)]
304
+ end
305
+
306
+ RBS_COLLECTION_SETUP_STEPS = {
307
+ collection_test_dir: "This looks like a gem_rbs_collection test directory: run the collection's " \
308
+ "`bin/test` setup for this gem first (it writes the lockfile and " \
309
+ "`.gem_rbs_collection/`), then run Rigor here again.",
310
+ collection_config: "An `rbs_collection.yaml` is here: run `rbs collection install` to write the " \
311
+ "lockfile, then run Rigor again."
312
+ }.freeze
313
+ private_constant :RBS_COLLECTION_SETUP_STEPS
314
+
315
+ def build_rbs_collection_setup_hint_diagnostic(hint)
316
+ Diagnostic.new(
317
+ path: @configuration.config_display_path,
318
+ line: 1,
319
+ column: 1,
320
+ message: "No `rbs_collection.lock.yaml` was found, so no `rbs collection` RBS was loaded: the signatures " \
321
+ "of this directory's gem dependencies are absent and calls into them read `Dynamic[top]`. " \
322
+ "#{RBS_COLLECTION_SETUP_STEPS.fetch(hint)}",
323
+ severity: :info,
324
+ rule: "rbs.coverage.collection-not-installed",
325
+ source_family: :builtin
326
+ )
327
+ end
328
+
329
+ # Issue #2962 — the library list is {Environment::BaseLibraries.resolve}'s, the same merge
330
+ # `Environment.for_project` loads, so a gem covered through `libraries:` or a lockfile stdlib
331
+ # entry is not reported missing. Only the names the environment loads count ({LibraryProbe.loadable}): a
332
+ # locked gem named there that RBS has no library for is still missing.
333
+ def resolved_default_libraries
334
+ resolved = Environment::BaseLibraries.resolve(
335
+ @configuration.libraries,
336
+ rbs_collection_lockfile: @configuration.rbs_collection_lockfile,
337
+ rbs_collection_auto_detect: @configuration.rbs_collection_auto_detect,
338
+ root: Dir.pwd
339
+ )
340
+ LibraryProbe.loadable(resolved)
341
+ end
342
+ private :resolved_default_libraries
343
+
344
+ # Issue #2441 — the same project-own set `Environment.for_project` skips the collection copy of.
345
+ def project_own_gem_names(locked)
346
+ Environment::ProjectPathGems.names(
347
+ locked,
348
+ paths: @configuration.paths, root: Dir.pwd,
349
+ exclude_patterns: @configuration.exclude_patterns, exclude_base: @configuration.exclude_base
350
+ )
351
+ end
352
+ private :project_own_gem_names
353
+
299
354
  # ADR-93 WD3 — the standalone residual. A bare `gem install rigortype` has no `rbs-inline` library,
300
355
  # so the spec's "annotations are official type sources whenever present" cannot be satisfied: the
301
356
  # annotated code reads `Dynamic[top]`. When the library is absent AND the project actually carries
@@ -342,7 +397,7 @@ module Rigor
342
397
 
343
398
  def build_rbs_inline_unsynthesized_diagnostic(sample_path)
344
399
  Diagnostic.new(
345
- path: ".rigor.yml",
400
+ path: @configuration.config_display_path,
346
401
  line: 1,
347
402
  column: 1,
348
403
  message: "Inline rbs-inline annotations (`# @rbs …`, `#: <type>`) are present in your project " \
@@ -379,7 +434,7 @@ module Rigor
379
434
  # the `reject-unparseable-signatures` feature promotes this rule to `:error` for anyone who opts in
380
435
  # (and by default at the next major).
381
436
  def rbs_quarantined_signature_diagnostics
382
- quarantined = quarantined_signatures_snapshot
437
+ quarantined = @snapshots[:quarantined_signatures]
383
438
  return [] if quarantined.empty?
384
439
 
385
440
  [build_rbs_quarantined_signature_diagnostic(quarantined)]
@@ -400,7 +455,7 @@ module Rigor
400
455
  # `reject-unparseable-signatures` bleeding-edge feature promotes it to `:error` for anyone who opts in
401
456
  # (and by default at the next major).
402
457
  def rbs_environment_build_failed_diagnostics
403
- failure = env_build_failure_snapshot
458
+ failure = @snapshots[:env_build_failure]
404
459
  return [] if failure.nil?
405
460
 
406
461
  [build_rbs_environment_build_failed_diagnostic(failure)]
@@ -426,7 +481,7 @@ module Rigor
426
481
  # a Rigor release turn a green build red with no user change (ADR-5 / AGENTS.md § FP discipline).
427
482
  # The `reject-unparseable-signatures` bleeding-edge feature promotes it to `:error`.
428
483
  def rbs_definition_build_failed_diagnostics
429
- failures = definition_build_failures_snapshot
484
+ failures = @snapshots[:definition_build_failures]
430
485
  return [] if failures.nil? || failures.empty?
431
486
 
432
487
  [build_rbs_definition_build_failed_diagnostic(failures)]
@@ -445,14 +500,14 @@ module Rigor
445
500
  # surface, no signature file is skipped, the environment builds. That is why this sits LAST on the
446
501
  # ladder, after its two `rbs.coverage.*` siblings above.
447
502
  def rbs_hkt_scan_failed_diagnostics
448
- failure = hkt_scan_failure_snapshot
503
+ failure = @snapshots[:hkt_scan_failure]
449
504
  return [] if failure.nil?
450
505
 
451
506
  [build_rbs_hkt_scan_failed_diagnostic(failure)]
452
507
  end
453
508
 
454
509
  def rbs_synthesized_namespace_diagnostics
455
- synthesized = synthesized_namespaces_snapshot
510
+ synthesized = @snapshots[:synthesized_namespaces]
456
511
  return [] if synthesized.nil? || synthesized.empty?
457
512
 
458
513
  [build_rbs_synthesized_namespace_diagnostic(synthesized)]
@@ -465,10 +520,12 @@ module Rigor
465
520
  # typing they are not getting and why, and — unlike the quarantine row this file used to be
466
521
  # misreported as — is not sent to remove a declaration the plugin owns.
467
522
  def rbs_plugin_signature_stood_down_diagnostics
468
- standdowns = signature_standdowns_snapshot
523
+ standdowns = @snapshots[:signature_standdowns]
469
524
  return [] if standdowns.nil? || standdowns.empty?
470
525
 
471
- standdowns.map { |entry| build_rbs_plugin_signature_stood_down_diagnostic(entry) }
526
+ members, files = standdowns.partition { |entry| entry[5] == :member }
527
+ files.map { |entry| build_rbs_plugin_signature_stood_down_diagnostic(entry) } +
528
+ members.group_by(&:first).map { |path, rows| build_rbs_plugin_member_stood_down_diagnostic(path, rows) }
472
529
  end
473
530
 
474
531
  # Issue #1713 — the other outcome that avoided a definition-build failure: a required-feature-gated
@@ -476,7 +533,7 @@ module Rigor
476
533
  # declares — a member, a whole type, or, when nothing narrower built, the directory. One `:info` per
477
534
  # directory, naming the declarations that stood down and the files that displaced them.
478
535
  def rbs_vendored_signature_stood_down_diagnostics
479
- standdowns = vendored_standdowns_snapshot
536
+ standdowns = @snapshots[:vendored_standdowns]
480
537
  return [] if standdowns.nil? || standdowns.empty?
481
538
 
482
539
  standdowns.map { |entry| build_rbs_vendored_signature_stood_down_diagnostic(entry) }
@@ -498,7 +555,7 @@ module Rigor
498
555
  # conformance; every analysis path, pooled or degraded, takes the snapshot `synthesized_namespaces`
499
556
  # comes from.
500
557
  def conforms_to_diagnostics
501
- results = conformance_results_snapshot
558
+ results = @snapshots[:conformance_results]
502
559
  return [] if results.nil? || results.empty?
503
560
 
504
561
  results.map { |record| build_conformance_diagnostic(record) }
@@ -570,7 +627,7 @@ module Rigor
570
627
  sample = quarantined.first(sample_size).map { |path, _first_line| relative_signature_path(path) }
571
628
  suffix = quarantined.size > sample_size ? ", and #{quarantined.size - sample_size} more" : ""
572
629
  Diagnostic.new(
573
- path: ".rigor.yml",
630
+ path: @configuration.config_display_path,
574
631
  line: 1,
575
632
  column: 1,
576
633
  message: "#{quarantined.size} RBS file(s) under `signature_paths:` were SKIPPED " \
@@ -593,7 +650,7 @@ module Rigor
593
650
  suffix = files.size > sample_size ? ", and #{files.size - sample_size} more" : ""
594
651
  conflicts = sample.empty? ? "" : " Conflicting signature file(s): #{sample.join(', ')}#{suffix}."
595
652
  Diagnostic.new(
596
- path: ".rigor.yml",
653
+ path: @configuration.config_display_path,
597
654
  line: 1,
598
655
  column: 1,
599
656
  message: "The RBS environment failed to build (#{error_class}): #{first_line}.#{conflicts} " \
@@ -630,9 +687,9 @@ module Rigor
630
687
  failures = failures.sort_by { |failure| failure.first.to_s }
631
688
  sample_size = 5
632
689
  files = failures.flat_map { |failure| Array(failure[3]) }
633
- .map { |name| relative_signature_path(name) }.uniq.sort
690
+ .map { |name| signature_source_label(name.to_s) }.uniq.sort
634
691
  Diagnostic.new(
635
- path: ".rigor.yml",
692
+ path: @configuration.config_display_path,
636
693
  line: 1,
637
694
  column: 1,
638
695
  message: "#{failures.size} RBS class definition(s) failed to build: " \
@@ -641,32 +698,120 @@ module Rigor
641
698
  "Rigor still treats each class as KNOWN, so calls into it — real methods and typos " \
642
699
  "alike — silently read `Dynamic[top]` instead of resolving, and this run is quieter " \
643
700
  "than it should be rather than cleaner. #{definition_build_advice(failures.first)}",
644
- severity: :warning,
701
+ severity: selected_core_failure?(failures) ? :error : :warning,
645
702
  rule: "rbs.coverage.definition-build-failed",
646
703
  source_family: :builtin
647
704
  )
648
705
  end
649
706
 
707
+ # Issue #2517 — a class that does not build from the selected `core_root:` alone is that explicit choice
708
+ # failing, not a Rigor release disagreeing with the user's `sig/`, so it is an error. A failure that also
709
+ # names a file outside the core (a project `sig/` collision) keeps the warning it has without one.
710
+ def selected_core_failure?(failures)
711
+ core_root = @configuration.core_root
712
+ return false if core_root.nil?
713
+
714
+ prefix = File.join(core_root, "")
715
+ failures.any? do |failure|
716
+ buffers = Array(failure[3]).map(&:to_s)
717
+ !buffers.empty? && buffers.all? { |name| name.start_with?(prefix) }
718
+ end
719
+ end
720
+
650
721
  # The closing advice follows the FIRST failure's error class: `GenericParameterMismatchError` is two
651
722
  # declarations of one CLASS at different generic arity (#610); `NoTypeFoundError` (issue #997) is
652
723
  # ONE declaration naming a type that does not exist, which "remove the duplicate declaration" sends
653
724
  # its reader after a duplicate that is not there — the fifth tuple element
654
- # ({RbsLoader#unresolved_type_name_detail}) is non-nil for exactly that case. Every other error class
655
- # (the two duplicated-definition errors, `RecursiveAncestorError`, …) keeps the duplicate-declaration
656
- # wording, which is accurate for them.
725
+ # ({RbsLoader#unresolved_type_name_detail}) is non-nil for exactly that case. Issue #2440 — a
726
+ # duplicated instance variable, a superclass mismatch, a missing superclass and a type applied to
727
+ # the wrong arguments each get their own sentence, and when a `virtual:` (inline RBS) buffer is
728
+ # among the colliding sources the advice never tells the reader to remove it as if it were a file.
729
+ # Every other error class (the two duplicated-definition errors, `RecursiveAncestorError`, …) keeps
730
+ # the duplicate-declaration wording, which is accurate for them.
657
731
  def definition_build_advice(failure)
658
- _, error_class, _member, _buffers, unresolved = failure
659
- if error_class.to_s.end_with?("GenericParameterMismatchError")
732
+ _, error_class, member, buffers, unresolved = failure
733
+ inline = Array(buffers).any? { |name| name.to_s.start_with?("virtual:") }
734
+ case error_class.to_s.split("::").last
735
+ when "GenericParameterMismatchError"
660
736
  "Two signature sources declare the class with a different number of type parameters; make " \
661
- "the declarations agree (`rbs validate`) to restore type coverage."
662
- elsif unresolved
663
- unresolved_type_name_advice(unresolved)
737
+ "the declarations agree (`rbs validate`) to restore type coverage."
738
+ when "InstanceVariableDuplicationError" then variable_duplication_advice("instance variable", failure)
739
+ when "ClassInstanceVariableDuplicationError"
740
+ variable_duplication_advice("class instance variable", failure)
741
+ when "SuperclassMismatchError" then superclass_mismatch_advice(inline)
742
+ when "NoSuperclassFoundError" then no_superclass_advice(member)
743
+ when "InvalidTypeApplicationError" then invalid_type_application_advice(member)
664
744
  else
745
+ return unresolved_type_name_advice(unresolved) if unresolved
746
+
665
747
  "Two signature sources declare the same member; remove the duplicate declaration " \
666
748
  "(`rbs validate`) to restore type coverage."
667
749
  end
668
750
  end
669
751
 
752
+ # The sixth tuple slot ({RbsLoader#variable_mixin_count}) is set only when the failing class mixes in
753
+ # the variable's owner at least twice and the owner declares it once: rbs counts the variable once per
754
+ # mixin. Otherwise — a variable duplicated in the owner itself, inherited or not — the wording follows
755
+ # which sources collide: inline only, inline and a file, two files, or one file declaring it twice.
756
+ def variable_duplication_advice(noun, failure)
757
+ class_name, _, member, buffers, _, mixins = failure
758
+ if mixins.is_a?(Integer) && mixins >= 2
759
+ return mixin_variable_duplication_advice(noun, class_name.to_s.delete_prefix("::"),
760
+ member.to_s.delete_prefix("::"))
761
+ end
762
+
763
+ names = Array(buffers).map(&:to_s)
764
+ inline = names.count { |name| name.start_with?("virtual:") }
765
+ if inline >= 2 && inline == names.size
766
+ "Two inline `# @rbs` annotations declare the same #{noun} in one class, and RBS rejects the " \
767
+ "pair even when the types agree; keep one of them to restore type coverage."
768
+ elsif inline.positive?
769
+ "The same #{noun} is declared twice in one class, at least once by an inline `# @rbs` " \
770
+ "annotation, and RBS rejects the pair even when the types agree. Keep one declaration: " \
771
+ "regenerate the committed `.rbs` (`rbs-inline --output`) or remove its copy of the " \
772
+ "variable, or drop the annotation from the `.rb` file, to restore type coverage."
773
+ elsif names.size >= 2
774
+ "Two signature files declare the same #{noun} in one class, and RBS rejects the pair even " \
775
+ "when the types agree; keep one declaration (`rbs validate`) to restore type coverage."
776
+ else
777
+ "The same #{noun} is declared twice in one class, and RBS rejects the pair even when the " \
778
+ "types agree; keep one declaration (`rbs validate`) to restore type coverage."
779
+ end
780
+ end
781
+
782
+ def mixin_variable_duplication_advice(noun, klass, owner)
783
+ "`#{klass}` mixes in `#{owner}` (`include`, `extend` or `prepend`) more than once, in one " \
784
+ "declaration or across several, and RBS counts each #{noun} `#{owner}` declares once per mixin. " \
785
+ "Keep a single mixin of `#{owner}` in `#{klass}` (a committed `rbs-inline --output` file and the " \
786
+ "`.rb` file it came from count as two declarations) to restore type coverage."
787
+ end
788
+
789
+ def superclass_mismatch_advice(inline)
790
+ advice = "Two declarations of the class name different superclasses; make them name the same " \
791
+ "one, or leave the superclass off every declaration but one (a reopening needs none), " \
792
+ "to restore type coverage."
793
+ return advice unless inline
794
+
795
+ "#{advice} Where one side is an inline annotation, fix the annotation and regenerate the " \
796
+ "committed `.rbs` (`rbs-inline --output`), or remove the committed copy."
797
+ end
798
+
799
+ def no_superclass_advice(member)
800
+ name = member.to_s.delete_prefix("::")
801
+ subject = name.empty? ? "A superclass" : "`#{name}`"
802
+ "#{subject} is named as a superclass, but no loaded signature declares it; declare it in your " \
803
+ "`sig/` (or load the library that does through `libraries:`), or re-run `rigor sig-gen` if " \
804
+ "the signature was generated, to restore type coverage."
805
+ end
806
+
807
+ def invalid_type_application_advice(member)
808
+ name = member.to_s.delete_prefix("::")
809
+ subject = name.empty? ? "a type" : "`#{name}`"
810
+ "A signature applies #{subject} with the wrong number of type arguments, or applies them to the " \
811
+ "wrong class; match the arguments to the type parameters the class declares (`rbs validate`) " \
812
+ "to restore type coverage."
813
+ end
814
+
670
815
  # Issue #997 — `unresolved` is {RbsLoader#unresolved_type_name_detail}'s `[token, location,
671
816
  # refinement_hint]`. `refinement_hint` turns the message into a fix: the token is not a typo to
672
817
  # chase down but the start of a Rigor refinement name that is not valid in an RBS type position, and
@@ -741,7 +886,7 @@ module Rigor
741
886
  frame_clause = relative_frame ? " at #{relative_frame}" : ""
742
887
  raised = "(#{error_class}): #{first_line}#{frame_clause}."
743
888
  Diagnostic.new(
744
- path: ".rigor.yml",
889
+ path: @configuration.config_display_path,
745
890
  line: 1,
746
891
  column: 1,
747
892
  message: stage == :overlay ? hkt_overlay_failed_message(raised) : hkt_scan_failed_message(raised),
@@ -777,6 +922,15 @@ module Rigor
777
922
  end
778
923
 
779
924
  # The absolute path is what the loader records; the user thinks in project-relative terms.
925
+ # Issue #2440 — a `virtual:<plugin>:<path>` buffer is named by the `.rb` file it was synthesized
926
+ # from, which is the file the user can open; the plugin id says how it became RBS.
927
+ def signature_source_label(name)
928
+ prefix, plugin_id, path = name.split(":", 3)
929
+ return relative_signature_path(name) unless prefix == "virtual" && plugin_id && path && !path.empty?
930
+
931
+ "#{relative_signature_path(path)} (inline RBS via #{plugin_id})"
932
+ end
933
+
780
934
  def relative_signature_path(path)
781
935
  root = "#{Dir.pwd}#{File::SEPARATOR}"
782
936
  path.start_with?(root) ? path.delete_prefix(root) : path
@@ -787,7 +941,7 @@ module Rigor
787
941
  sample = synthesized.first(sample_size)
788
942
  suffix = synthesized.size > sample_size ? ", and #{synthesized.size - sample_size} more" : ""
789
943
  Diagnostic.new(
790
- path: ".rigor.yml",
944
+ path: @configuration.config_display_path,
791
945
  line: 1,
792
946
  column: 1,
793
947
  message: "#{synthesized.size} RBS namespace(s) under `signature_paths:` are " \
@@ -806,7 +960,7 @@ module Rigor
806
960
  path, class_name, existing_arity, incoming_arity, existing_file = entry
807
961
  displaced_by = displacing_source_phrase(existing_file)
808
962
  Diagnostic.new(
809
- path: ".rigor.yml",
963
+ path: @configuration.config_display_path,
810
964
  line: 1,
811
965
  column: 1,
812
966
  message: "`#{relative_signature_path(path.to_s)}` (a signature file a plugin contributes) declares " \
@@ -824,10 +978,37 @@ module Rigor
824
978
  )
825
979
  end
826
980
 
981
+ # Issue #2422 — one plugin signature file that loaded without the declarations another source also makes,
982
+ # naming each (sampled) with the file whose declaration was used instead. One row per file, not per
983
+ # declaration: an `rbs collection install` of a gem can overlap the plugin for it on hundreds. A method
984
+ # that composed with the other source's as an overload is not here; the plugin's overloads still bind.
985
+ # The wording covers a superclass a plugin's class header gave up (#2439) as well as a member.
986
+ def build_rbs_plugin_member_stood_down_diagnostic(path, rows)
987
+ labels = rows.map do |_path, declaration, _, _, cause_file|
988
+ cause = cause_file.nil? || cause_file.empty? ? "" : " (#{relative_signature_path(cause_file.to_s)})"
989
+ "`#{declaration}`#{cause}"
990
+ end
991
+ Diagnostic.new(
992
+ path: @configuration.config_display_path,
993
+ line: 1,
994
+ column: 1,
995
+ message: "`#{relative_signature_path(path.to_s)}` (a signature file a plugin contributes) loaded without " \
996
+ "#{rows.size} declaration(s) another signature source already makes: #{sampled(labels, 10)}. " \
997
+ "Conflicting declarations (two of one method or constant, or two different superclasses " \
998
+ "of one class) fail the build, so the plugin's stood down and the other source's, named in " \
999
+ "parentheses, is used; the rest of the plugin's file still " \
1000
+ "loads. Nothing to fix unless you want the plugin's typing back, which needs that source to " \
1001
+ "stop declaring it.",
1002
+ severity: :info,
1003
+ rule: "rbs.coverage.plugin-signature-stood-down",
1004
+ source_family: :builtin
1005
+ )
1006
+ end
1007
+
827
1008
  def build_rbs_vendored_signature_stood_down_diagnostic(entry)
828
1009
  dir, declarations, whole = entry
829
1010
  Diagnostic.new(
830
- path: ".rigor.yml",
1011
+ path: @configuration.config_display_path,
831
1012
  line: 1,
832
1013
  column: 1,
833
1014
  message: vendored_standdown_message(dir, declarations, whole),
@@ -906,7 +1087,7 @@ module Rigor
906
1087
  sample = missing.first(sample_size).map(&:gem_name)
907
1088
  suffix = missing.size > sample_size ? ", and #{missing.size - sample_size} more" : ""
908
1089
  Diagnostic.new(
909
- path: ".rigor.yml",
1090
+ path: @configuration.config_display_path,
910
1091
  line: 1,
911
1092
  column: 1,
912
1093
  message: "#{missing.size} gem(s) in Gemfile.lock have no RBS available: " \
@@ -936,9 +1117,12 @@ module Rigor
936
1117
  # all three cross the pool drain channel (see {RbsExtended::Reporter}); an entry with no position
937
1118
  # falls back to `.rigor.yml`-style file-level attribution.
938
1119
  def rbs_extended_reporter_diagnostics
939
- return [] if @rbs_extended_reporter.empty?
1120
+ unresolved_payload_diagnostics + lossy_projection_diagnostics + hkt_directive_diagnostics +
1121
+ deprecated_form_diagnostics
1122
+ end
940
1123
 
941
- unresolved = @rbs_extended_reporter.unresolved_payloads.map do |entry|
1124
+ def unresolved_payload_diagnostics
1125
+ @rbs_extended_reporter.unresolved_payloads.map do |entry|
942
1126
  build_positioned_reporter_diagnostic(
943
1127
  entry,
944
1128
  rule: "dynamic.rbs-extended.unresolved",
@@ -947,8 +1131,10 @@ module Rigor
947
1131
  "that contributes the referenced type vocabulary."
948
1132
  )
949
1133
  end
1134
+ end
950
1135
 
951
- lossy = @rbs_extended_reporter.lossy_projections.map do |entry|
1136
+ def lossy_projection_diagnostics
1137
+ @rbs_extended_reporter.lossy_projections.map do |entry|
952
1138
  build_positioned_reporter_diagnostic(
953
1139
  entry,
954
1140
  rule: "dynamic.shape.lossy-projection",
@@ -957,8 +1143,6 @@ module Rigor
957
1143
  "a `HashShape` / `Tuple` carrier or accept the unchanged result."
958
1144
  )
959
1145
  end
960
-
961
- unresolved + lossy + hkt_directive_diagnostics + deprecated_form_diagnostics
962
1146
  end
963
1147
 
964
1148
  # ADR-109 WD3 — one row per annotation still written in a spelling the grammar accepts but no
@@ -1069,7 +1253,7 @@ module Rigor
1069
1253
 
1070
1254
  @boundary_cross_reporter.entries.map do |entry|
1071
1255
  Diagnostic.new(
1072
- path: ".rigor.yml", line: 1, column: 1,
1256
+ path: @configuration.config_display_path, line: 1, column: 1,
1073
1257
  message: "`#{entry.class_name}##{entry.method_name}` is contributed by both " \
1074
1258
  "RBS (#{entry.rbs_display}) and the `mode: :full` opt-in gem " \
1075
1259
  "`#{entry.gem_name}`. RBS wins on dispatch; verify the gem source " \
@@ -1196,7 +1380,7 @@ module Rigor
1196
1380
 
1197
1381
  def run_disclosure_diagnostic(record)
1198
1382
  Diagnostic.new(
1199
- path: ".rigor.yml", line: 1, column: 1,
1383
+ path: @configuration.config_display_path, line: 1, column: 1,
1200
1384
  message: record.fetch(:message),
1201
1385
  severity: record.fetch(:severity),
1202
1386
  rule: record.fetch(:rule),
@@ -1239,7 +1423,7 @@ module Rigor
1239
1423
  def plugin_trust_refusal_diagnostic(plugin, summary)
1240
1424
  plugin_id = plugin.manifest.id
1241
1425
  Diagnostic.new(
1242
- path: ".rigor.yml", line: 1, column: 1,
1426
+ path: @configuration.config_display_path, line: 1, column: 1,
1243
1427
  message: "plugin #{plugin_id.inspect} had #{summary[:count]} read(s) refused by the trust " \
1244
1428
  "policy; first refused path: #{summary[:first_path].inspect}, outside read root " \
1245
1429
  "#{summary[:nearest_root].inspect}. Spell the path the way that read root spells it " \
@@ -1330,38 +1514,6 @@ module Rigor
1330
1514
  def pre_eval_diagnostics_from_scanner
1331
1515
  @pre_eval_diagnostics_from_scanner_reader.call
1332
1516
  end
1333
-
1334
- def synthesized_namespaces_snapshot
1335
- @synthesized_namespaces_snapshot_reader.call
1336
- end
1337
-
1338
- def quarantined_signatures_snapshot
1339
- @quarantined_signatures_snapshot_reader.call
1340
- end
1341
-
1342
- def signature_standdowns_snapshot
1343
- @signature_standdowns_snapshot_reader.call
1344
- end
1345
-
1346
- def vendored_standdowns_snapshot
1347
- @vendored_standdowns_snapshot_reader.call
1348
- end
1349
-
1350
- def env_build_failure_snapshot
1351
- @env_build_failure_snapshot_reader.call
1352
- end
1353
-
1354
- def definition_build_failures_snapshot
1355
- @definition_build_failures_snapshot_reader.call
1356
- end
1357
-
1358
- def hkt_scan_failure_snapshot
1359
- @hkt_scan_failure_snapshot_reader.call
1360
- end
1361
-
1362
- def conformance_results_snapshot
1363
- @conformance_results_snapshot_reader.call
1364
- end
1365
1517
  end
1366
1518
  end
1367
1519
  end