rigortype 0.2.7 → 0.2.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 (414) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/docs/manual/04-diagnostics.md +7 -4
  4. data/docs/manual/06-baseline.md +5 -2
  5. data/docs/manual/15-type-protection-coverage.md +6 -4
  6. data/lib/rigor/analysis/baseline.rb +56 -96
  7. data/lib/rigor/analysis/buffer_binding.rb +13 -20
  8. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +29 -48
  9. data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +35 -54
  10. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +23 -37
  11. data/lib/rigor/analysis/check_rules/main_pass_collector.rb +16 -23
  12. data/lib/rigor/analysis/check_rules/rule_walk.rb +48 -71
  13. data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +19 -28
  14. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +48 -67
  15. data/lib/rigor/analysis/check_rules.rb +174 -274
  16. data/lib/rigor/analysis/dependency_recorder.rb +26 -38
  17. data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +13 -25
  18. data/lib/rigor/analysis/dependency_source_inference/builder.rb +17 -30
  19. data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +15 -26
  20. data/lib/rigor/analysis/dependency_source_inference/index.rb +45 -76
  21. data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +23 -40
  22. data/lib/rigor/analysis/dependency_source_inference/walker.rb +50 -83
  23. data/lib/rigor/analysis/dependency_source_inference.rb +6 -10
  24. data/lib/rigor/analysis/diagnostic.rb +48 -75
  25. data/lib/rigor/analysis/erb_template_detector.rb +13 -18
  26. data/lib/rigor/analysis/fact_store.rb +12 -22
  27. data/lib/rigor/analysis/incremental.rb +47 -63
  28. data/lib/rigor/analysis/incremental_session.rb +74 -100
  29. data/lib/rigor/analysis/project_scan.rb +12 -23
  30. data/lib/rigor/analysis/result.rb +3 -5
  31. data/lib/rigor/analysis/rule_catalog.rb +67 -95
  32. data/lib/rigor/analysis/run_stats.rb +38 -61
  33. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +101 -160
  34. data/lib/rigor/analysis/runner/pool_coordinator.rb +121 -188
  35. data/lib/rigor/analysis/runner/project_pre_passes.rb +62 -96
  36. data/lib/rigor/analysis/runner/run_snapshots.rb +12 -18
  37. data/lib/rigor/analysis/runner.rb +220 -333
  38. data/lib/rigor/analysis/self_call_resolution_recorder.rb +30 -43
  39. data/lib/rigor/analysis/worker_session.rb +64 -102
  40. data/lib/rigor/ast/type_node.rb +6 -8
  41. data/lib/rigor/ast.rb +6 -10
  42. data/lib/rigor/bleeding_edge.rb +27 -35
  43. data/lib/rigor/builtins/hkt_builtins.rb +7 -14
  44. data/lib/rigor/builtins/imported_refinements.rb +106 -149
  45. data/lib/rigor/builtins/predefined_constant_refinements.rb +51 -65
  46. data/lib/rigor/builtins/regex_refinement.rb +32 -43
  47. data/lib/rigor/builtins/static_return_refinements.rb +57 -81
  48. data/lib/rigor/cache/descriptor.rb +58 -94
  49. data/lib/rigor/cache/incremental_snapshot.rb +32 -48
  50. data/lib/rigor/cache/rbs_cache_producer.rb +10 -15
  51. data/lib/rigor/cache/rbs_class_ancestor_table.rb +10 -16
  52. data/lib/rigor/cache/rbs_class_type_param_names.rb +10 -16
  53. data/lib/rigor/cache/rbs_constant_table.rb +8 -13
  54. data/lib/rigor/cache/rbs_descriptor.rb +8 -13
  55. data/lib/rigor/cache/rbs_environment.rb +11 -19
  56. data/lib/rigor/cache/rbs_environment_marshal_patch.rb +11 -19
  57. data/lib/rigor/cache/rbs_known_class_names.rb +8 -12
  58. data/lib/rigor/cache/store.rb +96 -151
  59. data/lib/rigor/cli/annotate_command.rb +51 -88
  60. data/lib/rigor/cli/baseline_command.rb +10 -17
  61. data/lib/rigor/cli/check_command.rb +121 -199
  62. data/lib/rigor/cli/check_runner_factory.rb +8 -14
  63. data/lib/rigor/cli/ci_detector.rb +9 -14
  64. data/lib/rigor/cli/command.rb +8 -14
  65. data/lib/rigor/cli/coverage_command.rb +19 -26
  66. data/lib/rigor/cli/coverage_mutation.rb +14 -19
  67. data/lib/rigor/cli/coverage_report.rb +0 -2
  68. data/lib/rigor/cli/coverage_scan.rb +7 -11
  69. data/lib/rigor/cli/diagnostic_formats.rb +43 -62
  70. data/lib/rigor/cli/diff_command.rb +10 -20
  71. data/lib/rigor/cli/docs_command.rb +26 -40
  72. data/lib/rigor/cli/doctor_command.rb +8 -9
  73. data/lib/rigor/cli/explain_command.rb +4 -7
  74. data/lib/rigor/cli/fused_protection_renderer.rb +4 -5
  75. data/lib/rigor/cli/fused_protection_report.rb +6 -8
  76. data/lib/rigor/cli/lsp_command.rb +11 -19
  77. data/lib/rigor/cli/mcp_command.rb +4 -6
  78. data/lib/rigor/cli/mutation_protection_renderer.rb +3 -4
  79. data/lib/rigor/cli/mutation_protection_report.rb +6 -9
  80. data/lib/rigor/cli/options.rb +11 -19
  81. data/lib/rigor/cli/plugin_command.rb +18 -30
  82. data/lib/rigor/cli/plugins_command.rb +29 -51
  83. data/lib/rigor/cli/plugins_renderer.rb +12 -20
  84. data/lib/rigor/cli/prism_colorizer.rb +13 -19
  85. data/lib/rigor/cli/protection_renderer.rb +5 -7
  86. data/lib/rigor/cli/protection_report.rb +27 -17
  87. data/lib/rigor/cli/renderable.rb +4 -6
  88. data/lib/rigor/cli/show_bleedingedge_command.rb +5 -8
  89. data/lib/rigor/cli/sig_gen_command.rb +14 -26
  90. data/lib/rigor/cli/skill_command.rb +30 -47
  91. data/lib/rigor/cli/skill_describe.rb +40 -64
  92. data/lib/rigor/cli/trace_command.rb +9 -16
  93. data/lib/rigor/cli/trace_renderer.rb +35 -51
  94. data/lib/rigor/cli/triage_command.rb +6 -10
  95. data/lib/rigor/cli/triage_renderer.rb +1 -2
  96. data/lib/rigor/cli/type_of_command.rb +14 -23
  97. data/lib/rigor/cli/type_of_renderer.rb +3 -5
  98. data/lib/rigor/cli/type_scan_command.rb +6 -10
  99. data/lib/rigor/cli/type_scan_renderer.rb +3 -5
  100. data/lib/rigor/cli/type_scan_report.rb +2 -3
  101. data/lib/rigor/cli/upgrade_command.rb +2 -3
  102. data/lib/rigor/cli.rb +16 -28
  103. data/lib/rigor/config_audit.rb +35 -44
  104. data/lib/rigor/configuration/dependencies.rb +41 -70
  105. data/lib/rigor/configuration/severity_profile.rb +28 -42
  106. data/lib/rigor/configuration.rb +150 -241
  107. data/lib/rigor/environment/bundle_sig_discovery.rb +74 -118
  108. data/lib/rigor/environment/class_registry.rb +19 -26
  109. data/lib/rigor/environment/constant_type_cache_holder.rb +14 -21
  110. data/lib/rigor/environment/hkt_registry_holder.rb +6 -12
  111. data/lib/rigor/environment/lockfile_resolver.rb +31 -47
  112. data/lib/rigor/environment/rbs_collection_discovery.rb +39 -63
  113. data/lib/rigor/environment/rbs_coverage_report.rb +24 -42
  114. data/lib/rigor/environment/rbs_loader.rb +420 -518
  115. data/lib/rigor/environment/reflection.rb +28 -53
  116. data/lib/rigor/environment/reporters.rb +13 -24
  117. data/lib/rigor/environment.rb +176 -291
  118. data/lib/rigor/flow_contribution/conflict.rb +16 -27
  119. data/lib/rigor/flow_contribution/element.rb +7 -12
  120. data/lib/rigor/flow_contribution/fact.rb +33 -57
  121. data/lib/rigor/flow_contribution/merge_result.rb +6 -9
  122. data/lib/rigor/flow_contribution/merger.rb +32 -47
  123. data/lib/rigor/flow_contribution.rb +37 -55
  124. data/lib/rigor/inference/acceptance.rb +133 -219
  125. data/lib/rigor/inference/block_parameter_binder.rb +52 -82
  126. data/lib/rigor/inference/body_fixpoint.rb +22 -30
  127. data/lib/rigor/inference/budget_trace.rb +43 -63
  128. data/lib/rigor/inference/builtins/array_catalog.rb +4 -6
  129. data/lib/rigor/inference/builtins/comparable_catalog.rb +4 -6
  130. data/lib/rigor/inference/builtins/complex_catalog.rb +13 -19
  131. data/lib/rigor/inference/builtins/date_catalog.rb +38 -67
  132. data/lib/rigor/inference/builtins/encoding_catalog.rb +22 -36
  133. data/lib/rigor/inference/builtins/enumerable_catalog.rb +4 -6
  134. data/lib/rigor/inference/builtins/exception_catalog.rb +38 -57
  135. data/lib/rigor/inference/builtins/hash_catalog.rb +9 -14
  136. data/lib/rigor/inference/builtins/method_catalog.rb +29 -48
  137. data/lib/rigor/inference/builtins/numeric_catalog.rb +13 -18
  138. data/lib/rigor/inference/builtins/pathname_catalog.rb +8 -13
  139. data/lib/rigor/inference/builtins/proc_catalog.rb +38 -62
  140. data/lib/rigor/inference/builtins/random_catalog.rb +21 -32
  141. data/lib/rigor/inference/builtins/range_catalog.rb +12 -21
  142. data/lib/rigor/inference/builtins/rational_catalog.rb +9 -15
  143. data/lib/rigor/inference/builtins/re_catalog.rb +29 -48
  144. data/lib/rigor/inference/builtins/set_catalog.rb +18 -27
  145. data/lib/rigor/inference/builtins/string_catalog.rb +12 -19
  146. data/lib/rigor/inference/builtins/struct_catalog.rb +18 -30
  147. data/lib/rigor/inference/builtins/time_catalog.rb +28 -44
  148. data/lib/rigor/inference/closure_escape_analyzer.rb +44 -67
  149. data/lib/rigor/inference/coverage_scanner.rb +13 -18
  150. data/lib/rigor/inference/def_return_typer.rb +8 -14
  151. data/lib/rigor/inference/dynamic_origin.rb +23 -20
  152. data/lib/rigor/inference/expression_typer.rb +774 -1152
  153. data/lib/rigor/inference/fallback.rb +8 -12
  154. data/lib/rigor/inference/fallback_tracer.rb +4 -10
  155. data/lib/rigor/inference/flow_tracer.rb +25 -36
  156. data/lib/rigor/inference/hkt_body.rb +45 -68
  157. data/lib/rigor/inference/hkt_body_parser.rb +33 -52
  158. data/lib/rigor/inference/hkt_reducer.rb +38 -59
  159. data/lib/rigor/inference/hkt_registry.rb +50 -76
  160. data/lib/rigor/inference/indexed_narrowing.rb +55 -81
  161. data/lib/rigor/inference/macro_block_self_type.rb +21 -34
  162. data/lib/rigor/inference/method_dispatcher/array_to_h_folding.rb +11 -18
  163. data/lib/rigor/inference/method_dispatcher/block_folding.rb +49 -83
  164. data/lib/rigor/inference/method_dispatcher/call_context.rb +16 -23
  165. data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +13 -22
  166. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +307 -454
  167. data/lib/rigor/inference/method_dispatcher/data_folding.rb +24 -34
  168. data/lib/rigor/inference/method_dispatcher/file_folding.rb +22 -37
  169. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +52 -81
  170. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +51 -78
  171. data/lib/rigor/inference/method_dispatcher/literal_string_folding.rb +60 -97
  172. data/lib/rigor/inference/method_dispatcher/math_folding.rb +23 -34
  173. data/lib/rigor/inference/method_dispatcher/member_shape_projection.rb +18 -26
  174. data/lib/rigor/inference/method_dispatcher/method_folding.rb +37 -71
  175. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +114 -182
  176. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +122 -193
  177. data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +15 -24
  178. data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +64 -93
  179. data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +31 -45
  180. data/lib/rigor/inference/method_dispatcher/set_folding.rb +6 -9
  181. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +356 -511
  182. data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +22 -32
  183. data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +15 -21
  184. data/lib/rigor/inference/method_dispatcher/struct_folding.rb +66 -82
  185. data/lib/rigor/inference/method_dispatcher/time_folding.rb +10 -15
  186. data/lib/rigor/inference/method_dispatcher/uri_folding.rb +9 -13
  187. data/lib/rigor/inference/method_dispatcher.rb +378 -524
  188. data/lib/rigor/inference/method_parameter_binder.rb +81 -114
  189. data/lib/rigor/inference/multi_target_binder.rb +51 -68
  190. data/lib/rigor/inference/mutation_widening.rb +115 -158
  191. data/lib/rigor/inference/narrowing.rb +509 -727
  192. data/lib/rigor/inference/origin_lookup.rb +38 -0
  193. data/lib/rigor/inference/parameter_inference_collector.rb +100 -100
  194. data/lib/rigor/inference/precision_scanner.rb +26 -35
  195. data/lib/rigor/inference/project_patched_methods.rb +20 -32
  196. data/lib/rigor/inference/project_patched_scanner.rb +23 -37
  197. data/lib/rigor/inference/protection_scanner.rb +16 -18
  198. data/lib/rigor/inference/rbs_type_translator.rb +49 -66
  199. data/lib/rigor/inference/scope_indexer.rb +473 -817
  200. data/lib/rigor/inference/statement_evaluator.rb +706 -1111
  201. data/lib/rigor/inference/struct_fold_safety.rb +34 -48
  202. data/lib/rigor/inference/synthetic_method.rb +9 -16
  203. data/lib/rigor/inference/synthetic_method_index.rb +20 -35
  204. data/lib/rigor/inference/synthetic_method_scanner.rb +63 -103
  205. data/lib/rigor/language_server/buffer_resolution.rb +6 -9
  206. data/lib/rigor/language_server/buffer_table.rb +11 -18
  207. data/lib/rigor/language_server/completion_provider.rb +69 -116
  208. data/lib/rigor/language_server/debouncer.rb +16 -25
  209. data/lib/rigor/language_server/diagnostic_publisher.rb +26 -40
  210. data/lib/rigor/language_server/document_symbol_provider.rb +14 -19
  211. data/lib/rigor/language_server/folding_range_provider.rb +11 -19
  212. data/lib/rigor/language_server/hover_provider.rb +8 -11
  213. data/lib/rigor/language_server/hover_renderer.rb +56 -93
  214. data/lib/rigor/language_server/loop.rb +14 -19
  215. data/lib/rigor/language_server/project_context.rb +46 -74
  216. data/lib/rigor/language_server/selection_range_provider.rb +9 -12
  217. data/lib/rigor/language_server/server.rb +55 -83
  218. data/lib/rigor/language_server/signature_help_provider.rb +29 -46
  219. data/lib/rigor/language_server/synchronized_writer.rb +4 -7
  220. data/lib/rigor/language_server/uri.rb +8 -13
  221. data/lib/rigor/language_server.rb +4 -6
  222. data/lib/rigor/mcp/loop.rb +2 -3
  223. data/lib/rigor/mcp/server.rb +4 -7
  224. data/lib/rigor/mcp.rb +3 -6
  225. data/lib/rigor/plugin/access_denied_error.rb +5 -8
  226. data/lib/rigor/plugin/additional_initializer.rb +21 -31
  227. data/lib/rigor/plugin/base.rb +335 -518
  228. data/lib/rigor/plugin/blueprint.rb +14 -23
  229. data/lib/rigor/plugin/box.rb +18 -29
  230. data/lib/rigor/plugin/fact_store.rb +16 -26
  231. data/lib/rigor/plugin/inflector.rb +37 -53
  232. data/lib/rigor/plugin/io_boundary.rb +33 -56
  233. data/lib/rigor/plugin/isolation.rb +42 -55
  234. data/lib/rigor/plugin/load_error.rb +10 -15
  235. data/lib/rigor/plugin/loader.rb +30 -49
  236. data/lib/rigor/plugin/macro/block_as_method.rb +20 -32
  237. data/lib/rigor/plugin/macro/heredoc_template.rb +35 -58
  238. data/lib/rigor/plugin/macro/nested_class_template.rb +22 -36
  239. data/lib/rigor/plugin/macro/trait_registry.rb +34 -51
  240. data/lib/rigor/plugin/macro.rb +10 -15
  241. data/lib/rigor/plugin/manifest.rb +85 -144
  242. data/lib/rigor/plugin/node_context.rb +14 -22
  243. data/lib/rigor/plugin/node_rule_walk.rb +49 -74
  244. data/lib/rigor/plugin/protocol_contract.rb +25 -39
  245. data/lib/rigor/plugin/registry.rb +132 -205
  246. data/lib/rigor/plugin/services.rb +21 -33
  247. data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -19
  248. data/lib/rigor/plugin/trust_policy.rb +24 -38
  249. data/lib/rigor/plugin/type_node_resolver.rb +15 -24
  250. data/lib/rigor/protection/diagnostic_oracle.rb +11 -13
  251. data/lib/rigor/protection/mutation_scanner.rb +27 -35
  252. data/lib/rigor/protection/mutator.rb +50 -70
  253. data/lib/rigor/protection/test_suite_oracle.rb +20 -27
  254. data/lib/rigor/rbs_extended/conformance_checker.rb +48 -68
  255. data/lib/rigor/rbs_extended/hkt_directives.rb +28 -54
  256. data/lib/rigor/rbs_extended/reporter.rb +24 -40
  257. data/lib/rigor/rbs_extended.rb +107 -197
  258. data/lib/rigor/reflection.rb +68 -86
  259. data/lib/rigor/scope/discovery_index.rb +14 -19
  260. data/lib/rigor/scope.rb +255 -310
  261. data/lib/rigor/sig_gen/classification.rb +6 -10
  262. data/lib/rigor/sig_gen/generator.rb +197 -323
  263. data/lib/rigor/sig_gen/layout_index.rb +12 -20
  264. data/lib/rigor/sig_gen/method_candidate.rb +12 -17
  265. data/lib/rigor/sig_gen/observation_collector.rb +38 -70
  266. data/lib/rigor/sig_gen/observed_call.rb +13 -23
  267. data/lib/rigor/sig_gen/path_mapper.rb +17 -29
  268. data/lib/rigor/sig_gen/renderer.rb +7 -13
  269. data/lib/rigor/sig_gen/type_elaborator.rb +15 -28
  270. data/lib/rigor/sig_gen/write_result.rb +8 -16
  271. data/lib/rigor/sig_gen/writer.rb +95 -174
  272. data/lib/rigor/sig_gen.rb +3 -6
  273. data/lib/rigor/signature_path_audit.rb +24 -30
  274. data/lib/rigor/source/constant_path.rb +10 -14
  275. data/lib/rigor/source/literals.rb +31 -45
  276. data/lib/rigor/source/node_locator.rb +9 -11
  277. data/lib/rigor/source/node_walker.rb +9 -13
  278. data/lib/rigor/source.rb +3 -4
  279. data/lib/rigor/testing.rb +16 -20
  280. data/lib/rigor/triage/catalogue.rb +38 -62
  281. data/lib/rigor/triage.rb +31 -52
  282. data/lib/rigor/trinary.rb +9 -13
  283. data/lib/rigor/type/acceptance_router.rb +4 -6
  284. data/lib/rigor/type/accepts_result.rb +10 -14
  285. data/lib/rigor/type/app.rb +19 -27
  286. data/lib/rigor/type/bot.rb +4 -6
  287. data/lib/rigor/type/bound_method.rb +10 -15
  288. data/lib/rigor/type/combinator.rb +165 -257
  289. data/lib/rigor/type/constant.rb +23 -34
  290. data/lib/rigor/type/data_class.rb +10 -15
  291. data/lib/rigor/type/data_instance.rb +14 -20
  292. data/lib/rigor/type/difference.rb +21 -32
  293. data/lib/rigor/type/dynamic.rb +3 -5
  294. data/lib/rigor/type/hash_shape.rb +32 -18
  295. data/lib/rigor/type/integer_range.rb +11 -16
  296. data/lib/rigor/type/intersection.rb +27 -42
  297. data/lib/rigor/type/nominal.rb +10 -15
  298. data/lib/rigor/type/plain_lattice.rb +9 -13
  299. data/lib/rigor/type/refined.rb +67 -114
  300. data/lib/rigor/type/singleton.rb +4 -6
  301. data/lib/rigor/type/struct_class.rb +11 -16
  302. data/lib/rigor/type/struct_instance.rb +15 -21
  303. data/lib/rigor/type/tuple.rb +14 -19
  304. data/lib/rigor/type/union.rb +30 -42
  305. data/lib/rigor/type_node/generic.rb +14 -26
  306. data/lib/rigor/type_node/identifier.rb +12 -19
  307. data/lib/rigor/type_node.rb +3 -12
  308. data/lib/rigor/value_semantics.rb +16 -21
  309. data/lib/rigor/version.rb +1 -1
  310. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +18 -30
  311. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +16 -29
  312. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +12 -23
  313. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +22 -39
  314. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +26 -46
  315. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +51 -87
  316. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +10 -17
  317. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +26 -39
  318. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +118 -176
  319. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +30 -51
  320. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +57 -92
  321. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +71 -108
  322. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +13 -22
  323. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +15 -25
  324. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +8 -13
  325. data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +16 -24
  326. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +30 -47
  327. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +79 -129
  328. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +36 -57
  329. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +27 -41
  330. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +16 -24
  331. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +148 -235
  332. data/plugins/rigor-activerecord/lib/rigor-activerecord.rb +3 -5
  333. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +8 -14
  334. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +9 -15
  335. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +4 -7
  336. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +23 -41
  337. data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +3 -5
  338. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +6 -10
  339. data/plugins/rigor-activesupport-core-ext/lib/rigor-activesupport-core-ext.rb +8 -11
  340. data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +30 -45
  341. data/plugins/rigor-devise/lib/rigor-devise.rb +3 -5
  342. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +43 -69
  343. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +26 -35
  344. data/plugins/rigor-dry-schema/lib/rigor-dry-schema.rb +3 -5
  345. data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +30 -47
  346. data/plugins/rigor-dry-struct/lib/rigor-dry-struct.rb +3 -5
  347. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +67 -113
  348. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +29 -46
  349. data/plugins/rigor-dry-types/lib/rigor-dry-types.rb +3 -5
  350. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -20
  351. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +14 -23
  352. data/plugins/rigor-dry-validation/lib/rigor-dry-validation.rb +2 -3
  353. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +22 -37
  354. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +28 -46
  355. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +13 -17
  356. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +30 -47
  357. data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +52 -80
  358. data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +21 -31
  359. data/plugins/rigor-graphql/lib/rigor-graphql.rb +3 -5
  360. data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +11 -17
  361. data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +20 -34
  362. data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +45 -75
  363. data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +22 -36
  364. data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +22 -41
  365. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +17 -32
  366. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +6 -12
  367. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +4 -8
  368. data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +17 -32
  369. data/plugins/rigor-rails/lib/rigor-rails.rb +11 -18
  370. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +58 -92
  371. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +20 -34
  372. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +20 -31
  373. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +49 -82
  374. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +55 -92
  375. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +51 -90
  376. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +17 -30
  377. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +38 -70
  378. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +42 -74
  379. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +280 -497
  380. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +54 -89
  381. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +32 -54
  382. data/plugins/rigor-rbs-inline/lib/rigor-rbs-inline.rb +8 -13
  383. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +9 -16
  384. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +24 -39
  385. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +13 -22
  386. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +34 -56
  387. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/scope_walker.rb +22 -42
  388. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +43 -75
  389. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +27 -39
  390. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/http_status_codes.rb +14 -19
  391. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +20 -34
  392. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +28 -47
  393. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +21 -37
  394. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +13 -22
  395. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +18 -31
  396. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +6 -10
  397. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +14 -29
  398. data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +23 -41
  399. data/plugins/rigor-sinatra/lib/rigor-sinatra.rb +3 -5
  400. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +23 -38
  401. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +57 -96
  402. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +22 -35
  403. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +41 -69
  404. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/method_signature.rb +6 -10
  405. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +24 -41
  406. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +29 -50
  407. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +55 -88
  408. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +159 -262
  409. data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +21 -29
  410. data/plugins/rigor-statesman/lib/rigor-statesman.rb +3 -5
  411. data/plugins/rigor-typescript-utility-types/lib/rigor/plugin/typescript_utility_types.rb +23 -37
  412. data/plugins/rigor-typescript-utility-types/lib/rigor-typescript-utility-types.rb +4 -6
  413. data/sig/rigor/scope.rbs +6 -0
  414. metadata +2 -1
@@ -7,12 +7,10 @@ require_relative "rbs_extended/reporter"
7
7
  require_relative "rbs_extended/hkt_directives"
8
8
 
9
9
  module Rigor
10
- # Reader for the `RBS::Extended` annotation surface described in
11
- # `docs/type-specification/rbs-extended.md`.
10
+ # Reader for the `RBS::Extended` annotation surface described in `docs/type-specification/rbs-extended.md`.
12
11
  #
13
- # Reads `%a{rigor:v1:<directive> <payload>}` annotations off RBS
14
- # method definitions and returns well-typed effect objects the
15
- # inference engine can consume. Implemented directives:
12
+ # Reads `%a{rigor:v1:<directive> <payload>}` annotations off RBS method definitions and returns well-typed
13
+ # effect objects the inference engine can consume. Implemented directives:
16
14
  #
17
15
  # - `rigor:v1:predicate-if-true <target> is <ClassName|refinement>`
18
16
  # - `rigor:v1:predicate-if-false <target> is <ClassName|refinement>`
@@ -23,45 +21,33 @@ module Rigor
23
21
  # - `rigor:v1:return <type-expr>` — per-call return override
24
22
  # - `rigor:v1:conforms-to <InterfaceName>` — structural conformance
25
23
  #
26
- # `predicate-if-*` fires when the call is used as an `if` / `unless`
27
- # condition; `assert` fires unconditionally at the call's post-scope;
28
- # `assert-if-true` / `assert-if-false` fire at the post-scope only
29
- # when the call's return value can be observed as truthy / falsey.
30
- # Negation (`~T`) is supported for both class-name and refinement
31
- # right-hand sides. Parameterised refinements (`non-empty-array[T]`)
32
- # are also recognised. Annotations whose directive is unrecognised
33
- # are silently ignored per the spec's "unsupported metadata" guidance.
24
+ # `predicate-if-*` fires when the call is used as an `if` / `unless` condition; `assert` fires unconditionally
25
+ # at the call's post-scope; `assert-if-true` / `assert-if-false` fire at the post-scope only when the call's
26
+ # return value can be observed as truthy / falsey. Negation (`~T`) is supported for both class-name and
27
+ # refinement right-hand sides. Parameterised refinements (`non-empty-array[T]`) are also recognised. Annotations
28
+ # whose directive is unrecognised are silently ignored per the spec's "unsupported metadata" guidance.
34
29
  module RbsExtended # rubocop:disable Metrics/ModuleLength
35
30
  DIRECTIVE_PREFIX = "rigor:v1:"
36
31
 
37
- # Returned for `predicate-if-true` / `predicate-if-false`.
38
- # `target_kind` is `:parameter` (with `target_name` the
39
- # Ruby parameter symbol) or `:self`. `negative` is true
40
- # when the directive uses the `~ClassName` form, in
41
- # which case the engine narrows AWAY from `class_name`
42
- # (`Narrowing.narrow_not_class`) instead of toward it.
32
+ # Returned for `predicate-if-true` / `predicate-if-false`. `target_kind` is `:parameter` (with `target_name`
33
+ # the Ruby parameter symbol) or `:self`. `negative` is true when the directive uses the `~ClassName` form, in
34
+ # which case the engine narrows AWAY from `class_name` (`Narrowing.narrow_not_class`) instead of toward it.
43
35
  #
44
- # `refinement_type` is non-nil when the right-hand side is
45
- # a kebab-case refinement name (`non-empty-string`,
46
- # `lowercase-string`, …) instead of a Capitalised class
47
- # name. The narrowing tier substitutes the carrier for the
48
- # current local type; `class_name` is then nil. `negative`
49
- # may be true for refinement-form directives — `~T` negation
50
- # is supported; the narrowing tier computes the complement
51
- # decomposition (see `AssertEffect` docs below).
36
+ # `refinement_type` is non-nil when the right-hand side is a kebab-case refinement name (`non-empty-string`,
37
+ # `lowercase-string`, …) instead of a Capitalised class name. The narrowing tier substitutes the carrier for
38
+ # the current local type; `class_name` is then nil. `negative` may be true for refinement-form directives —
39
+ # `~T` negation is supported; the narrowing tier computes the complement decomposition (see `AssertEffect`
40
+ # docs below).
52
41
  class PredicateEffect < Data.define(:edge, :target_kind, :target_name, :class_name, :negative, :refinement_type)
53
42
  def truthy_only? = edge == :truthy_only
54
43
  def falsey_only? = edge == :falsey_only
55
44
  def negative? = negative == true
56
45
  def refinement? = !refinement_type.nil?
57
46
 
58
- # ADR-7 § "Slice 4-A" canonical translation. Lifts the
59
- # parser-side carrier into a `Rigor::FlowContribution::Fact`
60
- # that the merger and plugin contribution stream consume
61
- # uniformly. `class_name` lifts to `Nominal[<class>]`;
62
- # `refinement_type` is already a `Rigor::Type` and passes
63
- # through. The `edge` field doesn't survive the conversion —
64
- # the slot it lands in (truthy_facts / falsey_facts / ...)
47
+ # ADR-7 § "Slice 4-A" canonical translation. Lifts the parser-side carrier into a
48
+ # `Rigor::FlowContribution::Fact` that the merger and plugin contribution stream consume uniformly.
49
+ # `class_name` lifts to `Nominal[<class>]`; `refinement_type` is already a `Rigor::Type` and passes through.
50
+ # The `edge` field doesn't survive the conversion — the slot it lands in (truthy_facts / falsey_facts / ...)
65
51
  # encodes that.
66
52
  def to_fact
67
53
  FlowContribution::Fact.new(
@@ -73,21 +59,14 @@ module Rigor
73
59
  end
74
60
  end
75
61
 
76
- # Returned for `assert` / `assert-if-true` /
77
- # `assert-if-false`. `condition` is one of:
62
+ # Returned for `assert` / `assert-if-true` / `assert-if-false`. `condition` is one of:
78
63
  #
79
- # - `:always` — refines `target` at the call's
80
- # post-scope unconditionally
81
- # (`assert`).
82
- # - `:if_truthy_return` — refines `target` only when the
83
- # call's return value is observed
84
- # as truthy (currently: as the
85
- # predicate of a subsequent
86
- # `if` / `unless`).
64
+ # - `:always` — refines `target` at the call's post-scope unconditionally (`assert`).
65
+ # - `:if_truthy_return` — refines `target` only when the call's return value is observed as truthy
66
+ # (currently: as the predicate of a subsequent `if` / `unless`).
87
67
  # - `:if_falsey_return` — symmetric for falsey.
88
68
  #
89
- # `negative` mirrors `PredicateEffect`: true when the
90
- # directive uses `~ClassName` syntax.
69
+ # `negative` mirrors `PredicateEffect`: true when the directive uses `~ClassName` syntax.
91
70
  class AssertEffect < Data.define(:condition, :target_kind, :target_name, :class_name, :negative, :refinement_type)
92
71
  def always? = condition == :always
93
72
  def if_truthy_return? = condition == :if_truthy_return
@@ -95,12 +74,9 @@ module Rigor
95
74
  def negative? = negative == true
96
75
  def refinement? = !refinement_type.nil?
97
76
 
98
- # ADR-7 § "Slice 4-A" canonical translation. Same shape as
99
- # `PredicateEffect#to_fact`; the `condition` field
100
- # (`:always` / `:if_truthy_return` / `:if_falsey_return`)
101
- # routes which slot the resulting fact lands in at the
102
- # `read_flow_contribution` boundary, but does not surface
103
- # on the Fact itself.
77
+ # ADR-7 § "Slice 4-A" canonical translation. Same shape as `PredicateEffect#to_fact`; the `condition` field
78
+ # (`:always` / `:if_truthy_return` / `:if_falsey_return`) routes which slot the resulting fact lands in at
79
+ # the `read_flow_contribution` boundary, but does not surface on the Fact itself.
104
80
  def to_fact
105
81
  FlowContribution::Fact.new(
106
82
  target_kind: target_kind,
@@ -113,12 +89,9 @@ module Rigor
113
89
 
114
90
  module_function
115
91
 
116
- # Reads RBS::Extended predicate effects off
117
- # `RBS::Definition::Method#annotations`. Returns the
118
- # effects in source order; duplicates and unrecognised
119
- # `rigor:v1:` directives are dropped. Returns an empty
120
- # array (NEVER `nil`) for a method with no recognised
121
- # annotations so callers can iterate unconditionally.
92
+ # Reads RBS::Extended predicate effects off `RBS::Definition::Method#annotations`. Returns the effects in
93
+ # source order; duplicates and unrecognised `rigor:v1:` directives are dropped. Returns an empty array (NEVER
94
+ # `nil`) for a method with no recognised annotations so callers can iterate unconditionally.
122
95
  #
123
96
  # @param environment [Rigor::Environment, nil] ADR-13 slice
124
97
  # 3b. When provided, threads the plugin-supplied
@@ -148,14 +121,11 @@ module Rigor
148
121
  effects.uniq
149
122
  end
150
123
 
151
- # The right-hand side accepts either a Capitalised class
152
- # name (with optional `~` negation, optional `::` prefix,
153
- # qualified names) OR a kebab-case refinement payload
154
- # routed through `Builtins::ImportedRefinements::Parser`
155
- # (bare names, `name[T]`, `name<min, max>`). The two arms
156
- # share the same overall directive shape; the parser
157
- # detects which form matched by looking at the `class_name`
158
- # vs `refinement` capture groups.
124
+ # The right-hand side accepts either a Capitalised class name (with optional `~` negation, optional `::`
125
+ # prefix, qualified names) OR a kebab-case refinement payload routed through
126
+ # `Builtins::ImportedRefinements::Parser` (bare names, `name[T]`, `name<min, max>`). The two arms share the
127
+ # same overall directive shape; the parser detects which form matched by looking at the `class_name` vs
128
+ # `refinement` capture groups.
159
129
  PREDICATE_DIRECTIVE_PATTERN = /
160
130
  \A
161
131
  rigor:v1:(?<directive>predicate-if-(?:true|false))
@@ -202,14 +172,11 @@ module Rigor
202
172
  )
203
173
  end
204
174
 
205
- # Reads RBS::Extended assertion effects (`assert`,
206
- # `assert-if-true`, `assert-if-false`) off
207
- # `RBS::Definition::Method#annotations`. Returns an empty
208
- # array when no recognised assertion directives are
175
+ # Reads RBS::Extended assertion effects (`assert`, `assert-if-true`, `assert-if-false`) off
176
+ # `RBS::Definition::Method#annotations`. Returns an empty array when no recognised assertion directives are
209
177
  # attached to the method.
210
178
  #
211
- # See {.read_predicate_effects} for the `environment:`
212
- # keyword contract.
179
+ # See {.read_predicate_effects} for the `environment:` keyword contract.
213
180
  def read_assert_effects(method_def, environment: nil)
214
181
  return [] if method_def.nil?
215
182
 
@@ -332,16 +299,11 @@ module Rigor
332
299
  end
333
300
  end
334
301
 
335
- # Reads the `rigor:v1:return: <kebab-name>` directive off
336
- # `RBS::Definition::Method#annotations`. The directive
337
- # overrides a method's RBS-declared return type with one of
338
- # the imported-built-in refinements registered in
339
- # `Rigor::Builtins::ImportedRefinements`. The override is the
340
- # primary integration path for refinement carriers
341
- # (`non-empty-string`, `positive-int`, `non-empty-array`, …)
342
- # in v0.0 — annotation-driven, opt-in per method, and never
343
- # silently rewrites a hand-authored RBS signature outside the
344
- # annotation.
302
+ # Reads the `rigor:v1:return: <kebab-name>` directive off `RBS::Definition::Method#annotations`. The
303
+ # directive overrides a method's RBS-declared return type with one of the imported-built-in refinements
304
+ # registered in `Rigor::Builtins::ImportedRefinements`. The override is the primary integration path for
305
+ # refinement carriers (`non-empty-string`, `positive-int`, `non-empty-array`, …) in v0.0 annotation-driven,
306
+ # opt-in per method, and never silently rewrites a hand-authored RBS signature outside the annotation.
345
307
  #
346
308
  # Example annotation in an RBS file:
347
309
  #
@@ -350,22 +312,16 @@ module Rigor
350
312
  # def name: () -> String
351
313
  # end
352
314
  #
353
- # The RBS-declared return is `String`. The override
354
- # tightens it to `non-empty-string` (i.e.
355
- # `Difference[String, ""]`) for callers; RBS erasure of the
356
- # tightened return goes back to `String` so the round-trip
357
- # to ordinary RBS is unaffected.
315
+ # The RBS-declared return is `String`. The override tightens it to `non-empty-string` (i.e.
316
+ # `Difference[String, ""]`) for callers; RBS erasure of the tightened return goes back to `String` so the
317
+ # round-trip to ordinary RBS is unaffected.
358
318
  #
359
319
  # Returns the resolved `Rigor::Type` value, or `nil` when:
360
320
  # - the method has no annotations,
361
- # - none of the annotations match the `rigor:v1:return:`
362
- # directive,
363
- # - the directive's payload names a refinement not
364
- # registered in `Rigor::Builtins::ImportedRefinements`
365
- # (the analyzer prefers a silent miss over crashing on a
366
- # typo; ADR-13 slice 3b surfaces the miss as a
367
- # `dynamic.rbs-extended.unresolved` `:info` diagnostic when
368
- # an `environment:` is supplied).
321
+ # - none of the annotations match the `rigor:v1:return:` directive,
322
+ # - the directive's payload names a refinement not registered in `Rigor::Builtins::ImportedRefinements` (the
323
+ # analyzer prefers a silent miss over crashing on a typo; ADR-13 slice 3b surfaces the miss as a
324
+ # `dynamic.rbs-extended.unresolved` `:info` diagnostic when an `environment:` is supplied).
369
325
  def read_return_type_override(method_def, environment: nil)
370
326
  return nil if method_def.nil?
371
327
 
@@ -389,14 +345,10 @@ module Rigor
389
345
  nil
390
346
  end
391
347
 
392
- # The trailing payload supports the full refinement
393
- # grammar in `Builtins::ImportedRefinements::Parser`
394
- # bare kebab-case names plus parameterised forms like
395
- # `non-empty-array[Integer]`, `non-empty-hash[Symbol,
396
- # Integer]`, and `int<5, 10>`. The directive head is
397
- # consumed by the regex; the rest is forwarded to the
398
- # refinement parser. Anything the parser cannot resolve
399
- # falls back to nil so the call site keeps the
348
+ # The trailing payload supports the full refinement grammar in `Builtins::ImportedRefinements::Parser` — bare
349
+ # kebab-case names plus parameterised forms like `non-empty-array[Integer]`, `non-empty-hash[Symbol,
350
+ # Integer]`, and `int<5, 10>`. The directive head is consumed by the regex; the rest is forwarded to the
351
+ # refinement parser. Anything the parser cannot resolve falls back to nil so the call site keeps the
400
352
  # RBS-declared return type.
401
353
  RETURN_DIRECTIVE_PATTERN = /
402
354
  \A
@@ -408,15 +360,11 @@ module Rigor
408
360
  /x
409
361
  private_constant :RETURN_DIRECTIVE_PATTERN
410
362
 
411
- # ADR-20 slice 2d — recognises `App[<uri>, <ClassName>, ...]`
412
- # syntax in a `rigor:v1:return:` payload before falling
413
- # through to the refinement-name parser. The match captures
414
- # the namespaced URI (`json::value`) plus a comma-separated
415
- # list of bare class names (`String`, `Symbol`, `Integer`).
416
- # Slice 2d keeps the arg vocabulary intentionally narrow;
417
- # parameterised forms (`Array[T]`, `Hash[K, V]`), unions,
418
- # and refinements inside `App[...]` wait for a follow-up
419
- # slice's expression parser.
363
+ # ADR-20 slice 2d — recognises `App[<uri>, <ClassName>, ...]` syntax in a `rigor:v1:return:` payload before
364
+ # falling through to the refinement-name parser. The match captures the namespaced URI (`json::value`) plus a
365
+ # comma-separated list of bare class names (`String`, `Symbol`, `Integer`). Slice 2d keeps the arg vocabulary
366
+ # intentionally narrow; parameterised forms (`Array[T]`, `Hash[K, V]`), unions, and refinements inside
367
+ # `App[...]` wait for a follow-up slice's expression parser.
420
368
  APP_PAYLOAD_PATTERN = /
421
369
  \A
422
370
  App\[
@@ -452,17 +400,12 @@ module Rigor
452
400
  type
453
401
  end
454
402
 
455
- # ADR-20 slice 2d. Parses `App[<uri>, <ClassName>, ...]`
456
- # syntax into a `Rigor::Type::App`. When `hkt_registry` is
457
- # supplied and the URI is registered with a body_tree, the
458
- # `App` is reduced eagerly via {Inference::HktRegistry#reduce}
459
- # so call sites observe the unfolded form (e.g.
460
- # `Union[nil, true, false, ..., Array[App[json::value,
461
- # String]], Hash[String, App[json::value, String]]]`)
462
- # rather than the opaque carrier. When the registry is
463
- # absent or the URI is unregistered, the carrier with its
464
- # registry-supplied bound (or `untyped` as a last-resort
465
- # fallback) is returned as-is.
403
+ # ADR-20 slice 2d. Parses `App[<uri>, <ClassName>, ...]` syntax into a `Rigor::Type::App`. When
404
+ # `hkt_registry` is supplied and the URI is registered with a body_tree, the `App` is reduced eagerly via
405
+ # {Inference::HktRegistry#reduce} so call sites observe the unfolded form (e.g.
406
+ # `Union[nil, true, false, ..., Array[App[json::value, String]], Hash[String, App[json::value, String]]]`)
407
+ # rather than the opaque carrier. When the registry is absent or the URI is unregistered, the carrier with
408
+ # its registry-supplied bound (or `untyped` as a last-resort fallback) is returned as-is.
466
409
  def parse_app_payload(payload, name_scope: nil, reporter: nil, source_location: nil, hkt_registry: nil)
467
410
  match = APP_PAYLOAD_PATTERN.match(payload)
468
411
  return nil if match.nil?
@@ -499,22 +442,15 @@ module Rigor
499
442
  Type::Nominal.new(normalized)
500
443
  end
501
444
 
502
- # Returned for `rigor:v1:param: <name> <refinement>`. The
503
- # parameter name is a Ruby identifier (Symbol); the type
504
- # is any `Rigor::Type` the refinement parser resolves
505
- # (bare kebab-case name, parameterised form, or `int<...>`
506
- # range — the same grammar the `return:` directive
507
- # accepts).
445
+ # Returned for `rigor:v1:param: <name> <refinement>`. The parameter name is a Ruby identifier (Symbol); the
446
+ # type is any `Rigor::Type` the refinement parser resolves (bare kebab-case name, parameterised form, or
447
+ # `int<...>` range the same grammar the `return:` directive accepts).
508
448
  ParamOverride = Data.define(:param_name, :type)
509
449
 
510
- # Reads every `rigor:v1:param: <name> <refinement>`
511
- # directive off `RBS::Definition::Method#annotations` and
512
- # returns the resolved `ParamOverride` list. Annotations
513
- # the parser cannot resolve (typo, unknown refinement, no
514
- # `param:` directive at all) are silently dropped — the
515
- # call site keeps the RBS-declared parameter type for
516
- # those parameters. The reader accepts a nil method
517
- # definition so call sites can pass through optional
450
+ # Reads every `rigor:v1:param: <name> <refinement>` directive off `RBS::Definition::Method#annotations` and
451
+ # returns the resolved `ParamOverride` list. Annotations the parser cannot resolve (typo, unknown refinement,
452
+ # no `param:` directive at all) are silently dropped — the call site keeps the RBS-declared parameter type
453
+ # for those parameters. The reader accepts a nil method definition so call sites can pass through optional
518
454
  # method lookups without a guard.
519
455
  #
520
456
  # Example annotation in an RBS file:
@@ -524,11 +460,9 @@ module Rigor
524
460
  # def normalise: (::String id) -> String
525
461
  # end
526
462
  #
527
- # The RBS-declared type of `id` is `String`. The override
528
- # tightens it to `non-empty-string` for argument-check
529
- # purposes; passing a too-wide `Nominal[String]` argument
530
- # is flagged as an argument-type mismatch at the call
531
- # site.
463
+ # The RBS-declared type of `id` is `String`. The override tightens it to `non-empty-string` for
464
+ # argument-check purposes; passing a too-wide `Nominal[String]` argument is flagged as an argument-type
465
+ # mismatch at the call site.
532
466
  def read_param_type_overrides(method_def, environment: nil)
533
467
  return [] if method_def.nil?
534
468
 
@@ -548,23 +482,18 @@ module Rigor
548
482
  end
549
483
  end
550
484
 
551
- # Convenience reader for call sites that want to look up
552
- # a single override by parameter name. Returns a frozen
553
- # Hash<Symbol, Rigor::Type>; missing keys mean "use the
554
- # RBS-declared type". Callers MUST treat the hash as
555
- # read-only.
485
+ # Convenience reader for call sites that want to look up a single override by parameter name. Returns a
486
+ # frozen Hash<Symbol, Rigor::Type>; missing keys mean "use the RBS-declared type". Callers MUST treat the
487
+ # hash as read-only.
556
488
  def param_type_override_map(method_def, environment: nil)
557
489
  read_param_type_overrides(method_def, environment: environment)
558
490
  .to_h { |o| [o.param_name, o.type] }
559
491
  .freeze
560
492
  end
561
493
 
562
- # The `is` glue word is optional so authors can write
563
- # either `param: id is non-empty-string` (consistent with
564
- # the existing `assert` / `predicate-if-*` directives) or
565
- # the terser `param: id non-empty-string`. The trailing
566
- # payload accepts the full refinement grammar in
567
- # `Builtins::ImportedRefinements::Parser`.
494
+ # The `is` glue word is optional so authors can write either `param: id is non-empty-string` (consistent with
495
+ # the existing `assert` / `predicate-if-*` directives) or the terser `param: id non-empty-string`. The
496
+ # trailing payload accepts the full refinement grammar in `Builtins::ImportedRefinements::Parser`.
568
497
  PARAM_DIRECTIVE_PATTERN = /
569
498
  \A
570
499
  rigor:v1:param:
@@ -596,20 +525,14 @@ module Rigor
596
525
  ParamOverride.new(param_name: match[:param].to_sym, type: type)
597
526
  end
598
527
 
599
- # A class- / module-level directive declaring that the
600
- # annotated class satisfies a named structural interface as
601
- # part of its public contract (spec:
602
- # `docs/type-specification/rbs-extended.md` § "Explicit
603
- # conformance directive"). Unlike the per-method directives
604
- # above, this attaches to a `class` / `module` declaration and
605
- # names a single RBS interface (`_RewindableStream`); the
606
- # right-hand side is therefore an interface name (its last
607
- # segment begins with `_`), never a refinement payload.
528
+ # A class- / module-level directive declaring that the annotated class satisfies a named structural interface
529
+ # as part of its public contract (spec: `docs/type-specification/rbs-extended.md` § "Explicit conformance
530
+ # directive"). Unlike the per-method directives above, this attaches to a `class` / `module` declaration and
531
+ # names a single RBS interface (`_RewindableStream`); the right-hand side is therefore an interface name (its
532
+ # last segment begins with `_`), never a refinement payload.
608
533
  #
609
- # This parser only extracts the interface name; the
610
- # conformance check itself lives in
611
- # {Rigor::RbsExtended::ConformanceChecker}, which the
612
- # {Rigor::Analysis::Runner} runs once per project run.
534
+ # This parser only extracts the interface name; the conformance check itself lives in
535
+ # {Rigor::RbsExtended::ConformanceChecker}, which the {Rigor::Analysis::Runner} runs once per project run.
613
536
  CONFORMS_TO_DIRECTIVE_PATTERN = /
614
537
  \A
615
538
  rigor:v1:conforms-to
@@ -620,12 +543,10 @@ module Rigor
620
543
  /x
621
544
  private_constant :CONFORMS_TO_DIRECTIVE_PATTERN
622
545
 
623
- # Returns the interface name (leading `::` stripped) for a
624
- # `rigor:v1:conforms-to <Interface>` annotation, or `nil` when
625
- # the string is not a conforms-to directive (so callers can
626
- # walk an annotation list without pre-filtering). The name is
627
- # returned verbatim otherwise — namespace resolution happens at
628
- # the loader boundary when the interface is built.
546
+ # Returns the interface name (leading `::` stripped) for a `rigor:v1:conforms-to <Interface>` annotation, or
547
+ # `nil` when the string is not a conforms-to directive (so callers can walk an annotation list without
548
+ # pre-filtering). The name is returned verbatim otherwise namespace resolution happens at the loader
549
+ # boundary when the interface is built.
629
550
  def parse_conforms_to_annotation(string)
630
551
  return nil if string.nil?
631
552
 
@@ -635,11 +556,9 @@ module Rigor
635
556
  match[:interface].to_s.sub(/\A::/, "")
636
557
  end
637
558
 
638
- # The shared {Rigor::FlowContribution::Provenance} for every
639
- # bundle this module produces. `source_family: :rbs_extended`
640
- # so consumers (today the documentation surface; v0.1.0 the
641
- # plugin contribution merger) can attribute facts back to the
642
- # RBS::Extended layer.
559
+ # The shared {Rigor::FlowContribution::Provenance} for every bundle this module produces.
560
+ # `source_family: :rbs_extended` so consumers (today the documentation surface; v0.1.0 the plugin contribution
561
+ # merger) can attribute facts back to the RBS::Extended layer.
643
562
  RBS_EXTENDED_PROVENANCE = FlowContribution::Provenance.new(
644
563
  source_family: :rbs_extended,
645
564
  plugin_id: nil,
@@ -647,10 +566,8 @@ module Rigor
647
566
  descriptor: nil
648
567
  ).freeze
649
568
 
650
- # Rolls up every recognised RBS::Extended directive on
651
- # `method_def` into a single {Rigor::FlowContribution} with
652
- # the canonical {Rigor::FlowContribution::Fact} payload (see
653
- # ADR-7 § "Slice 4-A"):
569
+ # Rolls up every recognised RBS::Extended directive on `method_def` into a single {Rigor::FlowContribution}
570
+ # with the canonical {Rigor::FlowContribution::Fact} payload (see ADR-7 § "Slice 4-A"):
654
571
  #
655
572
  # - `predicate-if-true` → `truthy_facts`
656
573
  # - `predicate-if-false` → `falsey_facts`
@@ -659,18 +576,14 @@ module Rigor
659
576
  # - `assert-if-false` → `falsey_facts`
660
577
  # - `return:` override → `return_type` (`Rigor::Type`)
661
578
  #
662
- # Param overrides are intentionally NOT included — they refine
663
- # the call's signature contract rather than its flow facts and
664
- # do not fit ADR-2 § "Flow Contribution Bundle" slot semantics.
665
- # Callers that care about parameter contracts keep using
666
- # {.read_param_type_overrides} / {.param_type_override_map}.
579
+ # Param overrides are intentionally NOT included — they refine the call's signature contract rather than its
580
+ # flow facts and do not fit ADR-2 § "Flow Contribution Bundle" slot semantics. Callers that care about
581
+ # parameter contracts keep using {.read_param_type_overrides} / {.param_type_override_map}.
667
582
  #
668
- # Returns `nil` when the method carries no recognised
669
- # contribution directives (callers can skip the merge step
670
- # without iterating an empty bundle).
583
+ # Returns `nil` when the method carries no recognised contribution directives (callers can skip the merge
584
+ # step without iterating an empty bundle).
671
585
  #
672
- # See {.read_predicate_effects} for the `environment:`
673
- # keyword contract.
586
+ # See {.read_predicate_effects} for the `environment:` keyword contract.
674
587
  def read_flow_contribution(method_def, environment: nil)
675
588
  return nil if method_def.nil?
676
589
 
@@ -708,12 +621,9 @@ module Rigor
708
621
  facts.empty? ? nil : facts
709
622
  end
710
623
 
711
- # ADR-13 slice 3b — guards every reporter call so the
712
- # in-RbsExtended-module call sites can record events
713
- # uniformly without nil-checking each time. When the
714
- # reporter is nil (the v0.1.0 → v0.1.3 default for call
715
- # sites that do not yet thread `environment:`), the call is
716
- # a no-op and the parser stays fail-soft.
624
+ # ADR-13 slice 3b — guards every reporter call so the in-RbsExtended-module call sites can record events
625
+ # uniformly without nil-checking each time. When the reporter is nil (the v0.1.0 → v0.1.3 default for call
626
+ # sites that do not yet thread `environment:`), the call is a no-op and the parser stays fail-soft.
717
627
  def record_unresolved(reporter, payload, source_location)
718
628
  return if reporter.nil?
719
629