rigortype 0.3.9 → 0.4.1
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.
- checksums.yaml +4 -4
- data/README.md +5 -4
- data/data/core_overlay/enumerable.rbs +51 -0
- data/data/core_overlay/enumerator.rbs +84 -0
- data/data/core_overlay/hash_rbs3.rbs +41 -0
- data/data/core_overlay/process.rbs +40 -0
- data/data/core_overlay/string_io.rbs +33 -0
- data/data/effects/core.yml +3 -3
- data/data/gem_overlay/activesupport/core_ext.rbs +127 -4
- data/docs/handbook/03-narrowing.md +95 -10
- data/docs/handbook/04-tuples-and-shapes.md +8 -6
- data/docs/handbook/07-rbs-and-extended.md +16 -11
- data/docs/handbook/08-understanding-errors.md +3 -2
- data/docs/handbook/10-sorbet.md +9 -10
- data/docs/handbook/11-sig-gen.md +454 -13
- data/docs/install.md +87 -15
- data/docs/manual/02-cli-reference.md +65 -4
- data/docs/manual/03-configuration.md +12 -0
- data/docs/manual/04-diagnostics.md +4 -0
- data/docs/manual/07-plugins.md +1 -1
- data/docs/manual/08-skills.md +4 -3
- data/docs/manual/10-mcp-server.md +3 -2
- data/docs/manual/12-caching.md +43 -4
- data/docs/manual/14-rails-quickstart.md +19 -11
- data/docs/manual/16-rbs-extended-annotations.md +40 -7
- data/docs/manual/19-effect-labels.md +10 -0
- data/docs/manual/plugins/README.md +7 -0
- data/docs/manual/plugins/rigor-actioncable.md +8 -1
- data/docs/manual/plugins/rigor-actionmailer.md +7 -0
- data/docs/manual/plugins/rigor-actionpack.md +243 -0
- data/docs/manual/plugins/rigor-active-model-serializers.md +153 -0
- data/docs/manual/plugins/rigor-activejob.md +7 -0
- data/docs/manual/plugins/rigor-activerecord.md +110 -4
- data/docs/manual/plugins/rigor-activestorage.md +8 -1
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +11 -5
- data/docs/manual/plugins/rigor-grape.md +106 -0
- data/docs/manual/plugins/rigor-graphql.md +23 -2
- data/docs/manual/plugins/rigor-pundit.md +8 -1
- data/docs/manual/plugins/rigor-rails-i18n.md +10 -5
- data/docs/manual/plugins/rigor-rails-routes.md +7 -0
- data/docs/manual/plugins/rigor-rbs-inline.md +212 -25
- data/docs/manual/plugins/rigor-sidekiq.md +8 -1
- data/docs/manual/plugins/rigor-sorbet.md +21 -5
- data/exe/rigor +19 -4
- data/lib/rigor/analysis/baseline.rb +1 -1
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +167 -2
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +189 -0
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +5 -3
- data/lib/rigor/analysis/check_rules/rule_ids.rb +20 -5
- data/lib/rigor/analysis/check_rules/rule_walk.rb +2 -1
- data/lib/rigor/analysis/check_rules/source_arity.rb +427 -0
- data/lib/rigor/analysis/check_rules/special_global_setters.rb +146 -0
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +36 -2
- data/lib/rigor/analysis/check_rules.rb +638 -136
- data/lib/rigor/analysis/dependency_recorder.rb +222 -17
- data/lib/rigor/analysis/fact_store.rb +9 -0
- data/lib/rigor/analysis/incremental.rb +26 -0
- data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +266 -0
- data/lib/rigor/analysis/incremental_run_slot.rb +171 -0
- data/lib/rigor/analysis/incremental_session.rb +309 -53
- data/lib/rigor/analysis/plugin_fact_fingerprint.rb +24 -13
- data/lib/rigor/analysis/project_scan.rb +11 -1
- data/lib/rigor/analysis/reachability/plugin_roots.rb +0 -1
- data/lib/rigor/analysis/reachability/scan_cache.rb +3 -1
- data/lib/rigor/analysis/rule_catalog.rb +127 -0
- data/lib/rigor/analysis/run_cache_key.rb +46 -18
- data/lib/rigor/analysis/run_stats.rb +2 -2
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +168 -12
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +9 -4
- data/lib/rigor/analysis/runner/pool_coordinator.rb +109 -17
- data/lib/rigor/analysis/runner/project_pre_passes.rb +44 -17
- data/lib/rigor/analysis/runner.rb +603 -54
- data/lib/rigor/analysis/shadow_harness.rb +27 -0
- data/lib/rigor/analysis/source_rbs_gate.rb +157 -0
- data/lib/rigor/analysis/template_unit_collector.rb +303 -0
- data/lib/rigor/analysis/template_unit_paths.rb +93 -0
- data/lib/rigor/analysis/template_unit_positions.rb +293 -0
- data/lib/rigor/analysis/template_units.rb +409 -0
- data/lib/rigor/analysis/worker_session.rb +57 -13
- data/lib/rigor/bleeding_edge.rb +0 -2
- data/lib/rigor/builtins/hkt_builtins.rb +1 -0
- data/lib/rigor/builtins/imported_refinements.rb +4 -0
- data/lib/rigor/builtins/regex_refinement.rb +17 -9
- data/lib/rigor/builtins/static_return_refinements.rb +2 -0
- data/lib/rigor/cache/descriptor.rb +45 -1
- data/lib/rigor/cache/engine_source.rb +29 -1
- data/lib/rigor/cache/file_digest.rb +28 -0
- data/lib/rigor/cache/incremental_snapshot.rb +102 -8
- data/lib/rigor/cache/rbs_cache_producer.rb +4 -0
- data/lib/rigor/cache/rbs_descriptor.rb +37 -7
- data/lib/rigor/cache/store.rb +63 -4
- data/lib/rigor/cache/value_digest.rb +325 -0
- data/lib/rigor/ci_detector.rb +1 -0
- data/lib/rigor/cli/check_command.rb +83 -13
- data/lib/rigor/cli/doc_links.rb +1 -1
- data/lib/rigor/cli/docs_command.rb +4 -4
- data/lib/rigor/cli/doctor_command.rb +1 -1
- data/lib/rigor/cli/effects_report.rb +2 -2
- data/lib/rigor/cli/plugin_command.rb +3 -3
- data/lib/rigor/cli/prism_colorizer.rb +0 -1
- data/lib/rigor/cli/sig_gen_command.rb +210 -29
- data/lib/rigor/cli/skill_command.rb +1 -1
- data/lib/rigor/cli/skill_describe.rb +0 -1
- data/lib/rigor/cli/type_of_command.rb +19 -5
- data/lib/rigor/cli/type_of_renderer.rb +20 -9
- data/lib/rigor/cli/type_of_template_probe.rb +189 -0
- data/lib/rigor/cli/unused_command.rb +3 -3
- data/lib/rigor/cli.rb +21 -3
- data/lib/rigor/config_audit.rb +3 -2
- data/lib/rigor/config_path.rb +29 -0
- data/lib/rigor/configuration/severity_profile.rb +24 -3
- data/lib/rigor/configuration.rb +71 -7
- data/lib/rigor/effects/ancestry_recorder.rb +191 -0
- data/lib/rigor/effects/attribution.rb +11 -2
- data/lib/rigor/effects/callee_rule.rb +368 -0
- data/lib/rigor/effects/catalog.rb +7 -4
- data/lib/rigor/effects/collector.rb +11 -5
- data/lib/rigor/effects/config_envelopes.rb +9 -2
- data/lib/rigor/effects/definition_context.rb +179 -0
- data/lib/rigor/effects/effect_table.rb +11 -3
- data/lib/rigor/effects/envelope_check.rb +1 -1
- data/lib/rigor/effects/envelope_index.rb +15 -0
- data/lib/rigor/effects/file_collection.rb +59 -5
- data/lib/rigor/effects/framework_units.rb +1 -1
- data/lib/rigor/effects/identity.rb +16 -0
- data/lib/rigor/effects/local_ownership.rb +38 -12
- data/lib/rigor/effects/method_key.rb +21 -0
- data/lib/rigor/effects/mutation_classifier.rb +23 -12
- data/lib/rigor/effects/plugin_facts.rb +49 -37
- data/lib/rigor/effects/propagator.rb +295 -16
- data/lib/rigor/effects/registry.rb +1 -1
- data/lib/rigor/effects/scanner.rb +121 -72
- data/lib/rigor/effects/signature_sources.rb +1 -1
- data/lib/rigor/effects/snapshot.rb +2 -1
- data/lib/rigor/effects/summary.rb +27 -4
- data/lib/rigor/effects/unit_scan.rb +385 -30
- data/lib/rigor/effects/visibility.rb +101 -0
- data/lib/rigor/environment/bundle_sig_discovery.rb +5 -3
- data/lib/rigor/environment/lockfile_resolver.rb +27 -1
- data/lib/rigor/environment/member_consistency/comparator.rb +708 -0
- data/lib/rigor/environment/member_consistency.rb +298 -0
- data/lib/rigor/environment/rbs_collection_discovery.rb +10 -1
- data/lib/rigor/environment/rbs_loader.rb +400 -134
- data/lib/rigor/environment/source_rbs_synthesis.rb +147 -0
- data/lib/rigor/environment.rb +104 -96
- data/lib/rigor/hashing/xxh3.rb +264 -0
- data/lib/rigor/inference/acceptance.rb +139 -9
- data/lib/rigor/inference/block_auto_splat.rb +216 -0
- data/lib/rigor/inference/block_call_timing.rb +338 -0
- data/lib/rigor/inference/block_parameter_binder.rb +88 -26
- data/lib/rigor/inference/block_repetition.rb +71 -0
- data/lib/rigor/inference/body_fixpoint.rb +2 -1
- data/lib/rigor/inference/budget_trace.rb +2 -1
- data/lib/rigor/inference/builtins/method_catalog.rb +2 -1
- data/lib/rigor/inference/builtins/string_catalog.rb +1 -1
- data/lib/rigor/inference/captured_locals.rb +393 -15
- data/lib/rigor/inference/closure_escape_analyzer.rb +157 -13
- data/lib/rigor/inference/content_join.rb +200 -27
- data/lib/rigor/inference/declaration_walk/context.rb +195 -0
- data/lib/rigor/inference/declaration_walk/errors.rb +18 -0
- data/lib/rigor/inference/declaration_walk/shadow.rb +147 -0
- data/lib/rigor/inference/declaration_walk/traversal.rb +441 -0
- data/lib/rigor/inference/declaration_walk.rb +7 -0
- data/lib/rigor/inference/def_node_resolver.rb +3 -2
- data/lib/rigor/inference/def_return_typer.rb +11 -7
- data/lib/rigor/inference/define_method_block_self.rb +64 -0
- data/lib/rigor/inference/definer_resolution.rb +266 -0
- data/lib/rigor/inference/element_read_widening.rb +22 -10
- data/lib/rigor/inference/error_info.rb +196 -0
- data/lib/rigor/inference/expression_typer.rb +1665 -538
- data/lib/rigor/inference/external_ancestor_resolution.rb +264 -0
- data/lib/rigor/inference/fresh_frame_blocks.rb +127 -0
- data/lib/rigor/inference/global_write_census.rb +239 -0
- data/lib/rigor/inference/guard_rebinding.rb +488 -0
- data/lib/rigor/inference/hash_lookup_mutation.rb +88 -0
- data/lib/rigor/inference/index_write_widening.rb +16 -3
- data/lib/rigor/inference/indexed_narrowing.rb +61 -9
- data/lib/rigor/inference/jump_targets.rb +82 -0
- data/lib/rigor/inference/last_line/implicit_self.rb +210 -0
- data/lib/rigor/inference/last_line/self_evidence.rb +329 -0
- data/lib/rigor/inference/last_line.rb +340 -0
- data/lib/rigor/inference/last_status.rb +144 -0
- data/lib/rigor/inference/macro_block_self_type.rb +179 -17
- data/lib/rigor/inference/match_rebinding/calls.rb +281 -0
- data/lib/rigor/inference/match_rebinding/frame.rb +148 -0
- data/lib/rigor/inference/match_rebinding/operands.rb +236 -0
- data/lib/rigor/inference/match_rebinding/self_calls.rb +83 -0
- data/lib/rigor/inference/match_rebinding.rb +392 -0
- data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +36 -0
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +85 -24
- data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +147 -0
- data/lib/rigor/inference/method_dispatcher/hash_transform_keys_folding.rb +191 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +4 -0
- data/lib/rigor/inference/method_dispatcher/match_data_folding.rb +159 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +113 -73
- data/lib/rigor/inference/method_dispatcher/process_folding.rb +56 -0
- data/lib/rigor/inference/method_dispatcher/proven_overload.rb +72 -0
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +901 -38
- data/lib/rigor/inference/method_dispatcher/self_substitute.rb +142 -0
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +128 -53
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher.rb +214 -13
- data/lib/rigor/inference/method_parameter_binder.rb +8 -3
- data/lib/rigor/inference/module_function_state.rb +213 -0
- data/lib/rigor/inference/multi_target_binder.rb +345 -52
- data/lib/rigor/inference/mutation_rejoin.rb +4 -1
- data/lib/rigor/inference/mutation_widening.rb +70 -48
- data/lib/rigor/inference/narrowing.rb +674 -124
- data/lib/rigor/inference/operand_effects.rb +167 -0
- data/lib/rigor/inference/operand_walk.rb +88 -0
- data/lib/rigor/inference/optimistic_origin.rb +152 -9
- data/lib/rigor/inference/parameter_inference_collector.rb +13 -11
- data/lib/rigor/inference/project_method_ownership.rb +136 -0
- data/lib/rigor/inference/project_patched_methods.rb +7 -2
- data/lib/rigor/inference/project_patched_scanner.rb +7 -3
- data/lib/rigor/inference/receiver_alias.rb +90 -1
- data/lib/rigor/inference/receiver_blind_block.rb +219 -0
- data/lib/rigor/inference/refinement_mutation.rb +15 -11
- data/lib/rigor/inference/repeated_or_writes.rb +463 -0
- data/lib/rigor/inference/return_barrier.rb +54 -0
- data/lib/rigor/inference/rewrite_mutation.rb +120 -0
- data/lib/rigor/inference/scope_indexer/certainty.rb +176 -0
- data/lib/rigor/inference/scope_indexer/class_cvars_collector.rb +35 -0
- data/lib/rigor/inference/scope_indexer/def_nestings_collector.rb +47 -0
- data/lib/rigor/inference/scope_indexer/layered_def_nestings.rb +36 -0
- data/lib/rigor/inference/scope_indexer/member_layouts_collector.rb +61 -0
- data/lib/rigor/inference/scope_indexer/mixin_accumulator.rb +130 -0
- data/lib/rigor/inference/scope_indexer/superclasses_collector.rb +64 -0
- data/lib/rigor/inference/scope_indexer.rb +5913 -701
- data/lib/rigor/inference/singleton_hook_decline.rb +253 -0
- data/lib/rigor/inference/statement_evaluator.rb +3249 -497
- data/lib/rigor/inference/stored_block_call.rb +54 -0
- data/lib/rigor/inference/string_mutation.rb +44 -7
- data/lib/rigor/inference/unknown_store_widening.rb +200 -0
- data/lib/rigor/inference/unthreaded_rebinds.rb +282 -0
- data/lib/rigor/language_server/debouncer.rb +0 -1
- data/lib/rigor/language_server/diagnostic_publisher.rb +3 -2
- data/lib/rigor/language_server/hover_renderer.rb +3 -3
- data/lib/rigor/language_server/project_context.rb +5 -3
- data/lib/rigor/mcp/server.rb +2 -1
- data/lib/rigor/plugin/base.rb +196 -13
- data/lib/rigor/plugin/box_probe.rb +91 -0
- data/lib/rigor/plugin/bundled_catalog.rb +1 -1
- data/lib/rigor/plugin/effect_attribution.rb +58 -4
- data/lib/rigor/plugin/io_boundary.rb +82 -4
- data/lib/rigor/plugin/isolation.rb +1 -1
- data/lib/rigor/plugin/loader.rb +2 -1
- data/lib/rigor/plugin/macro/block_as_method.rb +45 -6
- data/lib/rigor/plugin/manifest.rb +71 -10
- data/lib/rigor/plugin/registry.rb +35 -1
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +9 -3
- data/lib/rigor/plugin/template_unit.rb +196 -0
- data/lib/rigor/plugin/trust_policy.rb +3 -3
- data/lib/rigor/plugin.rb +1 -0
- data/lib/rigor/protection/discovery_seed.rb +20 -9
- data/lib/rigor/protection/kill_signature.rb +0 -1
- data/lib/rigor/protection/mutation_cache.rb +4 -5
- data/lib/rigor/rbs_extended.rb +27 -0
- data/lib/rigor/reflection/constant_ancestors.rb +146 -0
- data/lib/rigor/reflection/constant_path.rb +41 -13
- data/lib/rigor/reflection.rb +73 -107
- data/lib/rigor/scope/discovery_index.rb +351 -2
- data/lib/rigor/scope/resolution_chain/relevance.rb +165 -0
- data/lib/rigor/scope/resolution_chain.rb +884 -0
- data/lib/rigor/scope.rb +981 -198
- data/lib/rigor/sig_gen/alias_index.rb +289 -0
- data/lib/rigor/sig_gen/classification.rb +22 -5
- data/lib/rigor/sig_gen/declaration_equivalence.rb +127 -0
- data/lib/rigor/sig_gen/effect_annotation.rb +202 -0
- data/lib/rigor/sig_gen/generator.rb +580 -47
- data/lib/rigor/sig_gen/inline_declarations.rb +184 -0
- data/lib/rigor/sig_gen/method_candidate.rb +47 -3
- data/lib/rigor/sig_gen/observation_collector.rb +1 -1
- data/lib/rigor/sig_gen/renderer.rb +124 -9
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +44 -1
- data/lib/rigor/sig_gen/write_result.rb +19 -3
- data/lib/rigor/sig_gen/writer.rb +166 -35
- data/lib/rigor/sig_gen.rb +3 -0
- data/lib/rigor/signature_path_audit.rb +1 -1
- data/lib/rigor/source/node_walker.rb +0 -3
- data/lib/rigor/source/parameter_envelope.rb +72 -0
- data/lib/rigor/source.rb +1 -0
- data/lib/rigor/type/combinator.rb +112 -12
- data/lib/rigor/type/difference.rb +1 -0
- data/lib/rigor/type/hash_shape.rb +1 -1
- data/lib/rigor/type/refined.rb +1 -0
- data/lib/rigor/version.rb +1 -1
- data/lib/rigor.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/effects.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +9 -5
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +13 -4
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +0 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +96 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/effects.rb +65 -8
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +270 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/render_locals.rb +402 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +370 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_units.rb +132 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +239 -4
- data/plugins/rigor-actionpack/sig/action_view.rbs +43 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_discoverer.rb +220 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_index.rb +56 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +263 -0
- data/plugins/rigor-active-model-serializers/lib/rigor-active-model-serializers.rb +7 -0
- data/plugins/rigor-active-model-serializers/sig/active_model_serializers.rbs +45 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +9 -5
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +35 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +72 -12
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +380 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +14 -6
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +281 -35
- data/plugins/rigor-activerecord/sig/active_record/relation.rbs +206 -31
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +25 -14
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +9 -2
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +171 -5
- data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +2 -0
- data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +1 -0
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/types.rb +1 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +10 -0
- data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +141 -0
- data/plugins/rigor-grape/lib/rigor-grape.rb +6 -0
- data/plugins/rigor-grape/sig/grape.rbs +263 -0
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +72 -2
- data/plugins/rigor-graphql/sig/graphql.rbs +485 -0
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +2 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +11 -7
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +35 -37
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +0 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +2 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +1 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +9 -17
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline/same_line_annotations.rb +149 -0
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +217 -36
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/schedule_scan.rb +1 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +9 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +0 -1
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +46 -1
- data/plugins/rigor-sorbet/sig/sorbet.rbs +277 -0
- data/sig/rigor/analysis/baseline.rbs +69 -7
- data/sig/rigor/analysis/fact_store.rbs +1 -1
- data/sig/rigor/analysis/project_scan.rbs +74 -0
- data/sig/rigor/effects/config_envelopes.rbs +100 -0
- data/sig/rigor/effects/effect_table.rbs +60 -0
- data/sig/rigor/effects/envelope.rbs +97 -0
- data/sig/rigor/effects/envelope_index.rbs +33 -0
- data/sig/rigor/effects/file_collection.rbs +81 -0
- data/sig/rigor/effects/label.rbs +26 -0
- data/sig/rigor/effects/label_set.rbs +46 -0
- data/sig/rigor/effects/method_key.rbs +24 -0
- data/sig/rigor/effects/origin.rbs +50 -0
- data/sig/rigor/effects/plugin_facts.rbs +141 -0
- data/sig/rigor/effects/registry.rbs +68 -0
- data/sig/rigor/effects/summary.rbs +50 -0
- data/sig/rigor/effects/taint_cause.rbs +12 -0
- data/sig/rigor/environment.rbs +14 -10
- data/sig/rigor/inference/optimistic_origin.rbs +10 -0
- data/sig/rigor/inference.rbs +6 -4
- data/sig/rigor/plugin/additional_initializer.rbs +36 -0
- data/sig/rigor/plugin/base.rbs +30 -7
- data/sig/rigor/plugin/effect_ancestry.rbs +27 -0
- data/sig/rigor/plugin/effect_attribution.rbs +66 -0
- data/sig/rigor/plugin/effect_edge.rbs +33 -0
- data/sig/rigor/plugin/effect_entry_points.rbs +25 -0
- data/sig/rigor/plugin/io_boundary.rbs +2 -1
- data/sig/rigor/plugin/loader.rbs +3 -3
- data/sig/rigor/plugin/manifest.rbs +50 -11
- data/sig/rigor/plugin/protocol_contract.rbs +68 -0
- data/sig/rigor/plugin/registry.rbs +62 -1
- data/sig/rigor/plugin.rbs +1 -1
- data/sig/rigor/rbs_extended.rbs +1 -1
- data/sig/rigor/reflection.rbs +7 -6
- data/sig/rigor/scope.rbs +177 -20
- data/sig/rigor/sig_gen/skip_reason_catalog.rbs +14 -7
- data/sig/rigor/source.rbs +4 -4
- data/sig/rigor/testing.rbs +10 -4
- data/sig/rigor/type.rbs +6 -0
- data/sig/rigor.rbs +38 -20
- data/skills/rigor-ask/SKILL.md +8 -5
- data/skills/rigor-baseline-reduce/SKILL.md +4 -6
- data/skills/rigor-ci-setup/SKILL.md +17 -21
- data/skills/rigor-doctor/SKILL.md +24 -22
- data/skills/rigor-doctor/references/01-checks.md +97 -33
- data/skills/rigor-editor-setup/SKILL.md +6 -4
- data/skills/rigor-mcp-setup/SKILL.md +5 -4
- data/skills/rigor-monkeypatch-resolve/SKILL.md +5 -3
- data/skills/rigor-next-steps/SKILL.md +4 -2
- data/skills/rigor-plugin-author/SKILL.md +19 -23
- data/skills/rigor-plugin-author/references/01-plan-and-scaffold.md +9 -8
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +12 -25
- data/skills/rigor-plugin-author/references/03-test-and-ship.md +6 -8
- data/skills/rigor-plugin-review/SKILL.md +6 -4
- data/skills/rigor-plugin-review/references/01-best-practices-checklist.md +2 -1
- data/skills/rigor-plugin-tune/SKILL.md +4 -2
- data/skills/rigor-project-init/SKILL.md +46 -18
- data/skills/rigor-project-init/references/01-detect.md +13 -9
- data/skills/rigor-project-init/references/02-configure.md +40 -10
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +14 -14
- data/skills/rigor-project-init/references/04-sig-uplift.md +27 -14
- data/skills/rigor-protection-uplift/SKILL.md +4 -6
- data/skills/rigor-rbs-setup/SKILL.md +4 -2
- data/skills/rigor-type-oracle/SKILL.md +4 -6
- data/skills/rigor-type-oracle/references/01-oracle-commands.md +12 -8
- data/skills/rigor-type-oracle/references/03-gap-protocol.md +0 -3
- data/skills/rigor-unused-adjudicate/SKILL.md +4 -2
- data/skills/rigor-upgrade/SKILL.md +13 -8
- metadata +132 -1
data/lib/rigor/reflection.rb
CHANGED
|
@@ -45,9 +45,10 @@ module Rigor
|
|
|
45
45
|
# out of scope for the v0.0.7 first pass; v0.1.0's plugin API added it as a separate
|
|
46
46
|
# concern.
|
|
47
47
|
module Reflection
|
|
48
|
-
# #
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
# Issue #1290 — what {.constant_type_at} answers for a candidate the project writes but no source types, on
|
|
49
|
+
# a ladder that checks the census. Never a type: {.resolve_constant_type} replaces it before it returns.
|
|
50
|
+
WRITTEN_CANDIDATE = Object.new.freeze
|
|
51
|
+
private_constant :WRITTEN_CANDIDATE
|
|
51
52
|
|
|
52
53
|
module_function
|
|
53
54
|
|
|
@@ -140,10 +141,16 @@ module Rigor
|
|
|
140
141
|
# answer to `::Foo`, and falling back to it was the bug (`::Rails` inside `module MyApp` typed
|
|
141
142
|
# as `MyApp::Rails`).
|
|
142
143
|
#
|
|
144
|
+
# `caller_derived: false` drops what {.toplevel_first_constant_type} takes from the caller — its
|
|
145
|
+
# namespaces and ancestors, for a bare name and for a path's head — for a reader whose miss is a
|
|
146
|
+
# meaningful answer rather than a read Ruby raises on. A constant compound write is one: an unset
|
|
147
|
+
# top-level `REGISTRY ||= {}` is the memoization idiom, and the caller's `Plugin::REGISTRY` is a binding
|
|
148
|
+
# Ruby never consults there. A path's later segments still walk their owner's ancestors.
|
|
149
|
+
#
|
|
143
150
|
# This is the shared owner of the lexical-constant resolution: `Inference::ExpressionTyper`
|
|
144
151
|
# reads it to type a constant read, and `Inference::Narrowing` reads it to recognise a
|
|
145
152
|
# value-pinned `Constant[Regexp]` match-predicate operand.
|
|
146
|
-
def resolve_constant_type(name, scope: Scope.empty, rooted: false)
|
|
153
|
+
def resolve_constant_type(name, scope: Scope.empty, rooted: false, caller_derived: true)
|
|
147
154
|
# Issue #644 — the ADR-46 name edge, recorded ONCE PER REFERENCE and BEFORE the ladder, so it does not
|
|
148
155
|
# depend on which resolver answers. A reference that resolves through RBS (`Math::PI`) or through the
|
|
149
156
|
# class registry is exactly as dependent on the project's constant write set as one that resolves
|
|
@@ -153,10 +160,25 @@ module Rigor
|
|
|
153
160
|
# go stale. Over-recording is ADR-46's safe direction.
|
|
154
161
|
record_constant_reference(name) if Analysis::DependencyRecorder.active?
|
|
155
162
|
return constant_type_at(name, scope) if rooted
|
|
163
|
+
|
|
164
|
+
# Issue #1290 — a candidate the project writes but no source types is where Ruby's lookup stops, so it
|
|
165
|
+
# REPLACES what a lower rung answers, and nothing else. The first pass hands the census's shadowing
|
|
166
|
+
# names to the rungs ({.constant_type_at}); a stop is `Dynamic[top]` only when the plain ladder, run
|
|
167
|
+
# again, answers below it. When nothing below answers, the reference stays unresolved exactly as before,
|
|
168
|
+
# so the nil its caller turns into the fallback, the missing-constant edge and the gem-origin label stay.
|
|
169
|
+
hit = lexical_constant_type(name, scope, caller_derived, scope.shadowing_constant_names(name.to_s))
|
|
170
|
+
return hit unless hit.equal?(WRITTEN_CANDIDATE)
|
|
171
|
+
|
|
172
|
+
Type::Combinator.untyped if lexical_constant_type(name, scope, caller_derived, nil)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# {.resolve_constant_type}'s unrooted ladder. `shadows` is the census's shadowing names for the
|
|
176
|
+
# reference, which the rungs above the last check their candidates against, or nil for the plain ladder.
|
|
177
|
+
def lexical_constant_type(name, scope, caller_derived, shadows)
|
|
156
178
|
# Issue #716 — a body whose `Module.nesting` was RECORDED EMPTY is definitively top level, and Ruby
|
|
157
179
|
# resolves its constants there no matter which namespace calls it. Steps 1 and 2 both derive from the
|
|
158
180
|
# caller and are both wrong for it, so it takes its own ladder.
|
|
159
|
-
return toplevel_first_constant_type(name, scope) if recorded_toplevel_nesting?(scope)
|
|
181
|
+
return toplevel_first_constant_type(name, scope, caller_derived, shadows) if recorded_toplevel_nesting?(scope)
|
|
160
182
|
|
|
161
183
|
# Step 1 — `Module.nesting`, innermost first. Each entry contributes only its OWN constants.
|
|
162
184
|
#
|
|
@@ -174,19 +196,20 @@ module Rigor
|
|
|
174
196
|
# beating the top-level whole-string answer is the point: `A::B` inside `P::Guard` with
|
|
175
197
|
# `P::A < P::Base` is `P::Base::B`, and step 3's `A::B` is a real but different class.
|
|
176
198
|
#
|
|
177
|
-
# Step 3 — the bare name (top level).
|
|
178
|
-
first_constant_hit(lexical_nesting_chain(scope), name, scope) ||
|
|
179
|
-
ancestor_constant_type(name, scope, enclosing_class_path(scope)) ||
|
|
180
|
-
constant_path_type(name, scope) ||
|
|
199
|
+
# Step 3 — the bare name (top level). It takes no `shadows`: nothing sits below it for a stop to replace.
|
|
200
|
+
first_constant_hit(lexical_nesting_chain(scope), name, scope, shadows) ||
|
|
201
|
+
ancestor_constant_type(name, scope, enclosing_class_path(scope), shadows) ||
|
|
202
|
+
constant_path_type(name, scope, shadows: shadows) ||
|
|
181
203
|
constant_type_at(name, scope)
|
|
182
204
|
end
|
|
205
|
+
private_class_method :lexical_constant_type
|
|
183
206
|
|
|
184
207
|
# The first candidate `<entry>::<name>` any source knows, walking `entries` in order, or nil. The one
|
|
185
208
|
# place a qualifying prefix is joined to a name, so every rung of the ladder consults its candidates
|
|
186
209
|
# identically.
|
|
187
|
-
def first_constant_hit(entries, name, scope)
|
|
210
|
+
def first_constant_hit(entries, name, scope, shadows)
|
|
188
211
|
entries.each do |entry|
|
|
189
|
-
hit = constant_type_at("#{entry}::#{name}", scope)
|
|
212
|
+
hit = constant_type_at("#{entry}::#{name}", scope, shadows)
|
|
190
213
|
return hit if hit
|
|
191
214
|
end
|
|
192
215
|
nil
|
|
@@ -194,10 +217,10 @@ module Rigor
|
|
|
194
217
|
private_class_method :first_constant_hit
|
|
195
218
|
|
|
196
219
|
# Step 2's rung on its own: nil when there is no enclosing class path to take ancestors of.
|
|
197
|
-
def ancestor_constant_type(name, scope, prefix)
|
|
220
|
+
def ancestor_constant_type(name, scope, prefix, shadows)
|
|
198
221
|
return nil if prefix.nil? || prefix.empty?
|
|
199
222
|
|
|
200
|
-
|
|
223
|
+
agreed_ancestor_hit(prefix, scope) { |entry| constant_type_at("#{entry}::#{name}", scope, shadows) }
|
|
201
224
|
end
|
|
202
225
|
private_class_method :ancestor_constant_type
|
|
203
226
|
|
|
@@ -222,21 +245,27 @@ module Rigor
|
|
|
222
245
|
#
|
|
223
246
|
# Issue #656's rung goes LAST here rather than second: for a top-level body Ruby's own first answer
|
|
224
247
|
# for `A::B` is the top level, and a whole-string hit there already means "`A` owns `B`". The
|
|
225
|
-
# segment-wise walk only has something to add once that misses.
|
|
226
|
-
|
|
227
|
-
|
|
248
|
+
# segment-wise walk only has something to add once that misses. Its head consults the caller's
|
|
249
|
+
# ancestors, so under `caller_derived: false` it resolves the head at the top level alone.
|
|
250
|
+
#
|
|
251
|
+
# Issue #1290 — the top level is this ladder's FIRST rung, so a top-level name the project writes stops it
|
|
252
|
+
# ({.constant_type_at}) before a caller's `Plug::TOP` can answer a read Ruby gives to the top-level `TOP`.
|
|
253
|
+
def toplevel_first_constant_type(name, scope, caller_derived, shadows)
|
|
254
|
+
constant_type_at(name, scope, shadows) ||
|
|
255
|
+
(caller_derived && caller_derived_constant_type(name, scope, shadows)) ||
|
|
256
|
+
constant_path_type(name, scope, caller_derived: caller_derived, shadows: shadows)
|
|
228
257
|
end
|
|
229
258
|
private_class_method :toplevel_first_constant_type
|
|
230
259
|
|
|
231
260
|
# The peel and its ancestors — {.resolve_constant_type}'s steps 1 and 2 as they answer for a scope with
|
|
232
261
|
# no recorded chain, factored out so the top-level ladder above can consult them BELOW the top level
|
|
233
262
|
# instead of above it.
|
|
234
|
-
def caller_derived_constant_type(name, scope)
|
|
263
|
+
def caller_derived_constant_type(name, scope, shadows)
|
|
235
264
|
prefix = enclosing_class_path(scope)
|
|
236
265
|
return nil if prefix.nil? || prefix.empty?
|
|
237
266
|
|
|
238
|
-
first_constant_hit(peeled_nesting(prefix), name, scope) ||
|
|
239
|
-
ancestor_constant_type(name, scope, prefix)
|
|
267
|
+
first_constant_hit(peeled_nesting(prefix), name, scope, shadows) ||
|
|
268
|
+
ancestor_constant_type(name, scope, prefix, shadows)
|
|
240
269
|
end
|
|
241
270
|
private_class_method :caller_derived_constant_type
|
|
242
271
|
|
|
@@ -244,7 +273,25 @@ module Rigor
|
|
|
244
273
|
# `Singleton[C]`), source-discovered classes, in-source value constants, then RBS-side
|
|
245
274
|
# constants. In-source values win over RBS constant decls because the user's source is
|
|
246
275
|
# authoritative for its own constants. Returns nil when no source knows `candidate`.
|
|
247
|
-
|
|
276
|
+
#
|
|
277
|
+
# Issue #1290 — `shadows`, passed on every rung that has a rung below it, is the last source: a candidate
|
|
278
|
+
# no other source types answers {WRITTEN_CANDIDATE} when `shadows` holds it, and {.resolve_constant_type}
|
|
279
|
+
# settles that stop. `shadows` is `Scope#shadowing_constant_names` for the reference, whose last segment
|
|
280
|
+
# every candidate shares. Ruby's lookup stops at a constant that exists, whatever its value, and the
|
|
281
|
+
# cross-file table publishes only a frozen scalar one file writes: another file's `App::LIMIT = { n: 1 }`
|
|
282
|
+
# was missed by every source, and the ladder moved on to a published top-level `LIMIT = 5`, typing `LIMIT`
|
|
283
|
+
# inside `module App` as `5` and reporting `call.undefined-method` on correct code. The value is one the
|
|
284
|
+
# analyzer does not carry, so the stop is gradual.
|
|
285
|
+
#
|
|
286
|
+
# Only an EXACT census name stops a candidate. The census keeps a path write as written
|
|
287
|
+
# ([#690](https://github.com/rigortype/rigor/issues/690)), so a suffix match would reach the as-written
|
|
288
|
+
# `Foo::BAR` from `M::Foo::BAR`, but would also stop `Admin::UsersController::X` on a top-level
|
|
289
|
+
# `UsersController::X`, losing the answer an ordinary Rails layout gets from the namespaced controller's
|
|
290
|
+
# superclass. A name written only through `||=` does not shadow, however many files memoize it: `X ||= v`
|
|
291
|
+
# resolves `X` through this same lookup, so wherever a lower rung answers, the memo finds that constant and
|
|
292
|
+
# never creates the name. The answer moves with the project's write set for the last segment, which the
|
|
293
|
+
# `constant:` edge {.resolve_constant_type} records once per reference already covers.
|
|
294
|
+
def constant_type_at(candidate, scope, shadows = nil)
|
|
248
295
|
env = scope.environment
|
|
249
296
|
|
|
250
297
|
singleton = env.singleton_for_name(candidate)
|
|
@@ -264,7 +311,7 @@ module Rigor
|
|
|
264
311
|
return in_source_value
|
|
265
312
|
end
|
|
266
313
|
|
|
267
|
-
env.constant_for_name(candidate)
|
|
314
|
+
env.constant_for_name(candidate) || (WRITTEN_CANDIDATE if shadows&.include?(candidate))
|
|
268
315
|
end
|
|
269
316
|
private_class_method :constant_type_at
|
|
270
317
|
|
|
@@ -275,92 +322,10 @@ module Rigor
|
|
|
275
322
|
# ({Analysis::Incremental.changed_constant_publications}). Gated by the caller on the recorder being
|
|
276
323
|
# active, so an ordinary run pays one integer read.
|
|
277
324
|
def record_constant_reference(name)
|
|
278
|
-
|
|
279
|
-
Analysis::DependencyRecorder.read_name(:constant, segment) if segment
|
|
325
|
+
Analysis::DependencyRecorder.read_last_segment(:constant, name)
|
|
280
326
|
end
|
|
281
327
|
private_class_method :record_constant_reference
|
|
282
328
|
|
|
283
|
-
# #354 — the project classes and modules whose own constants `class_name` inherits, in Ruby's
|
|
284
|
-
# ancestor order: included / prepended modules before the superclass (Ruby places mixins nearer),
|
|
285
|
-
# transitively, breadth-first. `class_name` itself is excluded — step 1 already covered it.
|
|
286
|
-
#
|
|
287
|
-
# Only PROJECT ancestors appear. `Scope#superclass_of` / `#includes_of` carry as-written names
|
|
288
|
-
# from the discovery pre-pass, and an as-written name that resolves to no discovered class or
|
|
289
|
-
# module is dropped — so a `class Foo < ActiveRecord::Base` contributes nothing and a constant
|
|
290
|
-
# owned by an RBS-known ancestor still resolves only if the bare name reaches it at step 3. That
|
|
291
|
-
# gap is deliberate for this slice: widening to the RBS ancestor graph is a separate question
|
|
292
|
-
# with its own FP surface.
|
|
293
|
-
#
|
|
294
|
-
# Memoised per run because step 2 runs on every constant reference whose lexical candidates all
|
|
295
|
-
# miss — which is the common case for a core-class reference (`String` inside `class Foo`). The
|
|
296
|
-
# bucket keys on the identity of the runner-seeded run-generation token (ADR-84 WD2), falling
|
|
297
|
-
# back to the per-file discovery table for runner-less scopes, so a re-run in one process (LSP,
|
|
298
|
-
# ADR-62 warm loop) cannot hit stale entries.
|
|
299
|
-
def ancestor_constant_scopes(class_name, scope)
|
|
300
|
-
# ADR-46: `superclass_of` / `includes_of` record a cross-file class dependency per consumer
|
|
301
|
-
# file, and the memo is run-scoped rather than file-scoped — a hit would skip the recording and
|
|
302
|
-
# under-record the edge for every later file. Recording runs are rare (incremental only), so
|
|
303
|
-
# they simply bypass the memo rather than complicate its key.
|
|
304
|
-
return compute_ancestor_constant_scopes(class_name, scope) if Analysis::DependencyRecorder.active?
|
|
305
|
-
|
|
306
|
-
generation = scope.run_generation || scope.discovered_superclasses
|
|
307
|
-
slot = Thread.current[ANCESTOR_SCOPES_KEY]
|
|
308
|
-
unless slot && slot[0].equal?(generation)
|
|
309
|
-
slot = [generation, {}]
|
|
310
|
-
Thread.current[ANCESTOR_SCOPES_KEY] = slot
|
|
311
|
-
end
|
|
312
|
-
bucket = slot[1]
|
|
313
|
-
bucket.fetch(class_name) { bucket[class_name] = compute_ancestor_constant_scopes(class_name, scope) }
|
|
314
|
-
end
|
|
315
|
-
private_class_method :ancestor_constant_scopes
|
|
316
|
-
|
|
317
|
-
def compute_ancestor_constant_scopes(class_name, scope)
|
|
318
|
-
queue = [class_name]
|
|
319
|
-
seen = { class_name => true }
|
|
320
|
-
out = []
|
|
321
|
-
until queue.empty?
|
|
322
|
-
current = queue.shift
|
|
323
|
-
# Mixins first, then the superclass — Ruby's ancestor order.
|
|
324
|
-
scope.includes_of(current).each do |raw|
|
|
325
|
-
resolved = resolve_ancestor_name(current, raw, scope)
|
|
326
|
-
next if resolved.nil? || seen[resolved]
|
|
327
|
-
|
|
328
|
-
seen[resolved] = true
|
|
329
|
-
out << resolved
|
|
330
|
-
queue << resolved
|
|
331
|
-
end
|
|
332
|
-
raw_super = scope.superclass_of(current)
|
|
333
|
-
next if raw_super.nil?
|
|
334
|
-
|
|
335
|
-
resolved_super = resolve_ancestor_name(current, raw_super, scope)
|
|
336
|
-
next if resolved_super.nil? || seen[resolved_super]
|
|
337
|
-
|
|
338
|
-
seen[resolved_super] = true
|
|
339
|
-
out << resolved_super
|
|
340
|
-
queue << resolved_super
|
|
341
|
-
end
|
|
342
|
-
out.freeze
|
|
343
|
-
end
|
|
344
|
-
private_class_method :compute_ancestor_constant_scopes
|
|
345
|
-
|
|
346
|
-
# Resolves an ancestor name AS WRITTEN (`"Base"`, or a qualified `"A::B"`) against the nesting in
|
|
347
|
-
# force where the subclass's header is written — `Scope#ancestor_name_candidates`, the single
|
|
348
|
-
# owner of that order, which `Scope#enqueue_ancestors` reads for method lookup and the
|
|
349
|
-
# override-visibility rule reads for its own walk. Returns nil when no candidate names a
|
|
350
|
-
# discovered project class or module.
|
|
351
|
-
def resolve_ancestor_name(subclass_qualified, raw, scope)
|
|
352
|
-
scope.ancestor_name_candidates(subclass_qualified, raw)
|
|
353
|
-
.find { |candidate| known_project_namespace?(candidate, scope) }
|
|
354
|
-
end
|
|
355
|
-
private_class_method :resolve_ancestor_name
|
|
356
|
-
|
|
357
|
-
def known_project_namespace?(name, scope)
|
|
358
|
-
scope.discovered_superclasses.key?(name) ||
|
|
359
|
-
scope.discovered_includes.key?(name) ||
|
|
360
|
-
scope.discovered_classes.key?(name)
|
|
361
|
-
end
|
|
362
|
-
private_class_method :known_project_namespace?
|
|
363
|
-
|
|
364
329
|
# Pulls the enclosing qualified class name out of `scope.self_type` when one is set.
|
|
365
330
|
# `Nominal[T]` and `Singleton[T]` both expose `class_name`. Returns nil at the top level.
|
|
366
331
|
def enclosing_class_path(scope)
|
|
@@ -447,7 +412,7 @@ module Rigor
|
|
|
447
412
|
nil
|
|
448
413
|
end
|
|
449
414
|
|
|
450
|
-
#
|
|
415
|
+
# The singleton-side twin of {#instance_definition}, nil under the same conditions.
|
|
451
416
|
def singleton_definition(class_name, scope: nil, environment: nil)
|
|
452
417
|
loader = rbs_loader_for(scope, environment)
|
|
453
418
|
return nil if loader.nil?
|
|
@@ -510,6 +475,7 @@ module Rigor
|
|
|
510
475
|
end
|
|
511
476
|
end
|
|
512
477
|
|
|
513
|
-
# Loaded last: the segment-wise path walk
|
|
514
|
-
# lookups, so the facade has to exist first.
|
|
478
|
+
# Loaded last: the ancestor walk and the segment-wise path walk reopen the module above and read its
|
|
479
|
+
# private candidate lookups, so the facade has to exist first.
|
|
480
|
+
require_relative "reflection/constant_ancestors"
|
|
515
481
|
require_relative "reflection/constant_path"
|