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,15 +4,12 @@ require "prism"
4
4
 
5
5
  module Rigor
6
6
  module Plugin
7
- # ADR-37 slice 1d — the lexical context of a node, handed to a
8
- # {Base.node_rule} block as its fifth argument. Realises the
9
- # `ContextInfo` ADR-2 § "Scope Object" promised: the enclosing
10
- # class / module, method, and block-DSL nesting that a per-node rule
11
- # needs but that `Scope` (value/type facts) does not carry.
7
+ # ADR-37 slice 1d — the lexical context of a node, handed to a {Base.node_rule} block as its fifth argument.
8
+ # Realises the `ContextInfo` ADR-2 § "Scope Object" promised: the enclosing class / module, method, and
9
+ # block-DSL nesting that a per-node rule needs but that `Scope` (value/type facts) does not carry.
12
10
  #
13
- # The engine builds one per matching node from the descent stack
14
- # (snapshotted, so it is safe to retain). Rules read the bits they
15
- # need:
11
+ # The engine builds one per matching node from the descent stack (snapshotted, so it is safe to retain).
12
+ # Rules read the bits they need:
16
13
  #
17
14
  # node_rule Prism::CallNode do |node, _scope, path, _fc, context|
18
15
  # action = context.enclosing_def&.name # rails-i18n
@@ -20,9 +17,8 @@ module Rigor
20
17
  # …
21
18
  # end
22
19
  #
23
- # `ancestors` is the full chain, outermost first, EXCLUDING the node
24
- # itself the general primitive; the accessors below are
25
- # conveniences derived from it.
20
+ # `ancestors` is the full chain, outermost first, EXCLUDING the node itself — the general primitive; the
21
+ # accessors below are conveniences derived from it.
26
22
  class NodeContext
27
23
  EMPTY = nil # sentinel documented for readers; rules get a real instance
28
24
 
@@ -33,25 +29,21 @@ module Rigor
33
29
  freeze
34
30
  end
35
31
 
36
- # The innermost enclosing `Prism::DefNode`, or nil. Its `#name`
37
- # is the method the node sits in (rails-i18n uses it to expand a
38
- # lazy `t('.key')` against the controller action).
32
+ # The innermost enclosing `Prism::DefNode`, or nil. Its `#name` is the method the node sits in (rails-i18n
33
+ # uses it to expand a lazy `t('.key')` against the controller action).
39
34
  def enclosing_def
40
35
  ancestors.rfind { |n| n.is_a?(Prism::DefNode) }
41
36
  end
42
37
 
43
- # The innermost enclosing `Prism::ClassNode` / `Prism::ModuleNode`,
44
- # or nil (actionpack uses it to resolve the controller a
45
- # `before_action` / `render` sits in).
38
+ # The innermost enclosing `Prism::ClassNode` / `Prism::ModuleNode`, or nil (actionpack uses it to resolve
39
+ # the controller a `before_action` / `render` sits in).
46
40
  def enclosing_module
47
41
  ancestors.rfind { |n| n.is_a?(Prism::ClassNode) || n.is_a?(Prism::ModuleNode) }
48
42
  end
49
43
 
50
- # The innermost enclosing `Prism::CallNode` that carries a block
51
- # and whose method name is `method_name` e.g. the
52
- # `RSpec.describe(Model) do end` a shoulda matcher sits in.
53
- # Returns the CallNode (so the caller can read its arguments /
54
- # receiver), or nil.
44
+ # The innermost enclosing `Prism::CallNode` that carries a block and whose method name is `method_name` —
45
+ # e.g. the `RSpec.describe(Model) do end` a shoulda matcher sits in. Returns the CallNode (so the caller
46
+ # can read its arguments / receiver), or nil.
55
47
  def enclosing_block(method_name)
56
48
  ancestors.rfind do |n|
57
49
  n.is_a?(Prism::CallNode) && n.block && n.name == method_name
@@ -8,48 +8,36 @@ module Rigor
8
8
  module Plugin
9
9
  # ADR-52 WD4 — one engine-owned AST walk per file for node rules.
10
10
  #
11
- # Before this, every plugin that declared a {Base.node_rule} walked
12
- # the file's AST itself (`Base#node_rule_diagnostics` →
13
- # `Source::NodeWalker.each_with_ancestors`), so a project with N
14
- # node-rule plugins paid N walks per file. This folds them into a
15
- # single walk that dispatches each visited node to every matching
16
- # `(plugin, rule)` pair.
11
+ # Before this, every plugin that declared a {Base.node_rule} walked the file's AST itself
12
+ # (`Base#node_rule_diagnostics` → `Source::NodeWalker.each_with_ancestors`), so a project with N node-rule
13
+ # plugins paid N walks per file. This folds them into a single walk that dispatches each visited node to
14
+ # every matching `(plugin, rule)` pair.
17
15
  #
18
- # Behaviour is preserved exactly so the diagnostics stay
19
- # byte-identical (the WD6 gate):
16
+ # Behaviour is preserved exactly so the diagnostics stay byte-identical (the WD6 gate):
20
17
  #
21
- # * Each plugin's `node_file_context` block runs once per file,
22
- # before any of its rules fire, `instance_exec`'d on that plugin —
23
- # same as the per-plugin walk.
24
- # * One frozen {NodeContext} is built per node, lazily, only when at
25
- # least one rule matches it. Because it wraps only the ancestors it
26
- # is safe to share across plugins for the same node.
27
- # * Each rule block is `instance_exec`'d on its own plugin instance
28
- # with the same five arguments `(node, scope, path, file_context,
29
- # context)`.
30
- # * A plugin whose context block or any rule block raises has its
31
- # whole node-rule contribution isolatedthe walk records the
32
- # error against that plugin and continues, matching the runner's
33
- # per-plugin rescue around the old `#node_rule_diagnostics` call.
34
- # * Diagnostics are bucketed per plugin and returned in the
35
- # registry order the runner already iterates, so emission order is
36
- # unchanged (plugin-major, not node-major) — order preservation is
37
- # what keeps the gate byte-identical in this slice.
18
+ # * Each plugin's `node_file_context` block runs once per file, before any of its rules fire,
19
+ # `instance_exec`'d on that plugin — same as the per-plugin walk.
20
+ # * One frozen {NodeContext} is built per node, lazily, only when at least one rule matches it. Because it
21
+ # wraps only the ancestors it is safe to share across plugins for the same node.
22
+ # * Each rule block is `instance_exec`'d on its own plugin instance with the same five arguments `(node,
23
+ # scope, path, file_context, context)`.
24
+ # * A plugin whose context block or any rule block raises has its whole node-rule contribution isolated —
25
+ # the walk records the error against that plugin and continues, matching the runner's per-plugin rescue
26
+ # around the old `#node_rule_diagnostics` call.
27
+ # * Diagnostics are bucketed per plugin and returned in the registry order the runner already iterates,
28
+ # so emission order is unchanged (plugin-major, not node-major)order preservation is what keeps the
29
+ # gate byte-identical in this slice.
38
30
  #
39
- # The result is an ordered Array of {Result}, one per node-rule
40
- # plugin (registry order). `Result#error` is non-nil iff that
41
- # plugin's context or a rule block raised, in which case
42
- # `#diagnostics` is empty; the runner turns the error into the same
43
- # per-plugin `runtime-error` envelope it produced before.
31
+ # The result is an ordered Array of {Result}, one per node-rule plugin (registry order). `Result#error` is
32
+ # non-nil iff that plugin's context or a rule block raised, in which case `#diagnostics` is empty; the
33
+ # runner turns the error into the same per-plugin `runtime-error` envelope it produced before.
44
34
  class NodeRuleWalk
45
- # One plugin's node-rule outcome for a single file. `error` is the
46
- # exception raised by the plugin's context block or a rule block
47
- # (nil on success); when set, `diagnostics` is empty.
35
+ # One plugin's node-rule outcome for a single file. `error` is the exception raised by the plugin's
36
+ # context block or a rule block (nil on success); when set, `diagnostics` is empty.
48
37
  Result = Struct.new(:plugin, :diagnostics, :error)
49
38
 
50
- # Plugins that declare at least one `node_rule`, paired with their
51
- # frozen rule list, in registry order. Built once per run and
52
- # reused for every file.
39
+ # Plugins that declare at least one `node_rule`, paired with their frozen rule list, in registry order.
40
+ # Built once per run and reused for every file.
53
41
  def initialize(plugins)
54
42
  @entries = plugins.filter_map do |plugin|
55
43
  rules = plugin.class.node_rules
@@ -62,28 +50,20 @@ module Rigor
62
50
  @entries.empty?
63
51
  end
64
52
 
65
- # Walk `root` once, dispatching every node to each matching
66
- # `(plugin, rule)`. Returns an Array of {Result} in plugin
67
- # (registry) order. `root` nil yields one empty Result per plugin.
53
+ # Walk `root` once, dispatching every node to each matching `(plugin, rule)`. Returns an Array of
54
+ # {Result} in plugin (registry) order. `root` nil yields one empty Result per plugin.
68
55
  #
69
- # ADR-53 B4 — when `collector_driver` is given (an
70
- # {Analysis::CheckRules::RuleWalk::CollectorDriver}), the SAME
71
- # single traversal also drives the built-in {CheckRules} node
72
- # collectors: each visited node is dispatched both to the plugin
73
- # rules (this walk's original job) and to the built-in collectors
74
- # (the `CollectorDriver`), so a file is walked once for both
75
- # instead of once each. The two dispatch models coexist: plugin
76
- # rules keep `is_a?` matching via the per-class memo and receive a
77
- # lazily-built {NodeContext} (ancestors); built-in collectors keep
78
- # exact-node-class dispatch and receive the immutable
79
- # {RuleWalk::Context} threaded through the descent. Order is
80
- # preserved because each side accumulates into its own bucket
81
- # (per-plugin {Result}s / per-collector `results`) and the two are
82
- # assembled separately by their respective diagnostic builders.
83
- # A raising plugin rule isolates only that plugin (per-{State}
84
- # rescue) and never aborts built-in collection, nor vice versa
85
- # (the collectors' `visit` is the verbatim legacy gather logic,
86
- # which does not raise on the corpora).
56
+ # ADR-53 B4 — when `collector_driver` is given (an {Analysis::CheckRules::RuleWalk::CollectorDriver}),
57
+ # the SAME single traversal also drives the built-in {CheckRules} node collectors: each visited node is
58
+ # dispatched both to the plugin rules (this walk's original job) and to the built-in collectors (the
59
+ # `CollectorDriver`), so a file is walked once for both instead of once each. The two dispatch models
60
+ # coexist: plugin rules keep `is_a?` matching via the per-class memo and receive a lazily-built
61
+ # {NodeContext} (ancestors); built-in collectors keep exact-node-class dispatch and receive the
62
+ # immutable {RuleWalk::Context} threaded through the descent. Order is preserved because each side
63
+ # accumulates into its own bucket (per-plugin {Result}s / per-collector `results`) and the two are
64
+ # assembled separately by their respective diagnostic builders. A raising plugin rule isolates only that
65
+ # plugin (per-{State} rescue) and never aborts built-in collection, nor vice versa (the collectors'
66
+ # `visit` is the verbatim legacy gather logic, which does not raise on the corpora).
87
67
  def diagnostics_for_file(path:, scope:, root:, collector_driver: nil)
88
68
  return @entries.map { |plugin, _| Result.new(plugin, [], nil) } if root.nil?
89
69
 
@@ -99,14 +79,11 @@ module Rigor
99
79
  walk_node(root, [], context, path, scope, states, collector_driver)
100
80
  end
101
81
 
102
- # The single converged DFS pre-order traversal. Threads both the
103
- # live `ancestors` stack (for plugin {NodeContext}) and the
104
- # immutable built-in {RuleWalk::Context} (for the collectors),
105
- # derived together as the walk descends — the cheap-ancestors
106
- # option from the ADR-53 B4 design note. Identical pre-order over
107
- # `compact_child_nodes` to both the legacy
108
- # `Source::NodeWalker.each_with_ancestors` and `RuleWalk.walk`, so
109
- # every node is visited in the same order each side saw before.
82
+ # The single converged DFS pre-order traversal. Threads both the live `ancestors` stack (for plugin
83
+ # {NodeContext}) and the immutable built-in {RuleWalk::Context} (for the collectors), derived together
84
+ # as the walk descends — the cheap-ancestors option from the ADR-53 B4 design note. Identical pre-order
85
+ # over `compact_child_nodes` to both the legacy `Source::NodeWalker.each_with_ancestors` and
86
+ # `RuleWalk.walk`, so every node is visited in the same order each side saw before.
110
87
  def walk_node(node, ancestors, context, path, scope, states, collector_driver)
111
88
  return unless node.is_a?(Prism::Node)
112
89
 
@@ -129,16 +106,15 @@ module Rigor
129
106
  matched = state.rules_for(node)
130
107
  next if matched.empty?
131
108
 
132
- # One frozen NodeContext per node, built lazily and shared
133
- # across every plugin that matches this node.
109
+ # One frozen NodeContext per node, built lazily and shared across every plugin that matches this
110
+ # node.
134
111
  node_context ||= NodeContext.new(ancestors)
135
112
  state.run_rules(matched, node, scope, path, node_context)
136
113
  end
137
114
  end
138
115
 
139
- # Mutable per-(plugin, file) walk state. Kept private to the walk —
140
- # holds the diagnostics bucket, the file context, the per-concrete-
141
- # class match memo, and the isolation flag.
116
+ # Mutable per-(plugin, file) walk state. Kept private to the walk — holds the diagnostics bucket, the
117
+ # file context, the per-concrete-class match memo, and the isolation flag.
142
118
  class State
143
119
  def initialize(plugin, rules, scope, root)
144
120
  @plugin = plugin
@@ -153,10 +129,9 @@ module Rigor
153
129
  !@error.nil?
154
130
  end
155
131
 
156
- # Rules whose `node_type` this concrete node satisfies, memoised
157
- # by the node's class so the `is_a?` scan runs once per class.
158
- # Preserves `is_a?` semantics when a rule's `node_type` is a
159
- # superclass of the concrete node.
132
+ # Rules whose `node_type` this concrete node satisfies, memoised by the node's class so the `is_a?`
133
+ # scan runs once per class. Preserves `is_a?` semantics when a rule's `node_type` is a superclass of
134
+ # the concrete node.
160
135
  def rules_for(node)
161
136
  @match_cache[node.class] ||=
162
137
  @rules.select { |rule| node.is_a?(rule[:node_type]) }
@@ -2,10 +2,8 @@
2
2
 
3
3
  module Rigor
4
4
  module Plugin
5
- # ADR-28 declaration: "every instance/singleton method named
6
- # `method_name`, defined in a source file matching `path_glob`,
7
- # is implicitly required to satisfy the declared parameter +
8
- # return-type protocol."
5
+ # ADR-28 declaration: "every instance/singleton method named `method_name`, defined in a source file
6
+ # matching `path_glob`, is implicitly required to satisfy the declared parameter + return-type protocol."
9
7
  #
10
8
  # Authored on a plugin manifest:
11
9
  #
@@ -22,49 +20,38 @@ module Rigor
22
20
  # ]
23
21
  # )
24
22
  #
25
- # The contract drives two distinct engine behaviours (ADR-28
26
- # § "provide-and-check"):
23
+ # The contract drives two distinct engine behaviours (ADR-28 § "provide-and-check"):
27
24
  #
28
- # - **provide** — when the inference engine binds the parameter
29
- # list of a matching `def`, {Rigor::Inference::MethodParameterBinder}
30
- # substitutes the declared `param_types` for the usual
31
- # `Dynamic[Top]` fallback, so the method body is analysed as
32
- # if the parameter carried its protocol type.
33
- # - **check** — the contributing plugin's `#diagnostics_for_file`
34
- # hook confirms the method exists and its inferred return type
35
- # conforms to `return_type_name`.
25
+ # - **provide** — when the inference engine binds the parameter list of a matching `def`,
26
+ # {Rigor::Inference::MethodParameterBinder} substitutes the declared `param_types` for the usual
27
+ # `Dynamic[Top]` fallback, so the method body is analysed as if the parameter carried its protocol type.
28
+ # - **check** — the contributing plugin's `#diagnostics_for_file` hook confirms the method exists and its
29
+ # inferred return type conforms to `return_type_name`.
36
30
  #
37
31
  # ## Fields
38
32
  #
39
- # - `path_glob` — `File.fnmatch` glob (String) selecting the
40
- # source files the contract applies to, relative to the
41
- # analysed project root (e.g. `"lib/controller/**/*.rb"`).
42
- # - `method_name` — Symbol; the instance (or singleton) method
43
- # the contract constrains.
44
- # - `singleton` — Boolean; `true` constrains `def self.<name>`,
45
- # `false` (default) constrains instance methods.
46
- # - `param_types` — Array of `ParamType` (positional index →
47
- # fully-qualified type name). The type names resolve against
48
- # the analysed project's environment lazily, at consumption
49
- # time, so the contract value object stays independent of
50
- # environment construction order.
51
- # - `return_type_name` — fully-qualified type name (String) the
52
- # method's inferred return type must conform to.
53
- # - `severity` — Symbol diagnostic severity for contract
54
- # violations (`:error` default).
33
+ # - `path_glob` — `File.fnmatch` glob (String) selecting the source files the contract applies to,
34
+ # relative to the analysed project root (e.g. `"lib/controller/**/*.rb"`).
35
+ # - `method_name` — Symbol; the instance (or singleton) method the contract constrains.
36
+ # - `singleton` — Boolean; `true` constrains `def self.<name>`, `false` (default) constrains instance
37
+ # methods.
38
+ # - `param_types` — Array of `ParamType` (positional index → fully-qualified type name). The type names
39
+ # resolve against the analysed project's environment lazily, at consumption time, so the contract value
40
+ # object stays independent of environment construction order.
41
+ # - `return_type_name` — fully-qualified type name (String) the method's inferred return type must
42
+ # conform to.
43
+ # - `severity` Symbol diagnostic severity for contract violations (`:error` default).
55
44
  #
56
45
  # ## Ractor-shareability
57
46
  #
58
- # Every field is frozen at construction (ADR-15 Phase 1); the
59
- # nested `ParamType` is a frozen `Data`. `Ractor.shareable?`
60
- # returns true after `#initialize`, so the contract survives
47
+ # Every field is frozen at construction (ADR-15 Phase 1); the nested `ParamType` is a frozen `Data`.
48
+ # `Ractor.shareable?` returns true after `#initialize`, so the contract survives
61
49
  # `Plugin::Registry.materialize` into a worker Ractor.
62
50
  class ProtocolContract
63
51
  VALID_SEVERITIES = %i[error warning info].freeze
64
52
 
65
- # One positional-parameter provision: the zero-based index of
66
- # the parameter and the fully-qualified name of the type it
67
- # carries under the protocol.
53
+ # One positional-parameter provision: the zero-based index of the parameter and the fully-qualified
54
+ # name of the type it carries under the protocol.
68
55
  ParamType = Data.define(:index, :type_name)
69
56
 
70
57
  attr_reader :path_glob, :method_name, :singleton, :param_types, :return_type_name, :severity
@@ -85,9 +72,8 @@ module Rigor
85
72
  freeze
86
73
  end
87
74
 
88
- # Returns a copy with `path_glob` replaced. Plugins use this to
89
- # honour a per-project config override of the convention path
90
- # without rebuilding the whole contract by hand.
75
+ # Returns a copy with `path_glob` replaced. Plugins use this to honour a per-project config override of
76
+ # the convention path without rebuilding the whole contract by hand.
91
77
  def with_path_glob(glob)
92
78
  ProtocolContract.new(
93
79
  path_glob: glob,