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
@@ -7,15 +7,11 @@ require_relative "controller_index"
7
7
  module Rigor
8
8
  module Plugin
9
9
  class Actionpack < Rigor::Plugin::Base
10
- # Walks `controller_search_paths` building a
11
- # {ControllerIndex} of `(class_name, methods,
12
- # parent_class_name)` triples. Used by Phase 2 (filter
13
- # chains) to validate that `before_action :name`
14
- # references a method defined on the controller or its
15
- # ancestor chain.
10
+ # Walks `controller_search_paths` building a {ControllerIndex} of `(class_name, methods,
11
+ # parent_class_name)` triples. Used by Phase 2 (filter chains) to validate that `before_action
12
+ # :name` references a method defined on the controller or its ancestor chain.
16
13
  #
17
- # Two declaration shapes are recognised and qualified
18
- # the same way:
14
+ # Two declaration shapes are recognised and qualified the same way:
19
15
  #
20
16
  # class Admin::AccountsController < BaseController
21
17
  # # → registered as "Admin::AccountsController"
@@ -26,25 +22,18 @@ module Rigor
26
22
  # end
27
23
  # end
28
24
  #
29
- # Pre-fix the nested form ignored the enclosing `module
30
- # Admin` and registered the inner class as bare
31
- # `"AccountsController"`, overwriting the top-level
32
- # `app/controllers/accounts_controller.rb` entry. Mastodon
33
- # has both shapes for the same logical name (top-level
34
- # `AccountsController` + `Admin::AccountsController` +
35
- # `Api::V1::AccountsController`) and the overwrite caused
36
- # the wrong inheritance / method set to flow downstream,
37
- # producing dozens of false `unknown-filter-method`
25
+ # Pre-fix the nested form ignored the enclosing `module Admin` and registered the inner class as
26
+ # bare `"AccountsController"`, overwriting the top-level `app/controllers/accounts_controller.rb`
27
+ # entry. Mastodon has both shapes for the same logical name (top-level `AccountsController` +
28
+ # `Admin::AccountsController` + `Api::V1::AccountsController`) and the overwrite caused the wrong
29
+ # inheritance / method set to flow downstream, producing dozens of false `unknown-filter-method`
38
30
  # diagnostics.
39
31
  #
40
- # Multi-level inheritance is also walked: `Admin::AccountsController
41
- # < BaseController < ApplicationController` resolves
42
- # methods from all three. Cycle-safe via a visited set.
43
- # The parent-name lookup is **lexically scoped** a bare
44
- # `BaseController` reference inside `module Admin` first
45
- # tries `Admin::BaseController`, then falls through to
46
- # top-level `BaseController`, matching Ruby's constant-
47
- # resolution semantics.
32
+ # Multi-level inheritance is also walked: `Admin::AccountsController < BaseController <
33
+ # ApplicationController` resolves methods from all three. Cycle-safe via a visited set. The
34
+ # parent-name lookup is **lexically scoped** a bare `BaseController` reference inside `module
35
+ # Admin` first tries `Admin::BaseController`, then falls through to top-level `BaseController`,
36
+ # matching Ruby's constant-resolution semantics.
48
37
  class ControllerDiscoverer
49
38
  def initialize(io_boundary:, search_paths:)
50
39
  @io_boundary = io_boundary
@@ -84,15 +73,12 @@ module Rigor
84
73
  nil
85
74
  end
86
75
 
87
- # Walks every `ClassNode` / `ModuleNode` in the AST,
88
- # yielding `[declaration_node, enclosing_namespace_array]`
89
- # for each. `enclosing` is the chain of module / class
90
- # qualifiers OUTSIDE the yielded declaration (e.g. for
91
- # `module Admin; class AccountsController; end; end`
92
- # the inner class yields with enclosing
93
- # `["Admin"]`). The yielded declaration's own segment
94
- # is added to the chain for its body's recursion so
95
- # constants nested two levels deep qualify correctly.
76
+ # Walks every `ClassNode` / `ModuleNode` in the AST, yielding `[declaration_node,
77
+ # enclosing_namespace_array]` for each. `enclosing` is the chain of module / class qualifiers
78
+ # OUTSIDE the yielded declaration (e.g. for `module Admin; class AccountsController; end; end`
79
+ # the inner class yields with enclosing `["Admin"]`). The yielded declaration's own segment is
80
+ # added to the chain for its body's recursion so constants nested two levels deep qualify
81
+ # correctly.
96
82
  def walk_declarations(node, namespace:, &)
97
83
  return unless node.is_a?(Prism::Node)
98
84
 
@@ -109,11 +95,9 @@ module Rigor
109
95
  end
110
96
  end
111
97
 
112
- # The segments contributed by a declaration to the
113
- # qualifier chain of its body. For `class A::B` this is
114
- # `["A", "B"]`; for `module Outer` it is `["Outer"]`.
115
- # Returns `[]` for an anonymous declaration the walker
116
- # cannot qualify.
98
+ # The segments contributed by a declaration to the qualifier chain of its body. For `class A::B`
99
+ # this is `["A", "B"]`; for `module Outer` it is `["Outer"]`. Returns `[]` for an anonymous
100
+ # declaration the walker cannot qualify.
117
101
  def namespace_segments_for(declaration_node)
118
102
  path = qualified_name_for(declaration_node.constant_path)
119
103
  path ? path.split("::") : []
@@ -133,13 +117,10 @@ module Rigor
133
117
  )
134
118
  end
135
119
 
136
- # Resolves the declared name against the enclosing
137
- # namespace chain. A `ConstantPathNode` (e.g.
138
- # `Admin::Foo` in `class Admin::Foo`) is already
139
- # absolute and ignores the enclosing chain. A
140
- # `ConstantReadNode` (bare `Foo` in `module Admin;
141
- # class Foo`) is qualified against the chain so the
142
- # name becomes `Admin::Foo`.
120
+ # Resolves the declared name against the enclosing namespace chain. A `ConstantPathNode` (e.g.
121
+ # `Admin::Foo` in `class Admin::Foo`) is already absolute and ignores the enclosing chain. A
122
+ # `ConstantReadNode` (bare `Foo` in `module Admin; class Foo`) is qualified against the chain so
123
+ # the name becomes `Admin::Foo`.
143
124
  def qualified_name_with_enclosing(node, enclosing)
144
125
  return nil unless node.is_a?(Prism::Node)
145
126
 
@@ -165,11 +146,9 @@ module Rigor
165
146
  accumulator
166
147
  end
167
148
 
168
- # Collects the qualified-constant targets passed to
169
- # `include` calls inside the body. Stops at nested
170
- # `ClassNode` / `ModuleNode` boundaries so a class
171
- # declared inside a concern doesn't pull the concern's
172
- # includes into itself.
149
+ # Collects the qualified-constant targets passed to `include` calls inside the body. Stops at
150
+ # nested `ClassNode` / `ModuleNode` boundaries so a class declared inside a concern doesn't pull
151
+ # the concern's includes into itself.
173
152
  def collect_include_targets(node, accumulator = [])
174
153
  return accumulator unless node.is_a?(Prism::Node)
175
154
  return accumulator if node.is_a?(Prism::ClassNode) || node.is_a?(Prism::ModuleNode)
@@ -3,13 +3,11 @@
3
3
  module Rigor
4
4
  module Plugin
5
5
  class Actionpack < Rigor::Plugin::Base
6
- # Per-run frozen index of discovered controllers AND
7
- # concerns (modules) in `controller_search_paths`. Phase 2
8
- # (filter-chain validation) consults the index at every
9
- # call site to check that `before_action :name` references
10
- # a method that actually exists on the controller, its
11
- # parent (one level of inheritance), or any module the
12
- # controller or its ancestor chain transitively `include`s.
6
+ # Per-run frozen index of discovered controllers AND concerns (modules) in
7
+ # `controller_search_paths`. Phase 2 (filter-chain validation) consults the index at every call
8
+ # site to check that `before_action :name` references a method that actually exists on the
9
+ # controller, its parent (one level of inheritance), or any module the controller or its ancestor
10
+ # chain transitively `include`s.
13
11
  #
14
12
  # Real-world example (Mastodon):
15
13
  # AccountsController < ApplicationController
@@ -19,23 +17,17 @@ module Rigor
19
17
  # SignatureVerification < module
20
18
  # def require_account_signature! # ← the filter target
21
19
  #
22
- # The include chain spans three concern modules.
23
- # `effective_methods_for("AccountsController")` walks all
24
- # of them transitively to collect `require_account_signature!`.
20
+ # The include chain spans three concern modules. `effective_methods_for("AccountsController")`
21
+ # walks all of them transitively to collect `require_account_signature!`.
25
22
  class ControllerIndex
26
- # `defined_methods` carries the discovered method names
27
- # (Symbols). `included_module_names` carries the constant
28
- # names passed to `include X` calls inside the
29
- # class / module body (Strings). `parent_class_name` is
30
- # the immediate superclass (nil for plain modules).
31
- # `enclosing_namespace` is the qualifier chain of the
32
- # declaration's *lexical* enclosing scope (e.g.
33
- # `["Admin"]` for an `Admin::Foo` declared via
34
- # `module Admin; class Foo; end; end`). Used by the
35
- # index's parent / module lookup to try lexically-scoped
36
- # constant resolution before falling through to the
37
- # top-level form — Ruby's constant lookup walks the
38
- # enclosing scope chain before `Object`.
23
+ # `defined_methods` carries the discovered method names (Symbols). `included_module_names`
24
+ # carries the constant names passed to `include X` calls inside the class / module body
25
+ # (Strings). `parent_class_name` is the immediate superclass (nil for plain modules).
26
+ # `enclosing_namespace` is the qualifier chain of the declaration's *lexical* enclosing scope
27
+ # (e.g. `["Admin"]` for an `Admin::Foo` declared via `module Admin; class Foo; end; end`). Used
28
+ # by the index's parent / module lookup to try lexically-scoped constant resolution before
29
+ # falling through to the top-level form — Ruby's constant lookup walks the enclosing scope chain
30
+ # before `Object`.
39
31
  Entry = Data.define(:class_name, :defined_methods, :parent_class_name, :included_module_names,
40
32
  :enclosing_namespace)
41
33
 
@@ -51,20 +43,15 @@ module Rigor
51
43
  @entries[class_name]
52
44
  end
53
45
 
54
- # Resolves the **effective** method set for a controller,
55
- # including methods contributed by every module the
56
- # controller / any ancestor transitively `include`s AND
57
- # methods inherited from the ancestor chain (unbounded
58
- # depth, cycle-safe via a visited set).
46
+ # Resolves the **effective** method set for a controller, including methods contributed by
47
+ # every module the controller / any ancestor transitively `include`s AND methods inherited from
48
+ # the ancestor chain (unbounded depth, cycle-safe via a visited set).
59
49
  #
60
- # Parent / module lookups are **lexically scoped** — a
61
- # bare `BaseController` reference inside `module Admin`
62
- # first tries `Admin::BaseController`, then falls
63
- # through to the top-level `BaseController`. Matches
64
- # Ruby's constant-resolution semantics. Without this an
65
- # `Admin::Foo < BaseController` declaration would
66
- # incorrectly walk the top-level `BaseController` even
67
- # when an `Admin::BaseController` exists.
50
+ # Parent / module lookups are **lexically scoped** — a bare `BaseController` reference inside
51
+ # `module Admin` first tries `Admin::BaseController`, then falls through to the top-level
52
+ # `BaseController`. Matches Ruby's constant-resolution semantics. Without this an `Admin::Foo <
53
+ # BaseController` declaration would incorrectly walk the top-level `BaseController` even when an
54
+ # `Admin::BaseController` exists.
68
55
  def effective_methods_for(class_name)
69
56
  seen_classes = {}
70
57
  seen_modules = {}
@@ -81,11 +68,9 @@ module Rigor
81
68
  collect_methods(resolved_include, seen_modules, methods)
82
69
  end
83
70
  next_parent = entry.parent_class_name
84
- # Same self-reference guard as `unresolved_include?`:
85
- # `class ActivityPub::ApplicationController <
86
- # ::ApplicationController` lexically resolves
87
- # `ApplicationController` to itself; fall back to
88
- # the unprefixed top-level name in that case.
71
+ # Same self-reference guard as `unresolved_include?`: `class ActivityPub::ApplicationController
72
+ # < ::ApplicationController` lexically resolves `ApplicationController` to itself; fall back
73
+ # to the unprefixed top-level name in that case.
89
74
  current = if next_parent
90
75
  resolved = resolve_constant_lexically(next_parent, entry.enclosing_namespace)
91
76
  resolved == current ? next_parent.sub(/\A::/, "") : resolved
@@ -94,30 +79,23 @@ module Rigor
94
79
  methods.uniq.freeze
95
80
  end
96
81
 
97
- # @return [Boolean] true when the class has at least one
98
- # include OR parent class we couldn't resolve in the
99
- # index (typically a gem-shipped concern such as Devise's
100
- # `Devise::Controllers::Helpers`, or a gem-shipped
101
- # parent controller such as `Devise::ConfirmationsController`
102
- # or `Doorkeeper::AuthorizedApplicationsController`).
103
- # Phase 2 uses this to downgrade `unknown-filter-method`
104
- # to silence — the unresolved module / parent may
105
- # legitimately contribute the filter (either directly,
106
- # or via its own ancestor chain which the static
107
- # analyzer cannot follow), and there's no way to verify.
82
+ # @return [Boolean] true when the class has at least one include OR parent class we couldn't
83
+ # resolve in the index (typically a gem-shipped concern such as Devise's
84
+ # `Devise::Controllers::Helpers`, or a gem-shipped parent controller such as
85
+ # `Devise::ConfirmationsController` or `Doorkeeper::AuthorizedApplicationsController`). Phase
86
+ # 2 uses this to downgrade `unknown-filter-method` to silence — the unresolved module / parent
87
+ # may legitimately contribute the filter (either directly, or via its own ancestor chain which
88
+ # the static analyzer cannot follow), and there's no way to verify.
108
89
  def unresolved_include?(class_name)
109
90
  entry = @entries[class_name]
110
91
  return false if entry.nil?
111
92
 
112
- # Walk the full ancestor chain. `Admin::Foo <
113
- # BaseController < ApplicationController` should report
114
- # an unresolved include if ANY of the three references
115
- # a gem-shipped concern OR a gem-shipped parent class
116
- # we cannot index. The first iteration's `current_entry`
117
- # is always resolved (caller verified `known?`); a nil
118
- # `current_entry` on a subsequent iteration means the
119
- # AST-side `< Parent` reached a gem-shipped class
120
- # whose ancestor methods are invisible to us.
93
+ # Walk the full ancestor chain. `Admin::Foo < BaseController < ApplicationController` should
94
+ # report an unresolved include if ANY of the three references a gem-shipped concern OR a
95
+ # gem-shipped parent class we cannot index. The first iteration's `current_entry` is always
96
+ # resolved (caller verified `known?`); a nil `current_entry` on a subsequent iteration means
97
+ # the AST-side `< Parent` reached a gem-shipped class whose ancestor methods are invisible to
98
+ # us.
121
99
  seen_classes = {}
122
100
  current = class_name
123
101
  first = true
@@ -136,15 +114,11 @@ module Rigor
136
114
  return true if resolved.nil? || !@entries.key?(resolved)
137
115
  end
138
116
  next_parent = current_entry.parent_class_name
139
- # Avoid lexically resolving to ourselves. `class
140
- # ActivityPub::ApplicationController < ::ApplicationController`
141
- # would otherwise resolve `ApplicationController` (in
142
- # the lexical scope `["ActivityPub"]`) to
143
- # `ActivityPub::ApplicationController` and short-
144
- # circuit the walk before reaching the top-level
145
- # parent. When the lexical match is the current
146
- # class itself, fall back to the unprefixed
147
- # top-level name.
117
+ # Avoid lexically resolving to ourselves. `class ActivityPub::ApplicationController <
118
+ # ::ApplicationController` would otherwise resolve `ApplicationController` (in the lexical
119
+ # scope `["ActivityPub"]`) to `ActivityPub::ApplicationController` and short-circuit the walk
120
+ # before reaching the top-level parent. When the lexical match is the current class itself,
121
+ # fall back to the unprefixed top-level name.
148
122
  current = if next_parent
149
123
  resolved = resolve_constant_lexically(next_parent, current_entry.enclosing_namespace)
150
124
  resolved == current ? next_parent.sub(/\A::/, "") : resolved
@@ -181,37 +155,28 @@ module Rigor
181
155
  end
182
156
  end
183
157
 
184
- # Ruby's constant-lookup walk: a bare constant name
185
- # inside `module Admin` first tries `Admin::Const`,
186
- # then walks outward, and finally falls through to
187
- # top-level `Const`. We approximate that by trying
188
- # the candidate `enclosing + name` chains from
189
- # deepest to shallowest, and returning the first
190
- # candidate that has an entry in the index. When
191
- # nothing resolves, return the original name
192
- # unchanged — the caller treats unresolved entries as
193
- # "gem-shipped concerns we cannot see" (the
194
- # `unresolved_include?` predicate).
158
+ # Ruby's constant-lookup walk: a bare constant name inside `module Admin` first tries
159
+ # `Admin::Const`, then walks outward, and finally falls through to top-level `Const`. We
160
+ # approximate that by trying the candidate `enclosing + name` chains from deepest to shallowest,
161
+ # and returning the first candidate that has an entry in the index. When nothing resolves,
162
+ # return the original name unchanged the caller treats unresolved entries as "gem-shipped
163
+ # concerns we cannot see" (the `unresolved_include?` predicate).
195
164
  #
196
- # `name` may already be qualified (`Foo::Bar`); we
197
- # only try lexical prefixing when the unqualified
198
- # first segment doesn't match a top-level entry.
165
+ # `name` may already be qualified (`Foo::Bar`); we only try lexical prefixing when the
166
+ # unqualified first segment doesn't match a top-level entry.
199
167
  def resolve_constant_lexically(name, enclosing)
200
168
  return nil if name.nil?
201
169
 
202
- # A leading `::` denotes the top-level constant
203
- # explicitly (`< ::ApplicationController`). Strip it
204
- # for index lookup the discoverer registers entries
205
- # under their unprefixed name. Without this strip a
206
- # `class ActivityPub::ApplicationController <
207
- # ::ApplicationController` parent never resolved.
170
+ # A leading `::` denotes the top-level constant explicitly (`< ::ApplicationController`).
171
+ # Strip it for index lookup — the discoverer registers entries under their unprefixed name.
172
+ # Without this strip a `class ActivityPub::ApplicationController < ::ApplicationController`
173
+ # parent never resolved.
208
174
  name = name.sub(/\A::/, "")
209
175
 
210
176
  # Constant already absolute or no enclosing scope.
211
177
  return name if enclosing.nil? || enclosing.empty?
212
178
 
213
- # Try the deepest enclosing scope first, walking
214
- # outward. `enclosing = ["A", "B"]` produces
179
+ # Try the deepest enclosing scope first, walking outward. `enclosing = ["A", "B"]` produces
215
180
  # candidates `["A::B::name", "A::name", "name"]`.
216
181
  enclosing.length.downto(0).each do |depth|
217
182
  prefix = enclosing[0, depth]