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
@@ -4,29 +4,22 @@ require "rbs"
4
4
 
5
5
  module Rigor
6
6
  module SigGen
7
- # Pre-scans every `.rbs` file under the configured
8
- # `signature_paths` to build a `qualified_class_name →
7
+ # Pre-scans every `.rbs` file under the configured `signature_paths` to build a `qualified_class_name →
9
8
  # sig_file_path` map.
10
9
  #
11
- # ADR-14 path-mapper limitation surfaced repeatedly during
12
- # the self-dogfood: the existing rigor `sig/` consolidates
13
- # multiple `.rb` sources into one `.rbs` file (e.g.
14
- # `sig/rigor/type.rbs` declares all 14 `Type::*` classes,
15
- # `sig/rigor.rbs` declares `CLI::TypeOfCommand` and
16
- # `CLI::TypeScanCommand`). The naive 1:1 mapper writes new
17
- # files alongside the existing consolidated ones, producing
10
+ # ADR-14 path-mapper limitation surfaced repeatedly during the self-dogfood: the existing rigor `sig/`
11
+ # consolidates multiple `.rb` sources into one `.rbs` file (e.g. `sig/rigor/type.rbs` declares all 14
12
+ # `Type::*` classes, `sig/rigor.rbs` declares `CLI::TypeOfCommand` and `CLI::TypeScanCommand`). The naive
13
+ # 1:1 mapper writes new files alongside the existing consolidated ones, producing
18
14
  # `RBS::DuplicatedMethodDefinition` errors at lookup time.
19
15
  #
20
- # The index lets {PathMapper} route a candidate to the
21
- # consolidated sig file when the class is already declared
22
- # there, falling back to the 1:1 mirror only when the
23
- # class has no existing declaration anywhere under the
24
- # signature tree.
16
+ # The index lets {PathMapper} route a candidate to the consolidated sig file when the class is already
17
+ # declared there, falling back to the 1:1 mirror only when the class has no existing declaration anywhere
18
+ # under the signature tree.
25
19
  #
26
- # First-found wins on duplicate declarations across files;
27
- # RBS itself allows the same class to be declared in
28
- # multiple files for additive member contributions, but
29
- # the writer only needs one canonical target per class.
20
+ # First-found wins on duplicate declarations across files; RBS itself allows the same class to be declared
21
+ # in multiple files for additive member contributions, but the writer only needs one canonical target per
22
+ # class.
30
23
  class LayoutIndex
31
24
  # @param signature_paths [Array<String, Pathname>, nil]
32
25
  # the `.rigor.yml`-configured signature directories.
@@ -84,8 +77,7 @@ module Rigor
84
77
  _, _, decls = RBS::Parser.parse_signature(source)
85
78
  record_decls(decls, [], rbs_path, accumulator)
86
79
  rescue StandardError
87
- # Bad RBS file — skip silently; the user's `rigor
88
- # check` run will surface the real parse error
80
+ # Bad RBS file — skip silently; the user's `rigor check` run will surface the real parse error
89
81
  # elsewhere.
90
82
  end
91
83
 
@@ -4,24 +4,20 @@ module Rigor
4
4
  module SigGen
5
5
  # Per-method record produced by the generator.
6
6
  #
7
- # `classification` is one of the {Classification} constants;
8
- # the remaining fields are populated only when applicable
9
- # to that classification.
7
+ # `classification` is one of the {Classification} constants; the remaining fields are populated only when
8
+ # applicable to that classification.
10
9
  #
11
10
  # - `path` — the source `.rb` file the def came from.
12
- # - `class_name` — qualified receiver class name (e.g.
13
- # `"Foo::Bar"`). `nil` for top-level / DSL-block defs
11
+ # - `class_name` — qualified receiver class name (e.g. `"Foo::Bar"`). `nil` for top-level / DSL-block defs
14
12
  # the MVP skips.
15
13
  # - `method_name` — the def's `Symbol` name.
16
14
  # - `kind` — `:instance` or `:singleton`.
17
- # - `inferred_return` — `Rigor::Type` instance (or `nil`
18
- # when the inference pass disqualified the def).
19
- # - `declared_return_rbs` — the existing RBS-declared return
20
- # spelling, or `nil` when no RBS declares the method.
21
- # - `rbs` — the rendered RBS one-liner the generator would
22
- # emit (`nil` for skipped / equivalent rows).
23
- # - `skip_reason` — one of {Classification::SKIP_DIAGNOSTIC_IDS}
24
- # keys when classification is `:skipped`, else `nil`.
15
+ # - `inferred_return` — `Rigor::Type` instance (or `nil` when the inference pass disqualified the def).
16
+ # - `declared_return_rbs` — the existing RBS-declared return spelling, or `nil` when no RBS declares the
17
+ # method.
18
+ # - `rbs` the rendered RBS one-liner the generator would emit (`nil` for skipped / equivalent rows).
19
+ # - `skip_reason` — one of {Classification::SKIP_DIAGNOSTIC_IDS} keys when classification is `:skipped`,
20
+ # else `nil`.
25
21
  class MethodCandidate
26
22
  attr_reader :path, :class_name, :method_name, :kind, :classification,
27
23
  :inferred_return, :declared_return_rbs, :rbs, :skip_reason,
@@ -41,10 +37,9 @@ module Rigor
41
37
  @skip_reason = skip_reason
42
38
  @namespace_kinds = namespace_kinds.freeze
43
39
  @class_shells = class_shells.freeze
44
- # Qualified-class-name => superclass source token (e.g.
45
- # `{ "Foo::Bar" => "Base" }`). Only plain-constant
46
- # superclasses appear; computed ones are absent. The Writer
47
- # emits `class Bar < Base` for the leaf when present.
40
+ # Qualified-class-name => superclass source token (e.g. `{ "Foo::Bar" => "Base" }`). Only plain-constant
41
+ # superclasses appear; computed ones are absent. The Writer emits `class Bar < Base` for the leaf when
42
+ # present.
48
43
  @class_superclasses = class_superclasses.freeze
49
44
  freeze
50
45
  end
@@ -10,37 +10,26 @@ require_relative "../inference/scope_indexer"
10
10
 
11
11
  module Rigor
12
12
  module SigGen
13
- # ADR-14 slice 3 — caller-side argument-type observation
14
- # collector.
13
+ # ADR-14 slice 3 — caller-side argument-type observation collector.
15
14
  #
16
- # Walks the user-supplied `--observe=PATH...` tree (default
17
- # `spec/`), parses every `.rb` file with `Prism`, scope-
18
- # indexes it the same way the main generator does, and
19
- # records the per-call-site argument-type tuples for every
20
- # `Prism::CallNode` whose receiver types as a
21
- # `Type::Nominal`. The {Generator} consumes the resulting
22
- # map to render `--params=observed` RBS:
15
+ # Walks the user-supplied `--observe=PATH...` tree (default `spec/`), parses every `.rb` file with `Prism`,
16
+ # scope- indexes it the same way the main generator does, and records the per-call-site argument-type tuples
17
+ # for every `Prism::CallNode` whose receiver types as a `Type::Nominal`. The {Generator} consumes the
18
+ # resulting map to render `--params=observed` RBS:
23
19
  #
24
- # @return [Hash{[class_name, method_name] =>
25
- # Array<Array<Rigor::Type>>}]
20
+ # @return [Hash{[class_name, method_name] => Array<Array<Rigor::Type>>}]
26
21
  #
27
- # ADR-5 clause 2 compliance: the observed union is the
28
- # MOST PERMISSIVE parameter contract the existing callers
29
- # prove sufficient by construction it accepts every type
30
- # any caller has already passed. The collector only
31
- # surfaces the data; the default `--params=untyped` keeps
32
- # the observation inert until the user opts in.
22
+ # ADR-5 clause 2 compliance: the observed union is the MOST PERMISSIVE parameter contract the existing
23
+ # callers prove sufficient by construction it accepts every type any caller has already passed. The
24
+ # collector only surfaces the data; the default `--params=untyped` keeps the observation inert until the
25
+ # user opts in.
33
26
  #
34
27
  # MVP scope:
35
- # - Explicit-receiver calls only (`foo.bar(args)`). Implicit-
36
- # self calls inside class bodies and RSpec-style
37
- # `let` / `subject` bindings ride on slice 5's optional
38
- # `rigor-rspec` integration.
39
- # - Calls whose receiver does not type as a `Type::Nominal`
40
- # (e.g. `(some_dynamic).bar(...)`) are skipped — the
41
- # collector cannot attribute them to a specific class.
42
- # - Zero-argument calls give no observation; methods are
43
- # matched by `(class_name, method_name)` only.
28
+ # - Explicit-receiver calls only (`foo.bar(args)`). Implicit-self calls inside class bodies and RSpec-style
29
+ # `let` / `subject` bindings ride on slice 5's optional `rigor-rspec` integration.
30
+ # - Calls whose receiver does not type as a `Type::Nominal` (e.g. `(some_dynamic).bar(...)`) are skipped
31
+ # the collector cannot attribute them to a specific class.
32
+ # - Zero-argument calls give no observation; methods are matched by `(class_name, method_name)` only.
44
33
  class ObservationCollector # rubocop:disable Metrics/ClassLength
45
34
  # @param configuration [Rigor::Configuration]
46
35
  # @param paths [Array<String>] observe paths (files /
@@ -104,11 +93,9 @@ module Rigor
104
93
  walk_calls(parse_result.value, scope_index, bindings, observations)
105
94
  end
106
95
 
107
- # Pre-walks `@source_paths` to collect every qualified
108
- # class / module declaration. The result seeds the
109
- # `discovered_classes` table on each observe-tree scope so
110
- # `Foo.new` and `Foo` resolve to the right singleton carrier
111
- # even when no RBS sig describes `Foo` yet.
96
+ # Pre-walks `@source_paths` to collect every qualified class / module declaration. The result seeds the
97
+ # `discovered_classes` table on each observe-tree scope so `Foo.new` and `Foo` resolve to the right
98
+ # singleton carrier even when no RBS sig describes `Foo` yet.
112
99
  def preindex_source_classes
113
100
  accumulator = {}
114
101
  resolve_paths(@source_paths).each { |path| harvest_classes_from(path, accumulator) }
@@ -122,8 +109,7 @@ module Rigor
122
109
 
123
110
  walk_class_decls(parse_result.value, [], accumulator)
124
111
  rescue StandardError
125
- # Source-side harvest failures are tolerated silently
126
- # — the collector still runs on whichever files
112
+ # Source-side harvest failures are tolerated silently — the collector still runs on whichever files
127
113
  # parsed cleanly.
128
114
  end
129
115
 
@@ -180,13 +166,10 @@ module Rigor
180
166
  observations[key] << observation
181
167
  end
182
168
 
183
- # ADR-14 follow-up (A): `.new` → `:initialize` routing.
184
- # `MethodCatalog.new(path: ...)` types its receiver as
185
- # `Type::Singleton[MethodCatalog]` and its call name as
186
- # `:new`, but the *implicit* effect at runtime is a call
187
- # to `MethodCatalog#initialize(path: ...)`. Route the
188
- # observation under `[class_name, :initialize]` so the
189
- # initialize-stub renderer can consult it.
169
+ # ADR-14 follow-up (A): `.new` → `:initialize` routing. `MethodCatalog.new(path: ...)` types its receiver
170
+ # as `Type::Singleton[MethodCatalog]` and its call name as `:new`, but the *implicit* effect at runtime is
171
+ # a call to `MethodCatalog#initialize(path: ...)`. Route the observation under `[class_name, :initialize]`
172
+ # so the initialize-stub renderer can consult it.
190
173
  def observation_key(call_node, receiver_type)
191
174
  if receiver_type.is_a?(Type::Singleton) && call_node.name == :new
192
175
  [receiver_type.class_name, :initialize]
@@ -195,20 +178,15 @@ module Rigor
195
178
  end
196
179
  end
197
180
 
198
- # ADR-14 slice 5 — RSpec-aware receiver typing.
199
- # Resolves a CallNode receiver against the collected
200
- # `bindings` map (built by {#collect_rspec_bindings})
201
- # before falling back to ordinary `scope.type_of`. The
181
+ # ADR-14 slice 5 — RSpec-aware receiver typing. Resolves a CallNode receiver against the collected
182
+ # `bindings` map (built by {#collect_rspec_bindings}) before falling back to ordinary `scope.type_of`. The
202
183
  # three RSpec-shaped receivers we recognise:
203
184
  #
204
- # - Bare-name CallNode (`subject`, `other`, ...) whose
205
- # name matches a `subject` / `let(:name)` binding —
185
+ # - Bare-name CallNode (`subject`, `other`, ...) whose name matches a `subject` / `let(:name)` binding —
206
186
  # return the binding's recorded type.
207
- # - `described_class.new(...)` chain — when the
208
- # surrounding `describe Foo do … end` resolved `Foo`,
187
+ # - `described_class.new(...)` chain — when the surrounding `describe Foo do … end` resolved `Foo`,
209
188
  # return `Type::Nominal[Foo]`.
210
- # - Anything else — pass through to `scope.type_of`,
211
- # matching slice-3 behaviour.
189
+ # - Anything else — pass through to `scope.type_of`, matching slice-3 behaviour.
212
190
  def resolve_receiver_type(receiver, scope, bindings)
213
191
  return resolve_described_class_new(bindings) if described_class_new?(receiver)
214
192
  return bindings[receiver.name] if bound_call?(receiver, bindings)
@@ -246,21 +224,14 @@ module Rigor
246
224
  node.block.nil?
247
225
  end
248
226
 
249
- # Walks the spec file for `describe X do … end` /
250
- # `RSpec.describe X do end` blocks plus the
251
- # `subject` / `let(:name)` declarations inside them.
252
- # Returns a flat map `{ binding_name (Symbol) => Type }`
253
- # plus a synthetic `:described_class` slot keyed off
254
- # the nearest enclosing `describe`.
227
+ # Walks the spec file for `describe X do … end` / `RSpec.describe X do … end` blocks plus the
228
+ # `subject` / `let(:name)` declarations inside them. Returns a flat map `{ binding_name (Symbol) => Type }`
229
+ # plus a synthetic `:described_class` slot keyed off the nearest enclosing `describe`.
255
230
  #
256
- # The recogniser is intentionally lightweight: it does
257
- # not enforce RSpec scope rules across `describe` /
258
- # `context` blocks. Nested `describe` declarations
259
- # overwrite the outer `described_class` for the
260
- # remainder of the walk; same-name `let` bindings are
261
- # last-wins. This matches the typical one-spec-file
262
- # shape ADR-14 slice 5 targets without re-implementing
263
- # the `rigor-rspec` plugin's full scope analyser.
231
+ # The recogniser is intentionally lightweight: it does not enforce RSpec scope rules across `describe` /
232
+ # `context` blocks. Nested `describe` declarations overwrite the outer `described_class` for the
233
+ # remainder of the walk; same-name `let` bindings are last-wins. This matches the typical one-spec-file
234
+ # shape ADR-14 slice 5 targets without re-implementing the `rigor-rspec` plugin's full scope analyser.
264
235
  def collect_rspec_bindings(root, scope_index)
265
236
  bindings = {}
266
237
  walk_rspec_bindings(root, bindings, scope_index)
@@ -339,12 +310,9 @@ module Rigor
339
310
  end
340
311
  end
341
312
 
342
- # ADR-14 follow-up (B): walks a call's argument list
343
- # separating positional from keyword arguments and
344
- # returning an {ObservedCall} carrier. Splat /
345
- # forwarded / block arguments still abort the
346
- # observation (`nil`) — those don't map cleanly to a
347
- # single per-position type the renderer can union.
313
+ # ADR-14 follow-up (B): walks a call's argument list separating positional from keyword arguments and
314
+ # returning an {ObservedCall} carrier. Splat / forwarded / block arguments still abort the observation
315
+ # (`nil`) those don't map cleanly to a single per-position type the renderer can union.
348
316
  def collect_args(call_node, scope)
349
317
  positional = []
350
318
  keyword = {}
@@ -2,27 +2,19 @@
2
2
 
3
3
  module Rigor
4
4
  module SigGen
5
- # Per-call-site argument observation produced by
6
- # {ObservationCollector}. ADR-14 follow-up: the earlier
7
- # MVP shape (`Array[Type]` of positional types only)
8
- # could not represent keyword arguments keyword calls
9
- # like `MethodCatalog.new(path: ..., mutating_selectors: ...)`
10
- # were silently skipped in that shape.
11
- # The new shape carries positional and keyword arg types
12
- # in parallel so the per-position / per-keyword unions
13
- # can each be reconstructed independently.
5
+ # Per-call-site argument observation produced by {ObservationCollector}. ADR-14 follow-up: the earlier MVP
6
+ # shape (`Array[Type]` of positional types only) could not represent keyword arguments — keyword calls like
7
+ # `MethodCatalog.new(path: ..., mutating_selectors: ...)` were silently skipped in that shape. The new shape
8
+ # carries positional and keyword arg types in parallel so the per-position / per-keyword unions can each be
9
+ # reconstructed independently.
14
10
  #
15
11
  # The carrier is intentionally minimal:
16
- # - `positional` — frozen Array of `Rigor::Type` per
17
- # positional argument, in call-site order.
18
- # - `keyword` — frozen Hash mapping each keyword
19
- # argument's Symbol name to its `Rigor::Type`.
12
+ # - `positional` — frozen Array of `Rigor::Type` per positional argument, in call-site order.
13
+ # - `keyword` — frozen Hash mapping each keyword argument's Symbol name to its `Rigor::Type`.
20
14
  #
21
- # Generator-side callers also accept a legacy shape
22
- # (plain Array of types) for backward compatibility with
23
- # specs that constructed observations directly before
24
- # this carrier existed; `ObservedCall.from(...)` does the
25
- # lift.
15
+ # Generator-side callers also accept a legacy shape (plain Array of types) for backward compatibility with
16
+ # specs that constructed observations directly before this carrier existed; `ObservedCall.from(...)` does
17
+ # the lift.
26
18
  class ObservedCall
27
19
  attr_reader :positional, :keyword
28
20
 
@@ -45,11 +37,9 @@ module Rigor
45
37
  [ObservedCall, positional, keyword].hash
46
38
  end
47
39
 
48
- # Lifts the legacy plain-Array shape into an
49
- # `ObservedCall` carrier. Already-lifted values pass
50
- # through unchanged. Used by `Generator#initialize`'s
51
- # observations-normalisation pass so spec fixtures
52
- # written against the slice-3 surface keep working.
40
+ # Lifts the legacy plain-Array shape into an `ObservedCall` carrier. Already-lifted values pass through
41
+ # unchanged. Used by `Generator#initialize`'s observations-normalisation pass so spec fixtures written
42
+ # against the slice-3 surface keep working.
53
43
  def self.from(value)
54
44
  case value
55
45
  when ObservedCall then value
@@ -2,33 +2,24 @@
2
2
 
3
3
  module Rigor
4
4
  module SigGen
5
- # Maps a source `.rb` file to its target `.rbs` sig file
6
- # under the project's signature tree.
5
+ # Maps a source `.rb` file to its target `.rbs` sig file under the project's signature tree.
7
6
  #
8
7
  # ADR-14 § "Output layout":
9
- # - `--write` MUST NOT touch files outside
10
- # `configuration.signature_paths` (default `sig/`).
11
- # - The first slice supports one source file → one RBS
12
- # file; multi-class files emit one RBS containing both
8
+ # - `--write` MUST NOT touch files outside `configuration.signature_paths` (default `sig/`).
9
+ # - The first slice supports one source file → one RBS file; multi-class files emit one RBS containing both
13
10
  # classes (handled by the {Writer}, not here).
14
11
  #
15
- # The mapping convention mirrors the Ruby community
16
- # default: strip the source root prefix (the first entry
17
- # of `configuration.paths`, typically `"lib"`), swap the
18
- # extension, and place the result under the first entry of
19
- # `configuration.signature_paths` (typically `"sig"`).
12
+ # The mapping convention mirrors the Ruby community default: strip the source root prefix (the first entry
13
+ # of `configuration.paths`, typically `"lib"`), swap the extension, and place the result under the first
14
+ # entry of `configuration.signature_paths` (typically `"sig"`).
20
15
  #
21
- # ADR-14 follow-up: when a class is already declared in
22
- # an existing consolidated sig file (e.g. `sig/rigor/type.rbs`
23
- # holds all `Rigor::Type::*` classes), the optional
24
- # `LayoutIndex` re-routes the target to that file so the
25
- # writer updates the consolidated declaration instead of
26
- # creating a duplicate at the 1:1 mirror path.
16
+ # ADR-14 follow-up: when a class is already declared in an existing consolidated sig file (e.g.
17
+ # `sig/rigor/type.rbs` holds all `Rigor::Type::*` classes), the optional `LayoutIndex` re-routes the target
18
+ # to that file so the writer updates the consolidated declaration instead of creating a duplicate at the 1:1
19
+ # mirror path.
27
20
  #
28
- # When the source path is not under any configured source
29
- # root (e.g. files supplied directly on the CLI from
30
- # outside `lib/`), the full relative path is preserved
31
- # under the sig root.
21
+ # When the source path is not under any configured source root (e.g. files supplied directly on the CLI
22
+ # from outside `lib/`), the full relative path is preserved under the sig root.
32
23
  class PathMapper
33
24
  # @param configuration [Rigor::Configuration]
34
25
  # @param project_root [String, Pathname] (defaults to `Dir.pwd`)
@@ -63,9 +54,8 @@ module Rigor
63
54
  @layout_index.file_for(class_name)
64
55
  end
65
56
 
66
- # The directory `--write` is allowed to create / modify.
67
- # Used by callers to assert the target stays inside the
68
- # configured signature tree before touching the disk.
57
+ # The directory `--write` is allowed to create / modify. Used by callers to assert the target stays inside
58
+ # the configured signature tree before touching the disk.
69
59
  def sig_root_dir
70
60
  @sig_root_dir ||= @project_root / sig_root_name
71
61
  end
@@ -76,8 +66,7 @@ module Rigor
76
66
  path = Pathname(source_path)
77
67
  return path unless path.absolute?
78
68
 
79
- # Both sides go through realpath so macOS `/tmp` vs
80
- # `/private/tmp` (and any other symlinked project
69
+ # Both sides go through realpath so macOS `/tmp` vs `/private/tmp` (and any other symlinked project
81
70
  # root) compare cleanly.
82
71
  path.realpath.relative_path_from(@project_root.realpath)
83
72
  rescue ArgumentError, Errno::ENOENT
@@ -95,9 +84,8 @@ module Rigor
95
84
  components.empty? ? Pathname("") : Pathname(components.join(File::SEPARATOR))
96
85
  end
97
86
 
98
- # `Configuration` resolves `paths:` and `signature_paths:`
99
- # to absolute Strings. We only need the trailing basename
100
- # for the mapping (`/abs/lib` → `lib`, `/abs/app` → `app`).
87
+ # `Configuration` resolves `paths:` and `signature_paths:` to absolute Strings. We only need the trailing
88
+ # basename for the mapping (`/abs/lib` `lib`, `/abs/app` → `app`).
101
89
  def source_root_name
102
90
  @source_root_name ||= begin
103
91
  path = @configuration.paths.first
@@ -9,16 +9,12 @@ module Rigor
9
9
  # Output formatter for `rigor sig-gen`.
10
10
  #
11
11
  # Supports three modes:
12
- # - `:print` (default) — RBS skeletons grouped by source
13
- # file and class declaration, ready for the user to
12
+ # - `:print` (default) — RBS skeletons grouped by source file and class declaration, ready for the user to
14
13
  # paste into `sig/<path>.rbs`.
15
- # - `:diff` — a unified-style diff comparing the existing
16
- # RBS spelling (if any) against the inferred spelling.
17
- # The MVP renders a minimal "- declared / + inferred"
18
- # block; full per-file diffing arrives with slice 2's
19
- # `--write` merge.
20
- # - `:json` — machine-readable payload with the same
21
- # classification table as `:print`.
14
+ # - `:diff` — a unified-style diff comparing the existing RBS spelling (if any) against the inferred
15
+ # spelling. The MVP renders a minimal "- declared / + inferred" block; full per-file diffing arrives with
16
+ # slice 2's `--write` merge.
17
+ # - `:json` — machine-readable payload with the same classification table as `:print`.
22
18
  class Renderer
23
19
  def initialize(out:)
24
20
  @out = out
@@ -107,10 +103,8 @@ module Rigor
107
103
 
108
104
  public
109
105
 
110
- # Renders the per-source-file outcomes of a `--write`
111
- # run. Distinct from {#render} because the write
112
- # path's reporting surface is action-oriented (created
113
- # / updated / skipped) rather than candidate-oriented.
106
+ # Renders the per-source-file outcomes of a `--write` run. Distinct from {#render} because the write
107
+ # path's reporting surface is action-oriented (created / updated / skipped) rather than candidate-oriented.
114
108
  def render_write(results:, format:)
115
109
  case format
116
110
  when "json" then render_write_json(results)
@@ -5,30 +5,20 @@ require_relative "../type"
5
5
 
6
6
  module Rigor
7
7
  module SigGen
8
- # ADR-14 follow-up to the dogfood findings: when the
9
- # inference engine produces a `Type::Nominal` for a class
10
- # that requires type parameters (`Array`, `Hash`, `Set`,
11
- # `Range`, `Enumerable`, `Enumerator`, ...) with an empty
12
- # `type_args` array, the carrier is structurally valid but
13
- # `erase_to_rbs` renders just `Array` / `Hash` / etc. While
14
- # RBS itself accepts the bare form, downstream consumers
15
- # (Steep, IDE plugins, gem-published `sig/` trees) expect
16
- # the elaborated `Array[untyped]` / `Hash[untyped, untyped]`
17
- # spelling.
8
+ # ADR-14 follow-up to the dogfood findings: when the inference engine produces a `Type::Nominal` for a class
9
+ # that requires type parameters (`Array`, `Hash`, `Set`, `Range`, `Enumerable`, `Enumerator`, ...) with an
10
+ # empty `type_args` array, the carrier is structurally valid but `erase_to_rbs` renders just `Array` /
11
+ # `Hash` / etc. While RBS itself accepts the bare form, downstream consumers (Steep, IDE plugins,
12
+ # gem-published `sig/` trees) expect the elaborated `Array[untyped]` / `Hash[untyped, untyped]` spelling.
18
13
  #
19
- # This module walks a `Rigor::Type` tree and rebuilds every
20
- # raw `Nominal[C]` for a generic `C` into `Nominal[C, [Dynamic, ...]]`
21
- # where the arity comes from
22
- # `Reflection.class_type_param_names`. The transformation is
23
- # purely cosmetic — the resulting carrier is structurally
24
- # distinct from the raw form, but `accepts(other) == accepts(other)`
25
- # holds because the gradual mode treats `Dynamic[top]`
26
- # arguments as covering anything.
14
+ # This module walks a `Rigor::Type` tree and rebuilds every raw `Nominal[C]` for a generic `C` into
15
+ # `Nominal[C, [Dynamic, ...]]` where the arity comes from `Reflection.class_type_param_names`. The
16
+ # transformation is purely cosmetic — the resulting carrier is structurally distinct from the raw form, but
17
+ # `accepts(other) == accepts(other)` holds because the gradual mode treats `Dynamic[top]` arguments as
18
+ # covering anything.
27
19
  #
28
- # The module is sig-gen-local; the broader question of
29
- # whether the inference engine itself should always
30
- # construct generics with explicit type_args is queued as
31
- # an ADR-14 follow-up.
20
+ # The module is sig-gen-local; the broader question of whether the inference engine itself should always
21
+ # construct generics with explicit type_args is queued as an ADR-14 follow-up.
32
22
  module TypeElaborator
33
23
  # @param type [Rigor::Type]
34
24
  # @param environment [Rigor::Environment]
@@ -70,12 +60,9 @@ module Rigor
70
60
  end
71
61
 
72
62
  def self.elaborate_hash_shape(type, _environment, _arity_cache)
73
- # HashShape's element types are read-only on the carrier;
74
- # rebuilding them would need going through the per-pair
75
- # required/optional/read-only machinery. Sig-gen only
76
- # routes top-level returns through here for now —
77
- # nested HashShape elaboration ships as a follow-up if
78
- # the need surfaces.
63
+ # HashShape's element types are read-only on the carrier; rebuilding them would need going through the
64
+ # per-pair required/optional/read-only machinery. Sig-gen only routes top-level returns through here for
65
+ # now nested HashShape elaboration ships as a follow-up if the need surfaces.
79
66
  type
80
67
  end
81
68
 
@@ -4,24 +4,16 @@ module Rigor
4
4
  module SigGen
5
5
  # Per-source-file outcome of a `rigor sig-gen --write` run.
6
6
  #
7
- # The writer reports back what it did so the renderer (and
8
- # the CLI's exit-status logic) can summarise actions and
9
- # surface user-authored-skip decisions without having to
10
- # re-parse the produced files.
7
+ # The writer reports back what it did so the renderer (and the CLI's exit-status logic) can summarise
8
+ # actions and surface user-authored-skip decisions without having to re-parse the produced files.
11
9
  #
12
10
  # - `source_path` — original `.rb` file.
13
- # - `target_path` — `.rbs` file the writer was responsible
14
- # for (`nil` when the source path falls outside the
15
- # project signature tree, in which case `action` is
16
- # `:skipped_outside_sig_root`).
17
- # - `action` — one of `:created` / `:updated` / `:noop` /
18
- # `:skipped_outside_sig_root`.
19
- # - `applied` — the {MethodCandidate}s that actually
20
- # landed on disk.
21
- # - `skipped` — the {MethodCandidate}s the writer
22
- # declined (e.g. tighter-return without `--overwrite`).
23
- # Each entry pairs the candidate with a skip reason
24
- # keyword (`:user_authored`).
11
+ # - `target_path` — `.rbs` file the writer was responsible for (`nil` when the source path falls outside
12
+ # the project signature tree, in which case `action` is `:skipped_outside_sig_root`).
13
+ # - `action` one of `:created` / `:updated` / `:noop` / `:skipped_outside_sig_root`.
14
+ # - `applied` — the {MethodCandidate}s that actually landed on disk.
15
+ # - `skipped` — the {MethodCandidate}s the writer declined (e.g. tighter-return without `--overwrite`). Each
16
+ # entry pairs the candidate with a skip reason keyword (`:user_authored`).
25
17
  class WriteResult
26
18
  attr_reader :source_path, :target_path, :action, :applied, :skipped
27
19