rigortype 0.2.7 → 0.2.9

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 (433) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/data/core_overlay/csv.rbs +28 -0
  4. data/data/core_overlay/psych.rbs +22 -0
  5. data/docs/handbook/01-getting-started.md +9 -1
  6. data/docs/handbook/02-everyday-types.md +4 -1
  7. data/docs/handbook/08-understanding-errors.md +3 -3
  8. data/docs/manual/01-installation.md +1 -0
  9. data/docs/manual/02-cli-reference.md +16 -7
  10. data/docs/manual/04-diagnostics.md +7 -4
  11. data/docs/manual/06-baseline.md +5 -2
  12. data/docs/manual/07-plugins.md +1 -1
  13. data/docs/manual/14-rails-quickstart.md +4 -2
  14. data/docs/manual/15-type-protection-coverage.md +27 -4
  15. data/docs/manual/plugins/rigor-actionpack.md +1 -1
  16. data/docs/manual/plugins/rigor-activerecord.md +12 -5
  17. data/docs/manual/plugins/rigor-rails-routes.md +11 -0
  18. data/lib/rigor/analysis/baseline.rb +56 -96
  19. data/lib/rigor/analysis/buffer_binding.rb +13 -20
  20. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +29 -48
  21. data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +35 -54
  22. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +23 -37
  23. data/lib/rigor/analysis/check_rules/main_pass_collector.rb +16 -23
  24. data/lib/rigor/analysis/check_rules/rule_walk.rb +48 -71
  25. data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +19 -28
  26. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +48 -67
  27. data/lib/rigor/analysis/check_rules.rb +174 -274
  28. data/lib/rigor/analysis/dependency_recorder.rb +26 -38
  29. data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +13 -25
  30. data/lib/rigor/analysis/dependency_source_inference/builder.rb +17 -30
  31. data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +15 -26
  32. data/lib/rigor/analysis/dependency_source_inference/index.rb +45 -76
  33. data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +23 -40
  34. data/lib/rigor/analysis/dependency_source_inference/walker.rb +50 -83
  35. data/lib/rigor/analysis/dependency_source_inference.rb +6 -10
  36. data/lib/rigor/analysis/diagnostic.rb +48 -75
  37. data/lib/rigor/analysis/erb_template_detector.rb +13 -18
  38. data/lib/rigor/analysis/fact_store.rb +12 -22
  39. data/lib/rigor/analysis/incremental.rb +47 -63
  40. data/lib/rigor/analysis/incremental_session.rb +74 -100
  41. data/lib/rigor/analysis/project_scan.rb +12 -23
  42. data/lib/rigor/analysis/result.rb +3 -5
  43. data/lib/rigor/analysis/rule_catalog.rb +67 -95
  44. data/lib/rigor/analysis/run_stats.rb +38 -61
  45. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +101 -160
  46. data/lib/rigor/analysis/runner/pool_coordinator.rb +121 -188
  47. data/lib/rigor/analysis/runner/project_pre_passes.rb +62 -96
  48. data/lib/rigor/analysis/runner/run_snapshots.rb +12 -18
  49. data/lib/rigor/analysis/runner.rb +220 -333
  50. data/lib/rigor/analysis/self_call_resolution_recorder.rb +30 -43
  51. data/lib/rigor/analysis/worker_session.rb +64 -102
  52. data/lib/rigor/ast/type_node.rb +6 -8
  53. data/lib/rigor/ast.rb +6 -10
  54. data/lib/rigor/bleeding_edge.rb +27 -35
  55. data/lib/rigor/builtins/hkt_builtins.rb +7 -14
  56. data/lib/rigor/builtins/imported_refinements.rb +106 -149
  57. data/lib/rigor/builtins/predefined_constant_refinements.rb +51 -65
  58. data/lib/rigor/builtins/regex_refinement.rb +32 -43
  59. data/lib/rigor/builtins/static_return_refinements.rb +57 -81
  60. data/lib/rigor/cache/descriptor.rb +58 -94
  61. data/lib/rigor/cache/incremental_snapshot.rb +32 -48
  62. data/lib/rigor/cache/rbs_cache_producer.rb +10 -15
  63. data/lib/rigor/cache/rbs_class_ancestor_table.rb +10 -16
  64. data/lib/rigor/cache/rbs_class_type_param_names.rb +10 -16
  65. data/lib/rigor/cache/rbs_constant_table.rb +8 -13
  66. data/lib/rigor/cache/rbs_descriptor.rb +8 -13
  67. data/lib/rigor/cache/rbs_environment.rb +11 -19
  68. data/lib/rigor/cache/rbs_environment_marshal_patch.rb +11 -19
  69. data/lib/rigor/cache/rbs_known_class_names.rb +8 -12
  70. data/lib/rigor/cache/store.rb +248 -186
  71. data/lib/rigor/cli/annotate_command.rb +51 -88
  72. data/lib/rigor/cli/baseline_command.rb +10 -17
  73. data/lib/rigor/cli/check_command.rb +121 -199
  74. data/lib/rigor/cli/check_runner_factory.rb +8 -14
  75. data/lib/rigor/cli/ci_detector.rb +9 -14
  76. data/lib/rigor/cli/command.rb +8 -14
  77. data/lib/rigor/cli/coverage_command.rb +62 -48
  78. data/lib/rigor/cli/coverage_mutation.rb +14 -19
  79. data/lib/rigor/cli/coverage_report.rb +0 -2
  80. data/lib/rigor/cli/coverage_scan.rb +7 -11
  81. data/lib/rigor/cli/diagnostic_formats.rb +46 -62
  82. data/lib/rigor/cli/diff_command.rb +10 -20
  83. data/lib/rigor/cli/docs_command.rb +26 -40
  84. data/lib/rigor/cli/doctor_command.rb +8 -9
  85. data/lib/rigor/cli/explain_command.rb +4 -7
  86. data/lib/rigor/cli/fused_protection_renderer.rb +4 -5
  87. data/lib/rigor/cli/fused_protection_report.rb +6 -8
  88. data/lib/rigor/cli/lsp_command.rb +11 -19
  89. data/lib/rigor/cli/mcp_command.rb +4 -6
  90. data/lib/rigor/cli/mutation_protection_renderer.rb +3 -4
  91. data/lib/rigor/cli/mutation_protection_report.rb +6 -9
  92. data/lib/rigor/cli/options.rb +11 -19
  93. data/lib/rigor/cli/plugin_command.rb +18 -30
  94. data/lib/rigor/cli/plugins_command.rb +29 -51
  95. data/lib/rigor/cli/plugins_renderer.rb +12 -20
  96. data/lib/rigor/cli/prism_colorizer.rb +13 -19
  97. data/lib/rigor/cli/protection_fork_scan.rb +55 -0
  98. data/lib/rigor/cli/protection_renderer.rb +5 -7
  99. data/lib/rigor/cli/protection_report.rb +34 -18
  100. data/lib/rigor/cli/renderable.rb +4 -6
  101. data/lib/rigor/cli/show_bleedingedge_command.rb +5 -8
  102. data/lib/rigor/cli/sig_gen_command.rb +14 -26
  103. data/lib/rigor/cli/skill_command.rb +30 -47
  104. data/lib/rigor/cli/skill_describe.rb +40 -64
  105. data/lib/rigor/cli/trace_command.rb +9 -16
  106. data/lib/rigor/cli/trace_renderer.rb +35 -51
  107. data/lib/rigor/cli/triage_command.rb +6 -10
  108. data/lib/rigor/cli/triage_renderer.rb +1 -2
  109. data/lib/rigor/cli/type_of_command.rb +14 -23
  110. data/lib/rigor/cli/type_of_renderer.rb +3 -5
  111. data/lib/rigor/cli/type_scan_command.rb +6 -10
  112. data/lib/rigor/cli/type_scan_renderer.rb +3 -5
  113. data/lib/rigor/cli/type_scan_report.rb +2 -3
  114. data/lib/rigor/cli/upgrade_command.rb +2 -3
  115. data/lib/rigor/cli.rb +16 -28
  116. data/lib/rigor/config_audit.rb +35 -44
  117. data/lib/rigor/configuration/dependencies.rb +41 -70
  118. data/lib/rigor/configuration/severity_profile.rb +28 -42
  119. data/lib/rigor/configuration.rb +150 -241
  120. data/lib/rigor/environment/bundle_sig_discovery.rb +74 -118
  121. data/lib/rigor/environment/class_registry.rb +19 -26
  122. data/lib/rigor/environment/constant_type_cache_holder.rb +14 -21
  123. data/lib/rigor/environment/hkt_registry_holder.rb +6 -12
  124. data/lib/rigor/environment/lockfile_resolver.rb +31 -47
  125. data/lib/rigor/environment/missing_gem_constant_index.rb +128 -0
  126. data/lib/rigor/environment/rbs_collection_discovery.rb +39 -63
  127. data/lib/rigor/environment/rbs_coverage_report.rb +24 -42
  128. data/lib/rigor/environment/rbs_loader.rb +420 -518
  129. data/lib/rigor/environment/reflection.rb +28 -53
  130. data/lib/rigor/environment/reporters.rb +13 -24
  131. data/lib/rigor/environment.rb +225 -304
  132. data/lib/rigor/flow_contribution/conflict.rb +16 -27
  133. data/lib/rigor/flow_contribution/element.rb +7 -12
  134. data/lib/rigor/flow_contribution/fact.rb +33 -57
  135. data/lib/rigor/flow_contribution/merge_result.rb +6 -9
  136. data/lib/rigor/flow_contribution/merger.rb +32 -47
  137. data/lib/rigor/flow_contribution.rb +37 -55
  138. data/lib/rigor/inference/acceptance.rb +133 -219
  139. data/lib/rigor/inference/block_parameter_binder.rb +52 -82
  140. data/lib/rigor/inference/body_fixpoint.rb +22 -30
  141. data/lib/rigor/inference/budget_trace.rb +43 -63
  142. data/lib/rigor/inference/builtins/array_catalog.rb +4 -6
  143. data/lib/rigor/inference/builtins/comparable_catalog.rb +4 -6
  144. data/lib/rigor/inference/builtins/complex_catalog.rb +13 -19
  145. data/lib/rigor/inference/builtins/date_catalog.rb +38 -67
  146. data/lib/rigor/inference/builtins/encoding_catalog.rb +22 -36
  147. data/lib/rigor/inference/builtins/enumerable_catalog.rb +4 -6
  148. data/lib/rigor/inference/builtins/exception_catalog.rb +38 -57
  149. data/lib/rigor/inference/builtins/hash_catalog.rb +9 -14
  150. data/lib/rigor/inference/builtins/method_catalog.rb +29 -48
  151. data/lib/rigor/inference/builtins/numeric_catalog.rb +13 -18
  152. data/lib/rigor/inference/builtins/pathname_catalog.rb +8 -13
  153. data/lib/rigor/inference/builtins/proc_catalog.rb +38 -62
  154. data/lib/rigor/inference/builtins/random_catalog.rb +21 -32
  155. data/lib/rigor/inference/builtins/range_catalog.rb +12 -21
  156. data/lib/rigor/inference/builtins/rational_catalog.rb +9 -15
  157. data/lib/rigor/inference/builtins/re_catalog.rb +29 -48
  158. data/lib/rigor/inference/builtins/set_catalog.rb +18 -27
  159. data/lib/rigor/inference/builtins/string_catalog.rb +12 -19
  160. data/lib/rigor/inference/builtins/struct_catalog.rb +18 -30
  161. data/lib/rigor/inference/builtins/time_catalog.rb +28 -44
  162. data/lib/rigor/inference/closure_escape_analyzer.rb +44 -67
  163. data/lib/rigor/inference/coverage_scanner.rb +13 -18
  164. data/lib/rigor/inference/def_return_typer.rb +8 -14
  165. data/lib/rigor/inference/dynamic_origin.rb +23 -20
  166. data/lib/rigor/inference/expression_typer.rb +794 -1154
  167. data/lib/rigor/inference/fallback.rb +8 -12
  168. data/lib/rigor/inference/fallback_tracer.rb +4 -10
  169. data/lib/rigor/inference/flow_tracer.rb +25 -36
  170. data/lib/rigor/inference/fork_map.rb +87 -0
  171. data/lib/rigor/inference/hkt_body.rb +45 -68
  172. data/lib/rigor/inference/hkt_body_parser.rb +33 -52
  173. data/lib/rigor/inference/hkt_reducer.rb +38 -59
  174. data/lib/rigor/inference/hkt_registry.rb +50 -76
  175. data/lib/rigor/inference/indexed_narrowing.rb +55 -81
  176. data/lib/rigor/inference/macro_block_self_type.rb +21 -34
  177. data/lib/rigor/inference/method_dispatcher/array_to_h_folding.rb +11 -18
  178. data/lib/rigor/inference/method_dispatcher/block_folding.rb +49 -83
  179. data/lib/rigor/inference/method_dispatcher/call_context.rb +16 -23
  180. data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +13 -22
  181. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +307 -454
  182. data/lib/rigor/inference/method_dispatcher/data_folding.rb +24 -34
  183. data/lib/rigor/inference/method_dispatcher/file_folding.rb +22 -37
  184. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +52 -81
  185. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +51 -78
  186. data/lib/rigor/inference/method_dispatcher/literal_string_folding.rb +60 -97
  187. data/lib/rigor/inference/method_dispatcher/math_folding.rb +23 -34
  188. data/lib/rigor/inference/method_dispatcher/member_shape_projection.rb +18 -26
  189. data/lib/rigor/inference/method_dispatcher/method_folding.rb +37 -71
  190. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +114 -182
  191. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +122 -193
  192. data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +15 -24
  193. data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +64 -93
  194. data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +31 -45
  195. data/lib/rigor/inference/method_dispatcher/set_folding.rb +6 -9
  196. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +356 -511
  197. data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +22 -32
  198. data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +15 -21
  199. data/lib/rigor/inference/method_dispatcher/struct_folding.rb +66 -82
  200. data/lib/rigor/inference/method_dispatcher/time_folding.rb +10 -15
  201. data/lib/rigor/inference/method_dispatcher/uri_folding.rb +9 -13
  202. data/lib/rigor/inference/method_dispatcher.rb +378 -524
  203. data/lib/rigor/inference/method_parameter_binder.rb +81 -114
  204. data/lib/rigor/inference/multi_target_binder.rb +51 -68
  205. data/lib/rigor/inference/mutation_widening.rb +115 -158
  206. data/lib/rigor/inference/narrowing.rb +627 -727
  207. data/lib/rigor/inference/origin_lookup.rb +38 -0
  208. data/lib/rigor/inference/parameter_inference_collector.rb +154 -109
  209. data/lib/rigor/inference/precision_scanner.rb +26 -35
  210. data/lib/rigor/inference/project_patched_methods.rb +20 -32
  211. data/lib/rigor/inference/project_patched_scanner.rb +23 -37
  212. data/lib/rigor/inference/protection_scanner.rb +16 -18
  213. data/lib/rigor/inference/rbs_type_translator.rb +49 -66
  214. data/lib/rigor/inference/scope_indexer.rb +473 -821
  215. data/lib/rigor/inference/statement_evaluator.rb +754 -1114
  216. data/lib/rigor/inference/struct_fold_safety.rb +34 -48
  217. data/lib/rigor/inference/synthetic_method.rb +9 -16
  218. data/lib/rigor/inference/synthetic_method_index.rb +20 -35
  219. data/lib/rigor/inference/synthetic_method_scanner.rb +63 -103
  220. data/lib/rigor/language_server/buffer_resolution.rb +6 -9
  221. data/lib/rigor/language_server/buffer_table.rb +11 -18
  222. data/lib/rigor/language_server/completion_provider.rb +69 -116
  223. data/lib/rigor/language_server/debouncer.rb +16 -25
  224. data/lib/rigor/language_server/diagnostic_publisher.rb +26 -40
  225. data/lib/rigor/language_server/document_symbol_provider.rb +14 -19
  226. data/lib/rigor/language_server/folding_range_provider.rb +11 -19
  227. data/lib/rigor/language_server/hover_provider.rb +8 -11
  228. data/lib/rigor/language_server/hover_renderer.rb +56 -93
  229. data/lib/rigor/language_server/loop.rb +14 -19
  230. data/lib/rigor/language_server/project_context.rb +46 -74
  231. data/lib/rigor/language_server/selection_range_provider.rb +9 -12
  232. data/lib/rigor/language_server/server.rb +55 -83
  233. data/lib/rigor/language_server/signature_help_provider.rb +29 -46
  234. data/lib/rigor/language_server/synchronized_writer.rb +4 -7
  235. data/lib/rigor/language_server/uri.rb +8 -13
  236. data/lib/rigor/language_server.rb +4 -6
  237. data/lib/rigor/mcp/loop.rb +2 -3
  238. data/lib/rigor/mcp/server.rb +4 -7
  239. data/lib/rigor/mcp.rb +3 -6
  240. data/lib/rigor/plugin/access_denied_error.rb +5 -8
  241. data/lib/rigor/plugin/additional_initializer.rb +21 -31
  242. data/lib/rigor/plugin/base.rb +335 -518
  243. data/lib/rigor/plugin/blueprint.rb +14 -23
  244. data/lib/rigor/plugin/box.rb +18 -29
  245. data/lib/rigor/plugin/fact_store.rb +16 -26
  246. data/lib/rigor/plugin/inflector.rb +37 -53
  247. data/lib/rigor/plugin/io_boundary.rb +33 -56
  248. data/lib/rigor/plugin/isolation.rb +42 -55
  249. data/lib/rigor/plugin/load_error.rb +10 -15
  250. data/lib/rigor/plugin/loader.rb +30 -49
  251. data/lib/rigor/plugin/macro/block_as_method.rb +20 -32
  252. data/lib/rigor/plugin/macro/heredoc_template.rb +35 -58
  253. data/lib/rigor/plugin/macro/nested_class_template.rb +22 -36
  254. data/lib/rigor/plugin/macro/trait_registry.rb +34 -51
  255. data/lib/rigor/plugin/macro.rb +10 -15
  256. data/lib/rigor/plugin/manifest.rb +85 -144
  257. data/lib/rigor/plugin/node_context.rb +14 -22
  258. data/lib/rigor/plugin/node_rule_walk.rb +49 -74
  259. data/lib/rigor/plugin/protocol_contract.rb +25 -39
  260. data/lib/rigor/plugin/registry.rb +132 -205
  261. data/lib/rigor/plugin/services.rb +21 -33
  262. data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -19
  263. data/lib/rigor/plugin/trust_policy.rb +24 -38
  264. data/lib/rigor/plugin/type_node_resolver.rb +15 -24
  265. data/lib/rigor/protection/diagnostic_oracle.rb +11 -13
  266. data/lib/rigor/protection/mutation_scanner.rb +27 -35
  267. data/lib/rigor/protection/mutator.rb +50 -70
  268. data/lib/rigor/protection/test_suite_oracle.rb +20 -27
  269. data/lib/rigor/rbs_extended/conformance_checker.rb +48 -68
  270. data/lib/rigor/rbs_extended/hkt_directives.rb +28 -54
  271. data/lib/rigor/rbs_extended/reporter.rb +24 -40
  272. data/lib/rigor/rbs_extended.rb +107 -197
  273. data/lib/rigor/reflection.rb +68 -86
  274. data/lib/rigor/scope/discovery_index.rb +14 -19
  275. data/lib/rigor/scope.rb +255 -310
  276. data/lib/rigor/sig_gen/classification.rb +6 -10
  277. data/lib/rigor/sig_gen/generator.rb +197 -323
  278. data/lib/rigor/sig_gen/layout_index.rb +12 -20
  279. data/lib/rigor/sig_gen/method_candidate.rb +12 -17
  280. data/lib/rigor/sig_gen/observation_collector.rb +38 -70
  281. data/lib/rigor/sig_gen/observed_call.rb +13 -23
  282. data/lib/rigor/sig_gen/path_mapper.rb +17 -29
  283. data/lib/rigor/sig_gen/renderer.rb +7 -13
  284. data/lib/rigor/sig_gen/type_elaborator.rb +15 -28
  285. data/lib/rigor/sig_gen/write_result.rb +8 -16
  286. data/lib/rigor/sig_gen/writer.rb +95 -174
  287. data/lib/rigor/sig_gen.rb +3 -6
  288. data/lib/rigor/signature_path_audit.rb +24 -30
  289. data/lib/rigor/source/constant_path.rb +10 -14
  290. data/lib/rigor/source/literals.rb +31 -45
  291. data/lib/rigor/source/node_locator.rb +9 -11
  292. data/lib/rigor/source/node_walker.rb +9 -13
  293. data/lib/rigor/source.rb +3 -4
  294. data/lib/rigor/testing.rb +16 -20
  295. data/lib/rigor/triage/catalogue.rb +38 -62
  296. data/lib/rigor/triage.rb +31 -52
  297. data/lib/rigor/trinary.rb +9 -13
  298. data/lib/rigor/type/acceptance_router.rb +4 -6
  299. data/lib/rigor/type/accepts_result.rb +10 -14
  300. data/lib/rigor/type/app.rb +19 -27
  301. data/lib/rigor/type/bot.rb +4 -6
  302. data/lib/rigor/type/bound_method.rb +10 -15
  303. data/lib/rigor/type/combinator.rb +165 -257
  304. data/lib/rigor/type/constant.rb +23 -34
  305. data/lib/rigor/type/data_class.rb +10 -15
  306. data/lib/rigor/type/data_instance.rb +14 -20
  307. data/lib/rigor/type/difference.rb +21 -32
  308. data/lib/rigor/type/dynamic.rb +3 -5
  309. data/lib/rigor/type/hash_shape.rb +32 -18
  310. data/lib/rigor/type/integer_range.rb +11 -16
  311. data/lib/rigor/type/intersection.rb +27 -42
  312. data/lib/rigor/type/nominal.rb +10 -15
  313. data/lib/rigor/type/plain_lattice.rb +9 -13
  314. data/lib/rigor/type/refined.rb +67 -114
  315. data/lib/rigor/type/singleton.rb +4 -6
  316. data/lib/rigor/type/struct_class.rb +11 -16
  317. data/lib/rigor/type/struct_instance.rb +15 -21
  318. data/lib/rigor/type/tuple.rb +14 -19
  319. data/lib/rigor/type/union.rb +30 -42
  320. data/lib/rigor/type_node/generic.rb +14 -26
  321. data/lib/rigor/type_node/identifier.rb +12 -19
  322. data/lib/rigor/type_node.rb +3 -12
  323. data/lib/rigor/value_semantics.rb +16 -21
  324. data/lib/rigor/version.rb +1 -1
  325. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +18 -30
  326. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +16 -29
  327. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +12 -23
  328. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +22 -39
  329. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +26 -46
  330. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +51 -87
  331. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +10 -17
  332. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +26 -39
  333. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +141 -184
  334. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +30 -51
  335. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +57 -92
  336. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +92 -108
  337. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +13 -22
  338. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +15 -25
  339. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +8 -13
  340. data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +16 -24
  341. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +40 -48
  342. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +140 -129
  343. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +56 -59
  344. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +27 -41
  345. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +16 -24
  346. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +172 -0
  347. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +168 -241
  348. data/plugins/rigor-activerecord/lib/rigor-activerecord.rb +3 -5
  349. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +8 -14
  350. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +9 -15
  351. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +4 -7
  352. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +23 -41
  353. data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +3 -5
  354. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +6 -10
  355. data/plugins/rigor-activesupport-core-ext/lib/rigor-activesupport-core-ext.rb +8 -11
  356. data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +32 -0
  357. data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +30 -45
  358. data/plugins/rigor-devise/lib/rigor-devise.rb +3 -5
  359. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +43 -69
  360. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +26 -35
  361. data/plugins/rigor-dry-schema/lib/rigor-dry-schema.rb +3 -5
  362. data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +30 -47
  363. data/plugins/rigor-dry-struct/lib/rigor-dry-struct.rb +3 -5
  364. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +67 -113
  365. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +29 -46
  366. data/plugins/rigor-dry-types/lib/rigor-dry-types.rb +3 -5
  367. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -20
  368. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +14 -23
  369. data/plugins/rigor-dry-validation/lib/rigor-dry-validation.rb +2 -3
  370. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +22 -37
  371. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +28 -46
  372. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +13 -17
  373. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +30 -47
  374. data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +52 -80
  375. data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +21 -31
  376. data/plugins/rigor-graphql/lib/rigor-graphql.rb +3 -5
  377. data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +11 -17
  378. data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +20 -34
  379. data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +45 -75
  380. data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +22 -36
  381. data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +22 -41
  382. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +17 -32
  383. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +6 -12
  384. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +4 -8
  385. data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +17 -32
  386. data/plugins/rigor-rails/lib/rigor-rails.rb +11 -18
  387. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +58 -92
  388. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +20 -34
  389. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +20 -31
  390. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +49 -82
  391. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +55 -92
  392. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +51 -90
  393. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +17 -30
  394. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/grape_api_discoverer.rb +189 -0
  395. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +38 -70
  396. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +61 -75
  397. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +319 -505
  398. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +91 -96
  399. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +32 -54
  400. data/plugins/rigor-rbs-inline/lib/rigor-rbs-inline.rb +8 -13
  401. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +9 -16
  402. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +24 -39
  403. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +13 -22
  404. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +34 -56
  405. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/scope_walker.rb +22 -42
  406. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +43 -75
  407. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +27 -39
  408. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/http_status_codes.rb +14 -19
  409. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +20 -34
  410. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +28 -47
  411. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +21 -37
  412. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +13 -22
  413. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +18 -31
  414. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +6 -10
  415. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +14 -29
  416. data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +23 -41
  417. data/plugins/rigor-sinatra/lib/rigor-sinatra.rb +3 -5
  418. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +23 -38
  419. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +57 -96
  420. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +22 -35
  421. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +41 -69
  422. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/method_signature.rb +6 -10
  423. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +24 -41
  424. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +29 -50
  425. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +55 -88
  426. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +159 -262
  427. data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +21 -29
  428. data/plugins/rigor-statesman/lib/rigor-statesman.rb +3 -5
  429. data/plugins/rigor-typescript-utility-types/lib/rigor/plugin/typescript_utility_types.rb +23 -37
  430. data/plugins/rigor-typescript-utility-types/lib/rigor-typescript-utility-types.rb +4 -6
  431. data/sig/rigor/environment.rbs +1 -0
  432. data/sig/rigor/scope.rbs +6 -0
  433. metadata +9 -1
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Gem entry point. Required by Rigor's plugin loader when
4
- # `.rigor.yml` lists `rigor-activerecord` under `plugins:`. The
5
- # loader expects this `require` to side-effect a call to
6
- # `Rigor::Plugin.register`, which the body of
7
- # `lib/rigor/plugin/activerecord.rb` performs at load time.
3
+ # Gem entry point. Required by Rigor's plugin loader when `.rigor.yml` lists `rigor-activerecord` under
4
+ # `plugins:`. The loader expects this `require` to side-effect a call to `Rigor::Plugin.register`, which
5
+ # the body of `lib/rigor/plugin/activerecord.rb` performs at load time.
8
6
  require_relative "rigor/plugin/activerecord"
@@ -5,17 +5,13 @@ require "prism"
5
5
  module Rigor
6
6
  module Plugin
7
7
  class Activestorage < Rigor::Plugin::Base
8
- # Per-file walker. Emits one `:info` `attachment-call`
9
- # diagnostic per recognised attachment access on a
10
- # known AR class. The diagnostic surfaces what the
11
- # plugin recognised so users can verify the model →
12
- # attachment mapping the plugin sees.
8
+ # Per-file walker. Emits one `:info` `attachment-call` diagnostic per recognised attachment access
9
+ # on a known AR class. The diagnostic surfaces what the plugin recognised so users can verify the
10
+ # model attachment mapping the plugin sees.
13
11
  #
14
- # No `:error` diagnostics here — the `dynamic_return`
15
- # return-type narrowing carries the type-checking value.
16
- # An `unknown-attachment` rule (similar to
17
- # `rigor-activerecord`'s `unknown-column`) is deferred:
18
- # it requires a coupled receiver-class narrowing pass.
12
+ # No `:error` diagnostics here — the `dynamic_return` return-type narrowing carries the
13
+ # type-checking value. An `unknown-attachment` rule (similar to `rigor-activerecord`'s
14
+ # `unknown-column`) is deferred: it requires a coupled receiver-class narrowing pass.
19
15
  class Analyzer
20
16
  attr_reader :diagnostics
21
17
 
@@ -47,10 +43,8 @@ module Rigor
47
43
  @attachment_index.attachments_for("::#{owner}")
48
44
  return if attachments.nil?
49
45
 
50
- # Only flag when the method matches a known
51
- # attachment name (the `dynamic_return` rule
52
- # provides the narrowing; the diagnostic just
53
- # confirms the recognition).
46
+ # Only flag when the method matches a known attachment name (the `dynamic_return` rule provides
47
+ # the narrowing; the diagnostic just confirms the recognition).
54
48
  attachment = attachments.find { |a| a[:name] == node.name.to_s }
55
49
  return if attachment.nil?
56
50
 
@@ -6,10 +6,8 @@ require "rigor/source/literals"
6
6
  module Rigor
7
7
  module Plugin
8
8
  class Activestorage < Rigor::Plugin::Base
9
- # Walks the configured model search paths via the plugin's
10
- # `IoBoundary`, parses each `.rb` file with Prism, and
11
- # collects `has_one_attached` / `has_many_attached`
12
- # declarations.
9
+ # Walks the configured model search paths via the plugin's `IoBoundary`, parses each `.rb` file
10
+ # with Prism, and collects `has_one_attached` / `has_many_attached` declarations.
13
11
  #
14
12
  # Returns rows the {AttachmentIndex} consumes:
15
13
  #
@@ -19,17 +17,13 @@ module Rigor
19
17
  #
20
18
  # Limitations (intentional for v0.1.0 of the plugin):
21
19
  #
22
- # - The walker matches any class declaration that
23
- # contains a `has_*_attached` call. Whether the class
24
- # IS an ActiveRecord model is not verified here
25
- # `rigor-activerecord` provides that check via its
26
- # own model index. The analyser is intentionally
27
- # lenient so the plugin runs standalone in projects
28
- # that haven't loaded `rigor-activerecord` yet.
29
- # - Only Symbol-literal attachment names are recognised.
30
- # `has_one_attached(args)` or computed names decline.
31
- # - Modules (`class Admin::User`) are recognised; the
32
- # resulting class name is the lexical path
20
+ # - The walker matches any class declaration that contains a `has_*_attached` call. Whether the
21
+ # class IS an ActiveRecord model is not verified here — `rigor-activerecord` provides that check
22
+ # via its own model index. The analyser is intentionally lenient so the plugin runs standalone in
23
+ # projects that haven't loaded `rigor-activerecord` yet.
24
+ # - Only Symbol-literal attachment names are recognised. `has_one_attached(args)` or computed names
25
+ # decline.
26
+ # - Modules (`class Admin::User`) are recognised; the resulting class name is the lexical path
33
27
  # (`Admin::User`).
34
28
  class AttachmentDiscoverer
35
29
  ATTACHMENT_METHODS = {
@@ -3,16 +3,13 @@
3
3
  module Rigor
4
4
  module Plugin
5
5
  class Activestorage < Rigor::Plugin::Base
6
- # Maps a discovered class name to the list of attachment
7
- # rows declared on it. Marshal-clean so the cache producer
8
- # round-trips it through the standard pair.
6
+ # Maps a discovered class name to the list of attachment rows declared on it. Marshal-clean so the
7
+ # cache producer round-trips it through the standard pair.
9
8
  #
10
9
  # Each row is `{ name:, kind: }`:
11
10
  #
12
- # - `name` — String, the attachment method name as the
13
- # user invokes it (`"avatar"`).
14
- # - `kind` — `:singular` (`has_one_attached`) or
15
- # `:collection` (`has_many_attached`).
11
+ # - `name` — String, the attachment method name as the user invokes it (`"avatar"`).
12
+ # - `kind` — `:singular` (`has_one_attached`) or `:collection` (`has_many_attached`).
16
13
  class AttachmentIndex
17
14
  attr_reader :entries
18
15
 
@@ -8,26 +8,18 @@ require_relative "activestorage/analyzer"
8
8
 
9
9
  module Rigor
10
10
  module Plugin
11
- # rigor-activestorage — recognises `has_one_attached` /
12
- # `has_many_attached` macros on ActiveRecord models and
13
- # contributes attachment accessor return types so chained
14
- # calls (`user.avatar.attached?`) route through Rigor's
15
- # normal dispatch.
11
+ # rigor-activestorage — recognises `has_one_attached` / `has_many_attached` macros on ActiveRecord
12
+ # models and contributes attachment accessor return types so chained calls (`user.avatar.attached?`)
13
+ # route through Rigor's normal dispatch.
16
14
  #
17
15
  # ## Architecture
18
16
  #
19
- # One discovery pass per run reads the configured AR model
20
- # paths (default `app/models/`) via the plugin's
21
- # `IoBoundary`, walks each `.rb` file with Prism, and
22
- # collects `has_one_attached :avatar` /
23
- # `has_many_attached :photos` macros into an
24
- # {AttachmentIndex} keyed by class name. The walker is
25
- # stand-alone (mirrors `rigor-activerecord`'s
26
- # `ModelDiscoverer`) so the plugin works even when
27
- # `rigor-activerecord` is not loaded; when it IS loaded,
28
- # the published `:model_index` fact (ADR-9 cross-plugin
29
- # API) drives the same class set so the two plugins agree
30
- # on what counts as a model.
17
+ # One discovery pass per run reads the configured AR model paths (default `app/models/`) via the
18
+ # plugin's `IoBoundary`, walks each `.rb` file with Prism, and collects `has_one_attached :avatar` /
19
+ # `has_many_attached :photos` macros into an {AttachmentIndex} keyed by class name. The walker is
20
+ # stand-alone (mirrors `rigor-activerecord`'s `ModelDiscoverer`) so the plugin works even when
21
+ # `rigor-activerecord` is not loaded; when it IS loaded, the published `:model_index` fact (ADR-9
22
+ # cross-plugin API) drives the same class set so the two plugins agree on what counts as a model.
31
23
  #
32
24
  # ## Configuration
33
25
  #
@@ -39,9 +31,8 @@ module Rigor
39
31
  #
40
32
  # `model_search_paths` defaults to `["app/models"]`.
41
33
  #
42
- # The class name `Rigor::Plugin::Activestorage` (single
43
- # capital A) matches the constant-distinguishing convention
44
- # used by `rigor-activerecord`.
34
+ # The class name `Rigor::Plugin::Activestorage` (single capital A) matches the constant-distinguishing
35
+ # convention used by `rigor-activerecord`.
45
36
  class Activestorage < Rigor::Plugin::Base
46
37
  manifest(
47
38
  id: "activestorage",
@@ -53,11 +44,9 @@ module Rigor
53
44
  consumes: [{ plugin_id: "activerecord", name: :model_index, optional: true }]
54
45
  )
55
46
 
56
- # Cached: attachment index. Walks every `.rb` file under
57
- # `model_search_paths` for `has_*_attached` macros. `watch:`
58
- # (ADR-60 WD3) covers model-file additions; the discoverer's
59
- # in-block reads are captured into the record-and-validate
60
- # dependency descriptor after the block runs.
47
+ # Cached: attachment index. Walks every `.rb` file under `model_search_paths` for `has_*_attached`
48
+ # macros. `watch:` (ADR-60 WD3) covers model-file additions; the discoverer's in-block reads are
49
+ # captured into the record-and-validate dependency descriptor after the block runs.
61
50
  producer :attachment_index, watch: -> { [[@model_search_paths, "**/*.rb"]] } do |_params|
62
51
  rows = AttachmentDiscoverer.new(
63
52
  io_boundary: io_boundary,
@@ -80,18 +69,12 @@ module Rigor
80
69
  Analyzer.new(path: path, attachment_index: index).analyze(root).diagnostics
81
70
  end
82
71
 
83
- # Return-type contribution: when the receiver is
84
- # `Nominal[Model]` and the method matches a discovered
85
- # attachment, narrows to
86
- # `Nominal[ActiveStorage::Attached::One]` (singular) or
87
- # `Nominal[ActiveStorage::Attached::Many]` (collection)
88
- # via a `dynamic_return` rule keyed on the live set of
89
- # model class names from the attachment index.
90
- # The chained call (`.attached?`, `.purge`, `.url`)
91
- # then resolves through ActiveStorage's RBS surface.
92
- # Attachment setters (`user.avatar=`) decline — they
93
- # take side-effecting argument types that the RBS
94
- # surface already covers.
72
+ # Return-type contribution: when the receiver is `Nominal[Model]` and the method matches a
73
+ # discovered attachment, narrows to `Nominal[ActiveStorage::Attached::One]` (singular) or
74
+ # `Nominal[ActiveStorage::Attached::Many]` (collection) via a `dynamic_return` rule keyed on the
75
+ # live set of model class names from the attachment index. The chained call (`.attached?`, `.purge`,
76
+ # `.url`) then resolves through ActiveStorage's RBS surface. Attachment setters (`user.avatar=`)
77
+ # decline they take side-effecting argument types that the RBS surface already covers.
95
78
  dynamic_return receivers: -> { attachment_index&.class_names || [] } do |call_node, scope|
96
79
  next nil unless call_node.is_a?(Prism::CallNode)
97
80
  next nil if call_node.receiver.nil?
@@ -129,10 +112,9 @@ module Rigor
129
112
  def attachment_index
130
113
  return @attachment_index if @attachment_index
131
114
 
132
- # ADR-60 WD3 record-and-validate: the producer's in-block
133
- # `AttachmentDiscoverer` reads are captured into the
134
- # dependency descriptor after the block runs, and the
135
- # producer's `watch:` covers model-file additions.
115
+ # ADR-60 WD3 record-and-validate: the producer's in-block `AttachmentDiscoverer` reads are
116
+ # captured into the dependency descriptor after the block runs, and the producer's `watch:`
117
+ # covers model-file additions.
136
118
  @attachment_index = cache_for(:attachment_index, params: {}).call
137
119
  rescue Plugin::AccessDeniedError => e
138
120
  @load_errors << "rigor-activestorage: #{e.message}"
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Entry point matching the `rigor-<id>` gem-name convention.
4
- # The Plugin::Loader's `require_gem!` step calls
5
- # `require "rigor-activestorage"`, and this file loads the
6
- # plugin's actual implementation under the `rigor/plugin/`
7
- # namespace so the require / register pair fires.
3
+ # Entry point matching the `rigor-<id>` gem-name convention. The Plugin::Loader's `require_gem!` step
4
+ # calls `require "rigor-activestorage"`, and this file loads the plugin's actual implementation under
5
+ # the `rigor/plugin/` namespace so the require / register pair fires.
8
6
  require "rigor/plugin/activestorage"
@@ -4,14 +4,11 @@ require "rigor/plugin"
4
4
 
5
5
  module Rigor
6
6
  module Plugin
7
- # ADR-25 — a pure RBS-bundle plugin. It ships NO analyzer code:
8
- # no `diagnostics_for_file`, no `dynamic_return`. Its
9
- # whole contribution is the manifest's `signature_paths: ["sig"]`,
10
- # which declares the bundled ActiveSupport `core_ext` RBS
11
- # directory. `Plugin::Loader` resolves that directory against
12
- # this gem's root and `Environment.for_project` merges it into
13
- # the RBS environment, so the ActiveSupport core-extension
14
- # selectors (`3.days`, `"x".squish`, `Time.current`, …) resolve.
7
+ # ADR-25 — a pure RBS-bundle plugin. It ships NO analyzer code: no `diagnostics_for_file`, no
8
+ # `dynamic_return`. Its whole contribution is the manifest's `signature_paths: ["sig"]`, which
9
+ # declares the bundled ActiveSupport `core_ext` RBS directory. `Plugin::Loader` resolves that
10
+ # directory against this gem's root and `Environment.for_project` merges it into the RBS environment,
11
+ # so the ActiveSupport core-extension selectors (`3.days`, `"x".squish`, `Time.current`, …) resolve.
15
12
  #
16
13
  # Activate it like any plugin — no path, no vendoring:
17
14
  #
@@ -23,8 +20,7 @@ module Rigor
23
20
  class ActivesupportCoreExt < Rigor::Plugin::Base
24
21
  manifest(
25
22
  id: "activesupport-core-ext",
26
- # Bumped 2026-05-28 — added Date#midnight /
27
- # at_midnight / beginning_of_day / end_of_day (Rails
23
+ # Bumped 2026-05-28 — added Date#midnight / at_midnight / beginning_of_day / end_of_day (Rails
28
24
  # aliases that return Time, not Date).
29
25
  version: "0.2.0",
30
26
  description: "RBS bundle for the most-frequently-flagged ActiveSupport core_ext extensions.",
@@ -1,20 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rigor-activesupport-core-ext — a community-maintained RBS bundle
4
- # for the most-frequently-flagged ActiveSupport core extensions.
3
+ # rigor-activesupport-core-ext — a community-maintained RBS bundle for the most-frequently-flagged
4
+ # ActiveSupport core extensions.
5
5
  #
6
- # Per ADR-25 this gem is a pure RBS-bundle *plugin*: it ships a
7
- # `sig/` directory and a trivial `Rigor::Plugin::Base` subclass
8
- # whose manifest declares `signature_paths: ["sig"]`. Activate it
9
- # by listing the gem under `.rigor.yml`'s `plugins:` — Rigor
10
- # resolves and loads the bundled `sig/` automatically, with no
11
- # hand-written path:
6
+ # Per ADR-25 this gem is a pure RBS-bundle *plugin*: it ships a `sig/` directory and a trivial
7
+ # `Rigor::Plugin::Base` subclass whose manifest declares `signature_paths: ["sig"]`. Activate it by
8
+ # listing the gem under `.rigor.yml`'s `plugins:` — Rigor resolves and loads the bundled `sig/`
9
+ # automatically, with no hand-written path:
12
10
  #
13
11
  # # .rigor.yml
14
12
  # plugins:
15
13
  # - rigor-activesupport-core-ext
16
14
  #
17
- # Coverage scope and rationale: see `README.md` in this directory
18
- # and `docs/notes/20260515-real-world-rails-survey.md` for the
19
- # survey that established the selector ranking.
15
+ # Coverage scope and rationale: see `README.md` in this directory and
16
+ # `docs/notes/20260515-real-world-rails-survey.md` for the survey that established the selector ranking.
20
17
  require_relative "rigor/plugin/activesupport_core_ext"
@@ -62,6 +62,9 @@ class Object
62
62
  # `acts_like?(:string)` / `acts_like?(:date)` / `acts_like?(:time)`
63
63
  # is ActiveSupport's "duck-typing helper" predicate.
64
64
  def acts_like?: (Symbol | String) -> bool
65
+
66
+ # `core_ext/object/inclusion` — `x.in?([a, b])` / `x.in?(1..10)`.
67
+ def in?: (untyped) -> bool
65
68
  end
66
69
 
67
70
  # `nil.blank?` / `nil.present?` / `nil.try` are the most frequent
@@ -99,6 +102,9 @@ class String
99
102
  def demodulize: () -> String
100
103
  def deconstantize: () -> String
101
104
  def titleize: () -> String
105
+ def titlecase: () -> String
106
+ def dasherize: () -> String
107
+ def upcase_first: () -> String
102
108
  def parameterize: (?separator: String, ?preserve_case: bool, ?locale: Symbol?) -> String
103
109
  def tableize: () -> String
104
110
  def foreign_key: (?bool separate_class_name_and_id_with_underscore) -> String
@@ -112,6 +118,9 @@ class String
112
118
  def truncate: (Integer truncate_at, ?omission: String, ?separator: String | Regexp | nil) -> String
113
119
  def truncate_bytes: (Integer truncate_at, ?omission: String) -> String
114
120
  def truncate_words: (Integer words_count, ?omission: String, ?separator: String | Regexp | nil) -> String
121
+ # `remove` / `remove!` delete every occurrence of the given patterns.
122
+ def remove: (*Regexp | String patterns) -> String
123
+ def remove!: (*Regexp | String patterns) -> String
115
124
 
116
125
  # `core_ext/string/output_safety` — `html_safe` returns an
117
126
  # `ActiveSupport::SafeBuffer` (a String subclass). The closest
@@ -274,6 +283,9 @@ class Time
274
283
  def noon: () -> Time
275
284
  def utc?: () -> bool
276
285
  def acts_like_time?: () -> true
286
+ # `advance(days: 1, months: -2)` and `all_day` (a `beginning_of_day..end_of_day` Range).
287
+ def advance: (untyped options) -> Time
288
+ def all_day: () -> Range[Time]
277
289
  end
278
290
 
279
291
  # ---------------------------------------------------------------
@@ -314,6 +326,11 @@ class Date
314
326
  def at_beginning_of_day: () -> Time
315
327
  def end_of_day: () -> Time
316
328
  def at_end_of_day: () -> Time
329
+ # `advance(days: 1)`, `all_day` (a Time Range), and `to_time(form)` — the
330
+ # `:local` / `:utc` form arg core RBS' `Date#to_time` (arity 0) omits.
331
+ def advance: (untyped options) -> Date
332
+ def all_day: () -> Range[Time]
333
+ def to_time: (?Symbol form) -> Time
317
334
  end
318
335
 
319
336
  # ---------------------------------------------------------------
@@ -476,3 +493,18 @@ end
476
493
  class String
477
494
  def exclude?: (String) -> bool
478
495
  end
496
+
497
+ # ---------------------------------------------------------------
498
+ # ERB::Util — ActionView extends it with `html_escape_once`
499
+ # ---------------------------------------------------------------
500
+
501
+ # `ERB` is a CLASS in Ruby / RBS (not a module), so reopen it as a class —
502
+ # a `module ERB` wrapper collides with upstream `class ERB` once the `erb`
503
+ # stdlib is in scope. `ERB::Util` itself is a module.
504
+ class ERB
505
+ module Util
506
+ # `ERB::Util.html_escape_once(s)` escapes HTML without double-escaping
507
+ # an already-escaped entity. ActionView adds it on top of stdlib ERB.
508
+ def self.html_escape_once: (untyped) -> String
509
+ end
510
+ end
@@ -4,26 +4,21 @@ require "rigor/plugin"
4
4
 
5
5
  module Rigor
6
6
  module Plugin
7
- # ADR-16 Tier B worked plugin: recognises Devise's model-side
8
- # `devise :strategy_a, :strategy_b` DSL on `ActiveRecord::Base`
9
- # subclasses and explodes each strategy's module RBS into the
10
- # calling class.
7
+ # ADR-16 Tier B worked plugin: recognises Devise's model-side `devise :strategy_a, :strategy_b` DSL on
8
+ # `ActiveRecord::Base` subclasses and explodes each strategy's module RBS into the calling class.
11
9
  #
12
- # Per the per-library survey (§ Devise), Devise's `devise(*modules)`
13
- # at `lib/devise/models.rb:79-112` is a **table-driven include
14
- # sequence**: each Symbol argument resolves through
15
- # `Devise::Models.const_get(m.to_s.classify)` to a concrete
16
- # `Devise::Models::*` module, which is then mixed into the
17
- # calling class. The substrate replays the same shape
18
- # statically — the manifest's `modules_by_symbol:` mirrors
19
- # Devise's `lib/devise/modules.rb` and the pre-pass scanner
20
- # synthesises one SyntheticMethod per (calling class, included
21
- # module instance method) pair into the SyntheticMethodIndex.
10
+ # Per the per-library survey (§ Devise), Devise's `devise(*modules)` at `lib/devise/models.rb:79-112`
11
+ # is a **table-driven include sequence**: each Symbol argument resolves through
12
+ # `Devise::Models.const_get(m.to_s.classify)` to a concrete `Devise::Models::*` module, which is then
13
+ # mixed into the calling class. The substrate replays the same shape statically — the manifest's
14
+ # `modules_by_symbol:` mirrors Devise's `lib/devise/modules.rb` and the pre-pass scanner synthesises
15
+ # one SyntheticMethod per (calling class, included module instance method) pair into the
16
+ # SyntheticMethodIndex.
22
17
  #
23
18
  # ## Reach
24
19
  #
25
- # The full set of strategies Devise registers via
26
- # `Devise.add_module` at gem load (per `lib/devise/modules.rb`):
20
+ # The full set of strategies Devise registers via `Devise.add_module` at gem load (per
21
+ # `lib/devise/modules.rb`):
27
22
  #
28
23
  # - `:database_authenticatable` — password + email auth core
29
24
  # - `:recoverable` — password-reset flow
@@ -37,41 +32,31 @@ module Rigor
37
32
  # - `:omniauthable` — OmniAuth providers
38
33
  # - `:authenticatable` — always-included base module
39
34
  #
40
- # The substrate's pre-pass scanner consults each module's RBS
41
- # via `Environment::RbsLoader#instance_definition` to enumerate
42
- # method names. A user project providing real Devise via
43
- # Bundler will see methods like `valid_password?`,
44
- # `send_reset_password_instructions`, etc. resolve through the
45
- # synthetic-method tier without `call.undefined-method`.
35
+ # The substrate's pre-pass scanner consults each module's RBS via `Environment::RbsLoader#instance_definition`
36
+ # to enumerate method names. A user project providing real Devise via Bundler will see methods like
37
+ # `valid_password?`, `send_reset_password_instructions`, etc. resolve through the synthetic-method
38
+ # tier without `call.undefined-method`.
46
39
  #
47
40
  # ## Precision tier
48
41
  #
49
- # The scanner records `origin_module:` in each synthetic
50
- # method's provenance. The dispatcher's slice-6a TierB path
51
- # (`promote_via_origin_module`) redispatches on
52
- # `Nominal[origin_module]` via `RbsDispatch`, so Devise's
53
- # authored RBS return types win: `valid_password?` returns
54
- # `bool`, not `Dynamic[T]`. Unknown return types degrade
55
- # gracefully to `Dynamic[T]`.
42
+ # The scanner records `origin_module:` in each synthetic method's provenance. The dispatcher's
43
+ # slice-6a TierB path (`promote_via_origin_module`) redispatches on `Nominal[origin_module]` via
44
+ # `RbsDispatch`, so Devise's authored RBS return types win: `valid_password?` returns `bool`, not
45
+ # `Dynamic[T]`. Unknown return types degrade gracefully to `Dynamic[T]`.
56
46
  #
57
47
  # ## Scope
58
48
  #
59
- # - Recognises model-side `devise :a, :b` on any AR::Base
60
- # subclass; trait symbol set mirrors `lib/devise/modules.rb`.
61
- # - `Devise::Models::Authenticatable` is always_included
62
- # (matches Devise's `with_options model: true`).
63
- # - Unknown trait symbols silently skipped (per slice-3
64
- # design judgment (2)). User initializers that call
65
- # `Devise.add_module :my_strategy, ...` are NOT seen — that
66
- # path requires a separate scanner for `config/initializers/`
67
- # and is deferred.
68
- # - Controller-side helpers (`current_user`, `authenticate_user!`,
69
- # etc.) are Tier C work, NOT Tier B; deferred to a future
70
- # slice that consumes ADR-9 fact-store entries from a
71
- # `rigor-rails-routes`-style walker.
72
- # - Per-strategy `ClassMethods` extend (Devise's `extend
73
- # Mod::ClassMethods` pattern) is NOT yet wired — slice 3
74
- # covers instance methods only per WD13 floor.
49
+ # - Recognises model-side `devise :a, :b` on any AR::Base subclass; trait symbol set mirrors
50
+ # `lib/devise/modules.rb`.
51
+ # - `Devise::Models::Authenticatable` is always_included (matches Devise's `with_options model: true`).
52
+ # - Unknown trait symbols silently skipped (per slice-3 design judgment (2)). User initializers that
53
+ # call `Devise.add_module :my_strategy, ...` are NOT seen that path requires a separate scanner
54
+ # for `config/initializers/` and is deferred.
55
+ # - Controller-side helpers (`current_user`, `authenticate_user!`, etc.) are Tier C work, NOT Tier B;
56
+ # deferred to a future slice that consumes ADR-9 fact-store entries from a `rigor-rails-routes`-style
57
+ # walker.
58
+ # - Per-strategy `ClassMethods` extend (Devise's `extend Mod::ClassMethods` pattern) is NOT yet wired
59
+ # slice 3 covers instance methods only per WD13 floor.
75
60
  class Devise < Rigor::Plugin::Base
76
61
  manifest(
77
62
  id: "devise",
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Gem entry point. Required by Rigor's plugin loader when
4
- # `.rigor.yml` lists `rigor-devise` under `plugins:`. The loader
5
- # expects this `require` to side-effect a call to
6
- # `Rigor::Plugin.register`, which the body of
7
- # `lib/rigor/plugin/devise.rb` performs at load time.
3
+ # Gem entry point. Required by Rigor's plugin loader when `.rigor.yml` lists `rigor-devise` under
4
+ # `plugins:`. The loader expects this `require` to side-effect a call to `Rigor::Plugin.register`,
5
+ # which the body of `lib/rigor/plugin/devise.rb` performs at load time.
8
6
  require_relative "rigor/plugin/devise"