rigortype 0.4.5 → 0.4.7
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 +2 -2
- data/data/gem_overlay/activesupport/core_ext.rbs +16 -13
- data/data/vendored_gem_sigs/bundler/bundler.rbs +1 -1
- data/data/vendored_gem_sigs/rubygems/rubygems_extras.rbs +4 -3
- data/docs/handbook/01-getting-started.md +5 -2
- data/docs/handbook/11-sig-gen.md +61 -5
- data/docs/handbook/appendix-phpstan.md +4 -4
- data/docs/manual/02-cli-reference.md +192 -27
- data/docs/manual/03-configuration.md +38 -4
- data/docs/manual/04-diagnostics.md +1 -1
- data/docs/manual/06-baseline.md +6 -4
- data/docs/manual/09-editor-integration.md +13 -2
- data/docs/manual/10-mcp-server.md +47 -3
- data/docs/manual/12-caching.md +9 -1
- data/docs/manual/plugins/rigor-actionmailer.md +30 -0
- data/docs/manual/plugins/rigor-actionpack.md +49 -11
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +20 -1
- data/docs/manual/plugins/rigor-devise.md +15 -0
- data/docs/manual/plugins/rigor-rspec.md +2 -1
- data/lib/rigor/analysis/baseline.rb +24 -27
- data/lib/rigor/analysis/buffer_binding.rb +14 -0
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +5 -6
- data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +4 -4
- data/lib/rigor/analysis/check_rules/duplicate_hash_key_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/inferred_param_guard.rb +105 -12
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +143 -15
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +4 -1
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +5 -8
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +1 -1
- data/lib/rigor/analysis/check_rules/rbs_receiver_surface.rb +66 -3
- data/lib/rigor/analysis/check_rules/rebinding_block_callees/dispatch.rb +112 -0
- data/lib/rigor/analysis/check_rules/rebinding_block_callees.rb +394 -0
- data/lib/rigor/analysis/check_rules/return_in_ensure_collector.rb +1 -2
- data/lib/rigor/analysis/check_rules/ruby_deprecations.rb +7 -0
- data/lib/rigor/analysis/check_rules/rule_ids.rb +1 -1
- data/lib/rigor/analysis/check_rules/rule_walk.rb +9 -7
- data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +3 -4
- data/lib/rigor/analysis/check_rules/special_global_setters.rb +3 -3
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +53 -2
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +1 -1
- data/lib/rigor/analysis/check_rules.rb +217 -52
- data/lib/rigor/analysis/crash_signature.rb +2 -2
- data/lib/rigor/analysis/dependency_recorder.rb +15 -4
- data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +14 -3
- data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +1 -1
- data/lib/rigor/analysis/dependency_source_inference/index.rb +6 -8
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
- data/lib/rigor/analysis/edit_replay.rb +154 -0
- data/lib/rigor/analysis/fact_store.rb +3 -3
- data/lib/rigor/analysis/incremental.rb +37 -0
- data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +2 -2
- data/lib/rigor/analysis/incremental_run_slot.rb +2 -2
- data/lib/rigor/analysis/incremental_session.rb +202 -43
- data/lib/rigor/analysis/path_expansion.rb +41 -0
- data/lib/rigor/analysis/require_relative_closure.rb +100 -0
- data/lib/rigor/analysis/rule_catalog.rb +7 -3
- data/lib/rigor/analysis/run_disclosure_credit.rb +80 -0
- data/lib/rigor/analysis/run_disclosure_ledger.rb +155 -0
- data/lib/rigor/analysis/run_stats.rb +2 -2
- data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +8 -4
- data/lib/rigor/analysis/runner/declaration_position.rb +1 -1
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +204 -96
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +1 -1
- data/lib/rigor/analysis/runner/pool_coordinator.rb +157 -320
- data/lib/rigor/analysis/runner/project_pre_passes.rb +48 -6
- data/lib/rigor/analysis/runner/run_level_facts.rb +304 -0
- data/lib/rigor/analysis/runner/run_snapshots.rb +44 -54
- data/lib/rigor/analysis/runner/scan_environment.rb +51 -0
- data/lib/rigor/analysis/runner/worker_payload.rb +36 -0
- data/lib/rigor/analysis/runner.rb +233 -120
- data/lib/rigor/analysis/self_call_resolution_recorder.rb +1 -1
- data/lib/rigor/analysis/template_unit_positions.rb +2 -3
- data/lib/rigor/analysis/template_units.rb +9 -1
- data/lib/rigor/analysis/worker_session.rb +38 -33
- data/lib/rigor/bleeding_edge.rb +3 -6
- data/lib/rigor/builtins/imported_refinements.rb +6 -8
- data/lib/rigor/builtins/predefined_constant_refinements.rb +1 -1
- data/lib/rigor/builtins/regex_refinement.rb +4 -6
- data/lib/rigor/cache/descriptor.rb +6 -5
- data/lib/rigor/cache/incremental_snapshot.rb +60 -18
- data/lib/rigor/cache/rbs_cache_producer.rb +2 -2
- data/lib/rigor/cache/rbs_class_ancestor_table.rb +1 -1
- data/lib/rigor/cache/rbs_class_type_param_names.rb +2 -2
- data/lib/rigor/cache/rbs_constant_table.rb +1 -1
- data/lib/rigor/cache/rbs_descriptor.rb +54 -3
- data/lib/rigor/cache/rbs_environment.rb +4 -1
- data/lib/rigor/cache/rbs_environment_marshal_patch.rb +2 -2
- data/lib/rigor/cache/rbs_known_class_names.rb +1 -1
- data/lib/rigor/cache/store.rb +11 -10
- data/lib/rigor/ci_detector.rb +1 -1
- data/lib/rigor/cli/annotate_command.rb +24 -19
- data/lib/rigor/cli/baseline_command.rb +145 -55
- data/lib/rigor/cli/catalogue.rb +256 -0
- data/lib/rigor/cli/check_command.rb +188 -93
- data/lib/rigor/cli/check_runner_factory.rb +2 -2
- data/lib/rigor/cli/command.rb +15 -1
- data/lib/rigor/cli/coverage_command.rb +21 -8
- data/lib/rigor/cli/coverage_mutation.rb +5 -7
- data/lib/rigor/cli/coverage_renderer.rb +2 -1
- data/lib/rigor/cli/coverage_scan.rb +3 -5
- data/lib/rigor/cli/diff_command.rb +27 -21
- data/lib/rigor/cli/docs_command.rb +1 -2
- data/lib/rigor/cli/doctor_command.rb +12 -12
- data/lib/rigor/cli/effects_command.rb +50 -40
- data/lib/rigor/cli/effects_diff_renderer.rb +18 -17
- data/lib/rigor/cli/effects_explain_renderer.rb +13 -12
- data/lib/rigor/cli/effects_renderer.rb +2 -1
- data/lib/rigor/cli/effects_snapshot_command.rb +18 -17
- data/lib/rigor/cli/explain_command.rb +18 -8
- data/lib/rigor/cli/fused_protection_renderer.rb +2 -1
- data/lib/rigor/cli/json_document.rb +41 -0
- data/lib/rigor/cli/lens_command.rb +17 -13
- data/lib/rigor/cli/lsp_command.rb +250 -23
- data/lib/rigor/cli/mcp_command.rb +14 -8
- data/lib/rigor/cli/mutation_fork_scan.rb +1 -1
- data/lib/rigor/cli/mutation_protection_renderer.rb +3 -2
- data/lib/rigor/cli/options.rb +60 -4
- data/lib/rigor/cli/plugin_command.rb +93 -46
- data/lib/rigor/cli/plugins_command.rb +22 -18
- data/lib/rigor/cli/plugins_renderer.rb +34 -8
- data/lib/rigor/cli/protection_fork_scan.rb +2 -2
- data/lib/rigor/cli/protection_renderer.rb +2 -1
- data/lib/rigor/cli/show_bleedingedge_command.rb +23 -16
- data/lib/rigor/cli/sig_gen_command.rb +130 -34
- data/lib/rigor/cli/skill_command.rb +32 -3
- data/lib/rigor/cli/skill_deep_probe.rb +1 -1
- data/lib/rigor/cli/skill_describe.rb +1 -1
- data/lib/rigor/cli/trace_command.rb +14 -9
- data/lib/rigor/cli/triage_command.rb +10 -11
- data/lib/rigor/cli/triage_renderer.rb +2 -1
- data/lib/rigor/cli/type_of_command.rb +18 -12
- data/lib/rigor/cli/type_of_project_scope.rb +24 -0
- data/lib/rigor/cli/type_of_renderer.rb +4 -1
- data/lib/rigor/cli/type_scan_command.rb +14 -9
- data/lib/rigor/cli/type_scan_renderer.rb +2 -1
- data/lib/rigor/cli/unused_command.rb +27 -17
- data/lib/rigor/cli/upgrade_command.rb +5 -0
- data/lib/rigor/cli.rb +209 -54
- data/lib/rigor/config_audit.rb +17 -6
- data/lib/rigor/configuration/severity_profile.rb +5 -5
- data/lib/rigor/configuration.rb +86 -34
- data/lib/rigor/effects/definition_context.rb +0 -2
- data/lib/rigor/effects/envelope.rb +1 -1
- data/lib/rigor/effects/framework_units.rb +1 -1
- data/lib/rigor/effects/mutation_classifier.rb +4 -7
- data/lib/rigor/effects/propagator.rb +1 -1
- data/lib/rigor/effects/registry.rb +2 -2
- data/lib/rigor/effects/snapshot.rb +1 -1
- data/lib/rigor/effects/taint_cause.rb +0 -2
- data/lib/rigor/effects/unit_scan.rb +9 -13
- data/lib/rigor/environment/bundle_sig_discovery.rb +5 -9
- data/lib/rigor/environment/class_registry.rb +3 -3
- data/lib/rigor/environment/core_root.rb +77 -0
- data/lib/rigor/environment/default_libraries.rb +1 -1
- data/lib/rigor/environment/deferred_signature_plan.rb +283 -0
- data/lib/rigor/environment/gated_signature_guard.rb +1 -1
- data/lib/rigor/environment/gated_signature_plan.rb +5 -2
- data/lib/rigor/environment/lockfile_resolver.rb +28 -12
- data/lib/rigor/environment/member_consistency/comparator.rb +18 -1
- data/lib/rigor/environment/member_consistency.rb +56 -7
- data/lib/rigor/environment/missing_gem_constant_index.rb +3 -2
- data/lib/rigor/environment/project_path_gems.rb +124 -0
- data/lib/rigor/environment/rbs_hierarchy.rb +6 -15
- data/lib/rigor/environment/rbs_loader.rb +592 -70
- data/lib/rigor/environment/reflection.rb +7 -7
- data/lib/rigor/environment/required_features.rb +136 -32
- data/lib/rigor/environment/ruby_library_roots.rb +122 -0
- data/lib/rigor/environment/vendored_signature_plan.rb +153 -0
- data/lib/rigor/environment.rb +44 -11
- data/lib/rigor/flow_contribution/merger.rb +4 -4
- data/lib/rigor/inference/acceptance.rb +93 -32
- data/lib/rigor/inference/block_parameter_binder.rb +2 -3
- data/lib/rigor/inference/block_run_count.rb +178 -0
- data/lib/rigor/inference/budget_trace.rb +8 -2
- data/lib/rigor/inference/builtins/exception_catalog.rb +2 -2
- data/lib/rigor/inference/builtins/numeric_catalog.rb +2 -5
- data/lib/rigor/inference/builtins/random_catalog.rb +2 -2
- data/lib/rigor/inference/callee_mutation_chain.rb +126 -0
- data/lib/rigor/inference/callee_write_census.rb +815 -0
- data/lib/rigor/inference/construction_escape.rb +217 -0
- data/lib/rigor/inference/declaration_walk/traversal.rb +1 -1
- data/lib/rigor/inference/deep_erasure.rb +170 -0
- data/lib/rigor/inference/def_handle.rb +1 -1
- data/lib/rigor/inference/def_node_resolver.rb +1 -1
- data/lib/rigor/inference/def_return_typer.rb +204 -12
- data/lib/rigor/inference/definer_resolution.rb +21 -5
- data/lib/rigor/inference/definers_index.rb +106 -0
- data/lib/rigor/inference/direct_ivar_writes.rb +300 -0
- data/lib/rigor/inference/element_read_widening.rb +49 -3
- data/lib/rigor/inference/error_info.rb +17 -3
- data/lib/rigor/inference/expression_typer.rb +173 -57
- data/lib/rigor/inference/external_ancestor_resolution.rb +3 -4
- data/lib/rigor/inference/global_write_census.rb +110 -1
- data/lib/rigor/inference/global_writer_reach.rb +260 -0
- data/lib/rigor/inference/hkt_body.rb +1 -2
- data/lib/rigor/inference/hkt_body_parser.rb +3 -5
- data/lib/rigor/inference/hkt_reducer.rb +2 -2
- data/lib/rigor/inference/hkt_registry.rb +3 -5
- data/lib/rigor/inference/indexed_narrowing.rb +4 -7
- data/lib/rigor/inference/intervening_ivar_reset.rb +26 -4
- data/lib/rigor/inference/ivar_writer_census.rb +246 -0
- data/lib/rigor/inference/key_presence_guard.rb +2 -1
- data/lib/rigor/inference/loop_value_record.rb +57 -0
- data/lib/rigor/inference/match_rebinding/frame.rb +65 -0
- data/lib/rigor/inference/match_rebinding/yielding_match.rb +45 -0
- data/lib/rigor/inference/match_rebinding.rb +11 -1
- data/lib/rigor/inference/memo_audit.rb +55 -0
- data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/argument_distribution.rb +40 -0
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +113 -12
- data/lib/rigor/inference/method_dispatcher/contested_overloads.rb +89 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +7 -3
- data/lib/rigor/inference/method_dispatcher/no_match_fallback.rb +54 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +39 -27
- data/lib/rigor/inference/method_dispatcher/random_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +203 -17
- data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/self_substitute.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/set_folding.rb +59 -24
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +83 -20
- data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +0 -1
- data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +50 -17
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -5
- data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +4 -6
- data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher.rb +109 -29
- data/lib/rigor/inference/module_function_state/spellings.rb +64 -0
- data/lib/rigor/inference/module_function_state.rb +23 -1
- data/lib/rigor/inference/multi_target_binder.rb +1 -1
- data/lib/rigor/inference/mutation_rejoin.rb +240 -4
- data/lib/rigor/inference/mutation_widening.rb +162 -29
- data/lib/rigor/inference/narrowing.rb +113 -38
- data/lib/rigor/inference/object_mixins.rb +13 -1
- data/lib/rigor/inference/optimistic_origin.rb +1 -1
- data/lib/rigor/inference/out_buffer_mutation.rb +72 -0
- data/lib/rigor/inference/parameter_inference_collector.rb +5 -6
- data/lib/rigor/inference/pre_eval_constants.rb +1 -1
- data/lib/rigor/inference/project_method_ownership.rb +6 -3
- data/lib/rigor/inference/project_seed_tables.rb +2 -1
- data/lib/rigor/inference/project_yielder.rb +122 -0
- data/lib/rigor/inference/receiver_alias.rb +20 -0
- data/lib/rigor/inference/refined_dispatch/constructed_class.rb +3 -1
- data/lib/rigor/inference/refined_dispatch/own_method.rb +2 -1
- data/lib/rigor/inference/remover_holder_scan.rb +233 -0
- data/lib/rigor/inference/remover_narrowing.rb +224 -0
- data/lib/rigor/inference/rewrite_mutation.rb +53 -2
- data/lib/rigor/inference/scope_indexer/certainty.rb +9 -1
- data/lib/rigor/inference/scope_indexer/constant_ivar_value.rb +93 -0
- data/lib/rigor/inference/scope_indexer/declared_ivar_types.rb +64 -0
- data/lib/rigor/inference/scope_indexer/declared_param_writes.rb +205 -0
- data/lib/rigor/inference/scope_indexer/derived_param_value.rb +112 -0
- data/lib/rigor/inference/scope_indexer/empty_seed.rb +99 -0
- data/lib/rigor/inference/scope_indexer/ivar_contributions.rb +135 -0
- data/lib/rigor/inference/scope_indexer/unseen_ivar_writers.rb +133 -0
- data/lib/rigor/inference/scope_indexer.rb +614 -146
- data/lib/rigor/inference/self_call_ivar_writes.rb +101 -17
- data/lib/rigor/inference/set_mutation.rb +189 -0
- data/lib/rigor/inference/singleton_hook_decline.rb +1 -2
- data/lib/rigor/inference/statement_evaluator.rb +3036 -278
- data/lib/rigor/inference/struct_fold_safety.rb +4 -6
- data/lib/rigor/inference/synthetic_method_index.rb +23 -0
- data/lib/rigor/inference/synthetic_method_scanner/project_members.rb +130 -0
- data/lib/rigor/inference/synthetic_method_scanner.rb +73 -14
- data/lib/rigor/inference/toplevel_def_census.rb +59 -0
- data/lib/rigor/inference/unknown_store_widening.rb +103 -4
- data/lib/rigor/inference/unthreaded_rebinds.rb +2 -3
- data/lib/rigor/inference/void_tail_summary.rb +2 -1
- data/lib/rigor/language_server/buffer_table.rb +9 -3
- data/lib/rigor/language_server/completion_provider.rb +26 -20
- data/lib/rigor/language_server/config_warning_announcer.rb +28 -0
- data/lib/rigor/language_server/diagnostic_publisher.rb +28 -9
- data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
- data/lib/rigor/language_server/folding_range_provider.rb +1 -2
- data/lib/rigor/language_server/hover_provider.rb +1 -7
- data/lib/rigor/language_server/hover_renderer.rb +6 -8
- data/lib/rigor/language_server/project_context.rb +98 -4
- data/lib/rigor/language_server/publish_batcher.rb +3 -4
- data/lib/rigor/language_server/selection_range_provider.rb +2 -4
- data/lib/rigor/language_server/server.rb +12 -6
- data/lib/rigor/language_server/signature_help_provider.rb +4 -4
- data/lib/rigor/lens/plugins.rb +1 -1
- data/lib/rigor/mcp/server.rb +82 -3
- data/lib/rigor/mcp.rb +1 -1
- data/lib/rigor/plugin/access_denied_error.rb +1 -2
- data/lib/rigor/plugin/base.rb +26 -11
- data/lib/rigor/plugin/bundled_catalog.rb +1 -12
- data/lib/rigor/plugin/io_boundary.rb +1 -1
- data/lib/rigor/plugin/loader.rb +25 -8
- data/lib/rigor/plugin/macro/heredoc_template.rb +7 -8
- data/lib/rigor/plugin/macro/trait_registry.rb +6 -9
- data/lib/rigor/plugin/manifest.rb +38 -16
- data/lib/rigor/plugin/registry.rb +41 -3
- data/lib/rigor/plugin/services.rb +2 -3
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -0
- data/lib/rigor/plugin/trust_policy.rb +2 -2
- data/lib/rigor/plugin/type_node_resolver.rb +2 -4
- data/lib/rigor/plugin.rb +6 -8
- data/lib/rigor/plugin_gap_advisory.rb +5 -1
- data/lib/rigor/project_environment.rb +16 -2
- data/lib/rigor/protection/analysis_guard.rb +1 -1
- data/lib/rigor/protection/discovery_seed.rb +96 -2
- data/lib/rigor/protection/mutator.rb +1 -1
- data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
- data/lib/rigor/rbs_extended/hkt_directives.rb +6 -10
- data/lib/rigor/rbs_extended/reporter.rb +27 -3
- data/lib/rigor/rbs_extended.rb +2 -3
- data/lib/rigor/reflection/constant_ancestors.rb +5 -3
- data/lib/rigor/rooted_glob.rb +25 -2
- data/lib/rigor/run_scoped_slots.rb +38 -0
- data/lib/rigor/runtime/jit.rb +1 -1
- data/lib/rigor/scope/discovery_index.rb +19 -6
- data/lib/rigor/scope/resolution_chain.rb +3 -1
- data/lib/rigor/scope.rb +379 -36
- data/lib/rigor/sig_gen/classification.rb +4 -0
- data/lib/rigor/sig_gen/effect_annotation.rb +3 -3
- data/lib/rigor/sig_gen/generator.rb +668 -84
- data/lib/rigor/sig_gen/generic_header_scan.rb +189 -0
- data/lib/rigor/sig_gen/inline_declarations.rb +2 -2
- data/lib/rigor/sig_gen/layout_index.rb +3 -3
- data/lib/rigor/sig_gen/method_candidate.rb +23 -4
- data/lib/rigor/sig_gen/observation_collector.rb +7 -6
- data/lib/rigor/sig_gen/observed_call.rb +1 -1
- data/lib/rigor/sig_gen/path_mapper.rb +6 -0
- data/lib/rigor/sig_gen/rbs_validity.rb +1 -1
- data/lib/rigor/sig_gen/renderer.rb +21 -12
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +15 -2
- data/lib/rigor/sig_gen/type_elaborator.rb +21 -5
- data/lib/rigor/sig_gen/type_name_qualification.rb +69 -0
- data/lib/rigor/sig_gen/write_reporter.rb +63 -14
- data/lib/rigor/sig_gen/write_result.rb +23 -12
- data/lib/rigor/sig_gen/writer.rb +217 -37
- data/lib/rigor/type/acceptance_router.rb +2 -2
- data/lib/rigor/type/accepts_result.rb +1 -1
- data/lib/rigor/type/app.rb +4 -6
- data/lib/rigor/type/combinator.rb +13 -16
- data/lib/rigor/type/constant.rb +48 -7
- data/lib/rigor/type/hash_shape.rb +26 -40
- data/lib/rigor/type/struct_instance.rb +3 -2
- data/lib/rigor/type/union.rb +1 -1
- data/lib/rigor/type_node/identifier.rb +1 -2
- data/lib/rigor/type_node/resolver_chain.rb +1 -1
- data/lib/rigor/type_node/string_literal.rb +1 -2
- data/lib/rigor/type_node/symbol_literal.rb +1 -2
- data/lib/rigor/type_node/union.rb +3 -6
- data/lib/rigor/value_semantics.rb +1 -10
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +2 -2
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +2 -3
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +1 -1
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +89 -70
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +4 -2
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +25 -4
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +1 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -5
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +0 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +2 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +1 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +79 -19
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +6 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/association_roots.rb +3 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +2 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +21 -31
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +10 -16
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +2 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +0 -1
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +5 -4
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +3 -4
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +1 -1
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +7 -12
- data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +1 -1
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +1 -1
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/symbolize_keys.rb +102 -0
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +19 -6
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +26 -13
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_index.rb +3 -3
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +5 -3
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +1 -3
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +6 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +5 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +7 -6
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/params_shape.rb +2 -3
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +5 -8
- data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +0 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +1 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +10 -18
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/analyzer.rb +0 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/discoverer.rb +0 -2
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +4 -5
- data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +0 -2
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +6 -7
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +2 -4
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +2 -5
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +2 -2
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +6 -6
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +2 -1
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +3 -8
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +2 -3
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +5 -8
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +1 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +2 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +1 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +4 -11
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +1 -1
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +2 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +102 -11
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +2 -2
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +3 -4
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +6 -8
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +5 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +4 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +6 -7
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +1 -1
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +2 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +17 -21
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +2 -3
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_discoverer.rb +3 -2
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_index.rb +4 -4
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer.rb +1 -1
- data/sig/rigor/analysis/baseline.rbs +0 -2
- data/sig/rigor/analysis/fact_store.rbs +1 -0
- data/sig/rigor/analysis/reachability/scan_cache.rbs +1 -1
- data/sig/rigor/cli/diff_command.rbs +1 -1
- data/sig/rigor/cli/explain_command.rbs +1 -1
- data/sig/rigor/effects/file_collection.rbs +5 -6
- data/sig/rigor/effects/registry.rbs +8 -6
- data/sig/rigor/effects/summary.rbs +6 -5
- data/sig/rigor/environment.rbs +5 -3
- data/sig/rigor/inference/optimistic_origin.rbs +11 -0
- data/sig/rigor/inference.rbs +10 -1
- data/sig/rigor/plugin/additional_initializer.rbs +0 -5
- data/sig/rigor/plugin/base.rbs +1 -0
- data/sig/rigor/plugin/effect_ancestry.rbs +6 -4
- data/sig/rigor/plugin/effect_attribution.rbs +25 -10
- data/sig/rigor/plugin/effect_edge.rbs +12 -5
- data/sig/rigor/plugin/effect_entry_points.rbs +8 -3
- data/sig/rigor/plugin/io_boundary.rbs +6 -5
- data/sig/rigor/plugin/manifest.rbs +16 -18
- data/sig/rigor/plugin/protocol_contract.rbs +6 -9
- data/sig/rigor/plugin/registry.rbs +1 -1
- data/sig/rigor/scope.rbs +51 -50
- data/sig/rigor/type.rbs +0 -6
- data/skills/rigor-plugin-author/SKILL.md +4 -4
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +5 -5
- data/skills/rigor-plugin-review/SKILL.md +3 -3
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +12 -1
- metadata +55 -3
|
@@ -18,7 +18,7 @@ module Rigor
|
|
|
18
18
|
# recompute" lesson applied to self-calls.
|
|
19
19
|
#
|
|
20
20
|
# ADR-24 slice 4 (`call.self-undefined-method`) consumes the recorded misses behind a confidently-closed-class
|
|
21
|
-
# gate (see `CheckRules`
|
|
21
|
+
# gate (see `CheckRules`). The rule ships `:off` by default — {active?} is false on a normal run, so
|
|
22
22
|
# the instrumented choke-point pays a single integer read and records nothing. Recording is purely
|
|
23
23
|
# observational; it never changes a diagnostic.
|
|
24
24
|
#
|
|
@@ -173,9 +173,8 @@ module Rigor
|
|
|
173
173
|
# copies one tag body once, and the second `@author` is the same copy seen from the other end, not a
|
|
174
174
|
# second reading. Only a node OUTSIDE the winning run's own compiled span counts, which is what keeps
|
|
175
175
|
# the busy lines of a real view answerable while the cross-tag repeat (`<%= v %> <%= v.to_s %>`, or
|
|
176
|
-
# `<%= v %><%= "v" %>` probed at the STRING's `v`) still declines
|
|
177
|
-
# span would answer instead
|
|
178
|
-
# (see the PR), and the follow-up this rule is deliberately conservative ahead of.
|
|
176
|
+
# `<%= v %><%= "v" %>` probed at the STRING's `v`) still declines. That family is what a plugin-exported
|
|
177
|
+
# tag span would answer instead, and it is the follow-up this rule is deliberately conservative ahead of.
|
|
179
178
|
#
|
|
180
179
|
# `spill` is the nearest NON-BLANK compiled line above this template line's own, where a hoisted
|
|
181
180
|
# leading-text literal lives. Only a string literal the run does NOT contain counts there. A code
|
|
@@ -189,6 +189,15 @@ module Rigor
|
|
|
189
189
|
@entries.keys.sort
|
|
190
190
|
end
|
|
191
191
|
|
|
192
|
+
# Issue #2233 — whether a plugin claims `path` by one of its `template_globs:`, in any spelling a caller holds it
|
|
193
|
+
# (absolute, `./`-prefixed, relative). A claimed template is analysed as a unit, never as a plain `.rb` file, so
|
|
194
|
+
# the runner keeps the buffer's logical path out of the `.rb` targets, so it is not analysed twice.
|
|
195
|
+
def claims?(path)
|
|
196
|
+
return false if @claimed_globs.empty?
|
|
197
|
+
|
|
198
|
+
TemplateUnitPaths.claims?(@claimed_globs, TemplateUnitPaths.relative(path, @root))
|
|
199
|
+
end
|
|
200
|
+
|
|
192
201
|
def [](path)
|
|
193
202
|
entry_for(path)
|
|
194
203
|
end
|
|
@@ -293,7 +302,6 @@ module Rigor
|
|
|
293
302
|
[entry.locals.keys.map(&:to_sym)]
|
|
294
303
|
end
|
|
295
304
|
|
|
296
|
-
# The `view:<logical_name>` effect-unit key for a path, or nil.
|
|
297
305
|
# The file whose bytes a unit's path was READ from: the editor's buffer when one is bound to it, the
|
|
298
306
|
# project file otherwise. Read by the run's dependency descriptor, so it digests what the run read.
|
|
299
307
|
def physical_path(path, buffer)
|
|
@@ -20,10 +20,12 @@ require_relative "../inference/method_dispatcher/file_folding"
|
|
|
20
20
|
require_relative "check_rules"
|
|
21
21
|
require_relative "crash_signature"
|
|
22
22
|
require_relative "dependency_recorder"
|
|
23
|
+
require_relative "run_disclosure_credit"
|
|
23
24
|
require_relative "dependency_source_inference"
|
|
24
25
|
require_relative "diagnostic"
|
|
25
26
|
require_relative "erb_template_detector"
|
|
26
27
|
require_relative "template_units"
|
|
28
|
+
require_relative "runner/run_level_facts"
|
|
27
29
|
|
|
28
30
|
module Rigor
|
|
29
31
|
module Analysis
|
|
@@ -38,8 +40,8 @@ module Rigor
|
|
|
38
40
|
# - `configuration` — Phase 2a ({Rigor::Configuration} is `Ractor.shareable?`).
|
|
39
41
|
# - `cache_store` — the fork backend passes the parent runner's pre-built Store (`cache_store:
|
|
40
42
|
# @cache_store` in PoolCoordinator); workers share it rather than building their own at `cache_root`.
|
|
41
|
-
# - `plugin_blueprints` — Phase 3a (`
|
|
42
|
-
# - `explain` —
|
|
43
|
+
# - `plugin_blueprints` — Phase 3a (a list of `Plugin::Blueprint` is `Ractor.shareable?`).
|
|
44
|
+
# - `explain` — a flag.
|
|
43
45
|
# - `synthetic_method_index` / `project_patched_methods` / `project_scope_seed` — optional (default `nil`
|
|
44
46
|
# / `{}`). NOT `Ractor.shareable?` (the seed tables carry Prism def nodes), so the Ractor pool path
|
|
45
47
|
# leaves them unset; the fork backend (ADR-15 Amendment), which builds the session pre-fork on the
|
|
@@ -108,7 +110,7 @@ module Rigor
|
|
|
108
110
|
# above: a worker and the parent agree without a flag to keep in sync.
|
|
109
111
|
@effect_attribution = Effects::Attribution.build(configuration.effects_attribution)
|
|
110
112
|
@file_effects = {}
|
|
111
|
-
# ADR-32 WD4 — full project file list (frozen
|
|
113
|
+
# ADR-32 WD4 — full project file list (frozen) for env-build-time invocation of any
|
|
112
114
|
# loaded plugin's `source_rbs_synthesizer` callable.
|
|
113
115
|
@source_files = source_files
|
|
114
116
|
# #392 — the run's template units, synthesised on the PARENT before the fork and inherited here as
|
|
@@ -161,7 +163,7 @@ module Rigor
|
|
|
161
163
|
end
|
|
162
164
|
|
|
163
165
|
# Equivalent of {Rigor::Analysis::Runner#analyze_file} + `plugin_emitted_diagnostics` +
|
|
164
|
-
# `explain_diagnostics`. Returns a flat
|
|
166
|
+
# `explain_diagnostics`. Returns a flat list of diagnostics for the file. Severity profile re-stamping
|
|
165
167
|
# is intentionally NOT applied — that is a per-run aggregate concern handled by the caller. When
|
|
166
168
|
# `record_dependencies:` was set, wraps the analysis in a {DependencyRecorder} window (ADR-46) so the
|
|
167
169
|
# worker captures the file's cross-file reads for {#drain_dependencies}; the recorder's own disabled
|
|
@@ -171,12 +173,17 @@ module Rigor
|
|
|
171
173
|
|
|
172
174
|
diagnostics = nil
|
|
173
175
|
reads = []
|
|
174
|
-
record =
|
|
175
|
-
|
|
176
|
+
record = nil
|
|
177
|
+
# Issue #2020 — and the run-scoped rows it registered, as `Runner#analyze_file` keeps them.
|
|
178
|
+
disclosures = RunDisclosureCredit.collect do
|
|
179
|
+
record = Plugin::IoBoundary.attributing(reads) do
|
|
180
|
+
DependencyRecorder.record_for(path) { diagnostics = analyze_with_effects(path) }
|
|
181
|
+
end
|
|
176
182
|
end
|
|
177
183
|
@file_dependencies[path] = record
|
|
178
184
|
# Issue #1553 — the plugin reads this file's analysis made, as `Runner#analyze_file` keeps them.
|
|
179
185
|
(@analysis_reads ||= {})[path] = reads unless reads.empty?
|
|
186
|
+
(@analysis_disclosures ||= {})[path] = disclosures unless disclosures.empty?
|
|
180
187
|
diagnostics
|
|
181
188
|
end
|
|
182
189
|
|
|
@@ -265,7 +272,7 @@ module Rigor
|
|
|
265
272
|
# definition and never enters the failing build; a diagnostic wired off the parent's loader would
|
|
266
273
|
# appear at `--workers=0` and vanish at `--workers=N`, which is the same "reports less depending on
|
|
267
274
|
# how you ran it" defect the diagnostic exists to end. Draining it out of the workers is what makes
|
|
268
|
-
# the two paths say the same thing. The payload is
|
|
275
|
+
# the two paths say the same thing. The payload is a list of plain tuples —
|
|
269
276
|
# Marshal-clean for the fork backend and shareable for the Ractor one.
|
|
270
277
|
#
|
|
271
278
|
# Issue #784 — `hkt_scan_failure` rides the same channel for the same reason: the PARENT's own
|
|
@@ -278,33 +285,25 @@ module Rigor
|
|
|
278
285
|
# project whose `sig/` produced a single such event killed each worker HERE — after its files were
|
|
279
286
|
# analysed — and the run degraded to in-process re-analysis with a `pool-degraded` row. All three
|
|
280
287
|
# streams now carry `(path, line, column)` primitives.
|
|
288
|
+
#
|
|
289
|
+
# ADR-116 WD3 (#1195) — both halves are declared rather than listed here: each reporter snapshots its
|
|
290
|
+
# own streams ({Runner::RunLevelFacts::REPORTERS}), and the `:analysis` facts come from
|
|
291
|
+
# {Runner::RunLevelFacts.drain}, the same read the coordinator makes of an environment it analysed on.
|
|
292
|
+
# The facts are read first: their HKT demand (#784, made once per worker so a worker whose share of
|
|
293
|
+
# files demanded nothing still reports the run's outcome) is what fills the hkt-directive stream (#785).
|
|
294
|
+
# On a worker that analysed a file the demand is a memoised read; the fork backend never hands a worker
|
|
295
|
+
# an empty slice, so no idle worker pays the env load.
|
|
281
296
|
def drain_reporters
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
@
|
|
289
|
-
|
|
290
|
-
rbs_extended: {
|
|
291
|
-
unresolved_payloads: @rbs_extended_reporter.unresolved_payloads,
|
|
292
|
-
lossy_projections: @rbs_extended_reporter.lossy_projections,
|
|
293
|
-
# Issue #785 — the HKT directive stream rides the same channel for the same reason
|
|
294
|
-
# `hkt_scan_failure` does: the directives are read by the registry scan, and under the pool the
|
|
295
|
-
# PARENT never demands that scan, so a diagnostic wired off the parent's reporter would appear
|
|
296
|
-
# at `--workers=0` and vanish at `--workers=N`. The demand above is what fills this.
|
|
297
|
-
hkt_directive_errors: @rbs_extended_reporter.hkt_directive_errors,
|
|
298
|
-
# ADR-109 WD3 — the deprecated-form stream rides the same channel: the payload is read where
|
|
299
|
-
# the annotated method is dispatched, which under the pool is only ever inside a worker.
|
|
300
|
-
deprecated_forms: @rbs_extended_reporter.deprecated_forms
|
|
301
|
-
},
|
|
302
|
-
boundary_cross: @boundary_cross_reporter.entries,
|
|
303
|
-
source_rbs_synthesis: @source_rbs_synthesis_reporter.entries,
|
|
304
|
-
definition_build_failures: @environment&.rbs_loader&.definition_build_failures || [],
|
|
305
|
-
hkt_scan_failure: @environment&.hkt_scan_failure
|
|
306
|
-
}
|
|
297
|
+
facts = Runner::RunLevelFacts.drain(@environment)
|
|
298
|
+
Runner::RunLevelFacts.snapshot_reporters(reporters).merge(facts)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# The per-worker reporter accumulators, by {Runner::RunLevelFacts::REPORTERS} key.
|
|
302
|
+
def reporters
|
|
303
|
+
{ rbs_extended: @rbs_extended_reporter, boundary_cross: @boundary_cross_reporter,
|
|
304
|
+
source_rbs_synthesis: @source_rbs_synthesis_reporter }
|
|
307
305
|
end
|
|
306
|
+
private :reporters
|
|
308
307
|
|
|
309
308
|
# ADR-46 — the per-file {DependencyRecorder::Record}s captured by this session's `#analyze` calls (empty
|
|
310
309
|
# unless `record_dependencies:` was set). Marshal-clean (Data of frozen Sets / String Hashes), so the
|
|
@@ -320,6 +319,12 @@ module Rigor
|
|
|
320
319
|
@analysis_reads || {}
|
|
321
320
|
end
|
|
322
321
|
|
|
322
|
+
# Issue #2020 — the run-scoped rows each file's analysis registered, `{path => [record]}`; see
|
|
323
|
+
# {RunDisclosureCredit}. Marshal-clean like {#drain_run_disclosures}.
|
|
324
|
+
def drain_analysis_disclosures
|
|
325
|
+
@analysis_disclosures || {}
|
|
326
|
+
end
|
|
327
|
+
|
|
323
328
|
# ADR-103 WD12 — the per-file {Effects::FileCollection}s this session collected (empty unless the
|
|
324
329
|
# configuration carries an `effects:` block). Marshal-clean by construction — frozen Hashes of
|
|
325
330
|
# Strings, `LabelSet`s of frozen Arrays, and `Data` edges — so the fork pool ships them back to the
|
|
@@ -445,7 +450,7 @@ module Rigor
|
|
|
445
450
|
return nil if gem_name.nil? || gem_name.empty?
|
|
446
451
|
|
|
447
452
|
spec = Gem.loaded_specs[gem_name]
|
|
448
|
-
spec&.full_gem_path
|
|
453
|
+
spec&.full_gem_path
|
|
449
454
|
rescue StandardError
|
|
450
455
|
nil
|
|
451
456
|
end
|
data/lib/rigor/bleeding_edge.rb
CHANGED
|
@@ -9,11 +9,9 @@ module Rigor
|
|
|
9
9
|
# *today's* rules are) and is versioned with the gem, NOT a user-supplied file: the
|
|
10
10
|
# inspectable counterpart to PHPStan's `bleedingEdge` include.
|
|
11
11
|
#
|
|
12
|
-
# The
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# {FEATURES} entry with no engine plumbing — as the first one,
|
|
16
|
-
# `reject-unparseable-signatures`, does.
|
|
12
|
+
# The surface is wired end-to-end (`bleeding_edge:` config, `rigor show-bleedingedge`, the
|
|
13
|
+
# severity-composition hook in {Configuration::SeverityProfile.resolve}), so a *severity*
|
|
14
|
+
# discipline is a single {FEATURES} entry with no engine plumbing.
|
|
17
15
|
#
|
|
18
16
|
# A queued change whose effect is not a severity move — a measurement, an algorithm, or a
|
|
19
17
|
# default that changes while every rule keeps its severity — is a `:behaviour` feature
|
|
@@ -40,7 +38,6 @@ module Rigor
|
|
|
40
38
|
# {Configuration#bleeding_edge_active?}.
|
|
41
39
|
KINDS = %i[severity behaviour].freeze
|
|
42
40
|
|
|
43
|
-
# The severity map a `:behaviour` feature carries: none.
|
|
44
41
|
NO_SEVERITY_OVERRIDES = {}.freeze
|
|
45
42
|
|
|
46
43
|
# One queued change.
|
|
@@ -113,9 +113,8 @@ module Rigor
|
|
|
113
113
|
},
|
|
114
114
|
# ADR-13 § "Canonical type-function additions" — five shape-projection type functions
|
|
115
115
|
# that the `rigor-typescript-utility-types` plugin (and any other plugin that ships a
|
|
116
|
-
# shape-projection vocabulary) maps onto.
|
|
117
|
-
#
|
|
118
|
-
# in slice 5).
|
|
116
|
+
# shape-projection vocabulary) maps onto. Non-shape inputs return the input unchanged;
|
|
117
|
+
# the Resolver records `dynamic.shape.lossy-projection` for them.
|
|
119
118
|
"pick_of" => lambda { |args|
|
|
120
119
|
return nil unless args.size == 2
|
|
121
120
|
|
|
@@ -148,7 +147,7 @@ module Rigor
|
|
|
148
147
|
# `Class[range]` — a numeric class head bounded by a Ruby range literal (ADR-109). The
|
|
149
148
|
# builder receives the `Range` value and returns the carrier, or `nil` when the range is
|
|
150
149
|
# empty or its endpoints are not literals of the head class; `nil` surfaces as the ordinary
|
|
151
|
-
# unresolved-payload diagnostic. `Float`
|
|
150
|
+
# unresolved-payload diagnostic. `Float` builds a `FloatRange` carrier.
|
|
152
151
|
RANGE_HEAD_BUILDERS = {
|
|
153
152
|
"Integer" => lambda { |range|
|
|
154
153
|
lo = range.begin
|
|
@@ -186,8 +185,7 @@ module Rigor
|
|
|
186
185
|
# `Array<Integer>` and returns a `Rigor::Type` (or `nil`). Bounds are signed integer
|
|
187
186
|
# literals. A reversed pair (`min` > `max`) is declined as `nil` like every other shape
|
|
188
187
|
# mismatch, so the caller surfaces `dynamic.rbs-extended.unresolved` at the annotation;
|
|
189
|
-
# `Type::IntegerRange`
|
|
190
|
-
# `internal analyzer error` that abandoned the whole Ruby file.
|
|
188
|
+
# `Type::IntegerRange` would raise on it instead, which must not escape the analyzer.
|
|
191
189
|
PARAMETERISED_INT_BUILDERS = {
|
|
192
190
|
"int" => lambda { |bounds|
|
|
193
191
|
return nil unless bounds.size == 2
|
|
@@ -276,14 +274,14 @@ module Rigor
|
|
|
276
274
|
# grammar:
|
|
277
275
|
#
|
|
278
276
|
# type := simple_name | parametric
|
|
279
|
-
# simple_name := /[a-z][a-z0-
|
|
277
|
+
# simple_name := /[a-z][a-z0-9_-]*/
|
|
280
278
|
# parametric := simple_name '[' type_arg_list ']'
|
|
281
279
|
# | simple_name '<' int_bound_list '>'
|
|
282
280
|
# type_arg_list := type_arg (',' type_arg)*
|
|
283
281
|
# type_arg := range_literal | type | class_name
|
|
284
282
|
# class_name := /[A-Z][A-Za-z0-9_]*(?:::[A-Z][A-Za-z0-9_]*)*/
|
|
285
283
|
# range_literal := endpoint? ('..' | '...') endpoint? (at least one side written)
|
|
286
|
-
# endpoint := signed_int | 'nil'
|
|
284
|
+
# endpoint := signed_int | float_literal | 'nil' | 'Float::INFINITY' | 'Float::MAX'
|
|
287
285
|
# int_bound_list := signed_int (',' signed_int)*
|
|
288
286
|
# signed_int := /-?\d+/
|
|
289
287
|
#
|
|
@@ -62,7 +62,7 @@ module Rigor
|
|
|
62
62
|
# `RBS::VERSION` while Rigor checks itself, rubygems and Bundler internals while it checks
|
|
63
63
|
# CRuby's `lib/` — and that is worse than no answer: identical source would type differently
|
|
64
64
|
# depending on how the analyzer was installed. Removing an ad hoc `Object.const_get` from an
|
|
65
|
-
# analysis path is the same move ADR-4
|
|
65
|
+
# analysis path is the same move ADR-4 already made for predicate narrowing.
|
|
66
66
|
#
|
|
67
67
|
# This module is consulted by `Environment#constant_for_name` BEFORE the RBS
|
|
68
68
|
# constant-type table (widest types) but AFTER in-source constant writes (the user's own
|
|
@@ -8,13 +8,11 @@ module Rigor
|
|
|
8
8
|
# carriers Rigor already ships (`decimal-int-string`, `hex-int-string`,
|
|
9
9
|
# `octal-int-string`, `lowercase-string`, `uppercase-string`, `numeric-string`). See
|
|
10
10
|
# `docs/type-specification/imported-built-in-types.md` for the registry the refinements
|
|
11
|
-
# come from
|
|
12
|
-
# scope of this recogniser.
|
|
11
|
+
# come from.
|
|
13
12
|
#
|
|
14
|
-
# The
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
# whenever the named-capture body matches one of the rows in {RULES}.
|
|
13
|
+
# The consumer is `Inference::Narrowing.analyse_match_write`: given `if /(?<year>\d+)/ =~ str;
|
|
14
|
+
# year; end`, `year` narrows to `decimal-int-string` when the named-capture body matches a row
|
|
15
|
+
# in {RULES}, and stays plain `String` otherwise.
|
|
18
16
|
#
|
|
19
17
|
# Recognised body shapes (each row admits the `+` quantifier and the bounded `{n}` /
|
|
20
18
|
# `{n,m}` forms with `n >= 1`):
|
|
@@ -10,7 +10,8 @@ module Rigor
|
|
|
10
10
|
module Cache
|
|
11
11
|
# Cache invalidation descriptor — the typed-slot schema fixed by
|
|
12
12
|
# [`docs/design/20260505-cache-slice-taxonomy.md`](../../../docs/design/20260505-cache-slice-taxonomy.md).
|
|
13
|
-
#
|
|
13
|
+
# Value object, fully immutable after construction. Filesystem reads happen only in the `FileEntry.stat`,
|
|
14
|
+
# `FileEntry.kind` and `GlobEntry.compute` builders and in {#fresh?}. The storage layer
|
|
14
15
|
# ([`Rigor::Cache::Store`](store.rb), v0.0.8 slice 2) consumes descriptors but does not extend them.
|
|
15
16
|
#
|
|
16
17
|
# The descriptor has six slots (`files`, `gems`, `plugins`, `configs`, `dependencies`, `globs`); every slot is
|
|
@@ -462,10 +463,10 @@ module Rigor
|
|
|
462
463
|
|
|
463
464
|
# ADR-45 — re-validates this descriptor's recorded {FileEntry}s against the current filesystem. Used by
|
|
464
465
|
# the record-and-validate run-result cache: a value cached alongside its dependency descriptor is fresh
|
|
465
|
-
# iff every recorded file still matches. Only `files` are checked — non-file inputs (config / gems /
|
|
466
|
+
# iff every recorded file still matches. Only `files` and `globs` are checked — non-file inputs (config / gems /
|
|
466
467
|
# version) belong in the cache *key*, not the validated dependency set — so a descriptor carrying any
|
|
467
468
|
# non-file slot is never considered fresh (it was built wrong for this use). ADR-60 WD3 adds `globs`
|
|
468
|
-
# alongside `files` as a re-validatable slot: a {GlobEntry} is fresh when re-globbing
|
|
469
|
+
# alongside `files` as a re-validatable slot: a {GlobEntry} is fresh when re-globbing
|
|
469
470
|
# reproduces its recorded value. ADR-45 WD1 (#577): an absence row ({FileEntry.absent}) is fresh
|
|
470
471
|
# while its path is still missing — the negative half of the dependency set.
|
|
471
472
|
def fresh?
|
|
@@ -581,8 +582,8 @@ module Rigor
|
|
|
581
582
|
false
|
|
582
583
|
end
|
|
583
584
|
|
|
584
|
-
# ADR-60 WD3 / ADR-87 WD2 —
|
|
585
|
-
#
|
|
585
|
+
# ADR-60 WD3 / ADR-87 WD2 — recomputes the entry's signature over the live tree and compares it. Any
|
|
586
|
+
# failure reads as stale (recompute), never a crash.
|
|
586
587
|
def glob_entry_fresh?(entry)
|
|
587
588
|
GlobEntry.fresh?(entry)
|
|
588
589
|
end
|
|
@@ -8,6 +8,7 @@ require_relative "engine_source"
|
|
|
8
8
|
require_relative "store"
|
|
9
9
|
require_relative "../analysis/shadow_harness"
|
|
10
10
|
require_relative "../analysis/run_cache_key"
|
|
11
|
+
require_relative "../analysis/runner/run_level_facts"
|
|
11
12
|
require_relative "../environment"
|
|
12
13
|
require_relative "../analysis/path_expansion"
|
|
13
14
|
require_relative "../rooted_glob"
|
|
@@ -182,20 +183,39 @@ module Rigor
|
|
|
182
183
|
# 41: issue #1583 — the payload gains `discovery_digests`, the packed digest of each file a run over path
|
|
183
184
|
# arguments discovered without analysing, which a recheck compares to re-baseline when one moved. A pre-41
|
|
184
185
|
# blob carries none; the gate rejects it and the next run is cold.
|
|
185
|
-
|
|
186
|
+
# 42: issue #2184 — a `deferred_ranges` row for a `def` inside a block now carries the method's name, and a
|
|
187
|
+
# literal-named `define_method` / `define_singleton_method` call adds a row. A pre-42 bundle carries neither,
|
|
188
|
+
# so a warm run would report a top-level block call that a cold run declines.
|
|
189
|
+
# 43: issue #2020 — the payload gains `plugin_disclosures`, the run-scoped plugin rows each analysed file's
|
|
190
|
+
# last analysis registered, which a recheck replays for the files it serves. A pre-43 blob carries none, so
|
|
191
|
+
# its rechecks would drop every such row; the gate rejects it and the next run is cold.
|
|
192
|
+
# 44: PR #2286 review M1 — the payload gains `synthetic_surface_digest`, the ADR-16 synthetic-method index's
|
|
193
|
+
# {Rigor::Inference::SyntheticMethodIndex#surface_digest} at the run the cache was built under, which a recheck
|
|
194
|
+
# compares to re-baseline when a class-body DSL edit moved it. A pre-44 blob carries none; the gate rejects it
|
|
195
|
+
# and the next run is cold.
|
|
196
|
+
# 45: issue #1154 — each seed bundle's `global_write_census` also records the ivar writers the declared-parameter
|
|
197
|
+
# credit reads (`[:ivar_set, name]`, `[:ivar_set_class, class]`, `[:own_write, class, name, path]`), which a
|
|
198
|
+
# pre-45 bundle carries none of, so a warm run would credit an ivar write a cold run declines.
|
|
199
|
+
# 46: issue #2314 — each seed bundle's `global_write_census` also records the global writers
|
|
200
|
+
# (`[:global_writer, name, method]`) the statement walk reads past a call; a pre-46 bundle carries none, so a
|
|
201
|
+
# warm run would keep a global's binding a cold run forgets.
|
|
202
|
+
# 47: issues #2079 / #2170 — each seed bundle's `global_write_census` also records each instance-side ivar
|
|
203
|
+
# write's coarse value (`[:own_write_type, class, name, value, path]`), which the class-ivar census joins across
|
|
204
|
+
# files and along the chain; a pre-47 bundle carries none, so a warm run would keep a seed a cold run widens.
|
|
205
|
+
SCHEMA = 47
|
|
186
206
|
|
|
187
207
|
# The persisted per-file state.
|
|
188
208
|
# `cache` maps an analyzed file to its diagnostics.
|
|
189
|
-
# `sources` maps a consumer to the
|
|
209
|
+
# `sources` maps a consumer to the source files it read from.
|
|
190
210
|
# `digests` maps a file to its content digest at analysis time.
|
|
191
211
|
# `analyzed` is the ordered analyzed-file list.
|
|
192
212
|
# ADR-46 slice 4:
|
|
193
|
-
# `symbol_sources` maps a consumer to { source_path →
|
|
194
|
-
# `ancestry_sources` maps a consumer to
|
|
213
|
+
# `symbol_sources` maps a consumer to { source_path → the "ClassName#method" names it read }.
|
|
214
|
+
# `ancestry_sources` maps a consumer to the source paths it read for class ancestry.
|
|
195
215
|
# `symbol_fingerprints` maps a path to { "ClassName#method" => sha256_hex }.
|
|
196
216
|
# ADR-46 slice 3:
|
|
197
|
-
# `missing` maps a consumer to
|
|
198
|
-
# `class_decls` maps a path to
|
|
217
|
+
# `missing` maps a consumer to the "kind:name" keys it looked up and missed.
|
|
218
|
+
# `class_decls` maps a path to the qualified class names it declares.
|
|
199
219
|
# Issue #644:
|
|
200
220
|
# `constant_decls` maps a path to that file's constant PUBLICATION CENSUS,
|
|
201
221
|
# `{qualified name => [literal] | :unpublishable}`. The descriptor is what the recheck diffs: a name's
|
|
@@ -244,26 +264,36 @@ module Rigor
|
|
|
244
264
|
# `effect_collections` (nil when collection was off). A plugin stamps its attributions and edges into a file's
|
|
245
265
|
# collection, and `effects_identity` is plugin-blind (it is compared before any plugin loads), so the session
|
|
246
266
|
# compares this one after the recheck has loaded them.
|
|
267
|
+
# Issue #2020 — `plugin_disclosures` is {Analysis::RunDisclosureLedger#to_h}: `files`, each analysed file's
|
|
268
|
+
# run-scoped plugin rows ({Plugin::Base#disclose_once} / {Plugin::Base#emit_once}) from its last analysis, which a
|
|
269
|
+
# recheck replays for the files it serves, and `reads`, the boundary rows per `[plugin id, key]` that make one
|
|
270
|
+
# stale.
|
|
247
271
|
Payload = Data.define(:cache, :sources, :digests, :analyzed,
|
|
248
272
|
:symbol_sources, :ancestry_sources, :symbol_fingerprints,
|
|
249
273
|
:missing, :class_decls, :constant_decls, :seed_bundles, :plugin_fact_digest,
|
|
250
274
|
:return_summaries, :param_table,
|
|
251
275
|
:effect_collections, :effects_identity, :run_level_rows,
|
|
252
|
-
:effect_plugin_digest, :plugin_reads, :discovery_digests
|
|
276
|
+
:effect_plugin_digest, :plugin_reads, :discovery_digests, :plugin_disclosures,
|
|
277
|
+
:synthetic_surface_digest) do
|
|
253
278
|
# `effect_plugin_digest` defaults to nil so a payload built without it (an older caller, a spec fixture)
|
|
254
279
|
# reads as "unknown", which the session treats as moved. `plugin_reads` defaults to no reads, and
|
|
255
|
-
# `discovery_digests` to no discovery-only files.
|
|
256
|
-
|
|
280
|
+
# `discovery_digests` to no discovery-only files, and `plugin_disclosures` (#2020) to no replayed rows.
|
|
281
|
+
# `synthetic_surface_digest` defaults to nil, the empty index's digest: a run that builds a non-empty one
|
|
282
|
+
# reads it as moved.
|
|
283
|
+
def initialize(effect_plugin_digest: nil, plugin_reads: {}, discovery_digests: {}, plugin_disclosures: {},
|
|
284
|
+
synthetic_surface_digest: nil, **rest)
|
|
257
285
|
super
|
|
258
286
|
end
|
|
259
287
|
end
|
|
260
288
|
|
|
261
|
-
# Issues #796 / #794 — the
|
|
262
|
-
#
|
|
263
|
-
#
|
|
264
|
-
#
|
|
265
|
-
#
|
|
266
|
-
|
|
289
|
+
# Issues #796 / #794 — the run-level rows the snapshot carries: one member per run-level fact declared
|
|
290
|
+
# `replay` ({Analysis::Runner::RunLevelFacts}, ADR-116 WD3). Today that is `definition_build_failures`,
|
|
291
|
+
# the reported per-class detail list ({Environment::RbsLoader#definition_build_failures}), and
|
|
292
|
+
# `hkt_scan_failure`, the `[error_class, first_line, frame, stage]` tuple
|
|
293
|
+
# ({Rigor::Environment#hkt_scan_failure}), nil when the scan succeeded — which is why the presence of
|
|
294
|
+
# this object, not the tuple, is what says a replay is available. Declaring another fact `replay`
|
|
295
|
+
# changes this shape, so it bumps {SCHEMA}.
|
|
296
|
+
RunLevelRows = Data.define(*Analysis::Runner::RunLevelFacts.replayable_names)
|
|
267
297
|
|
|
268
298
|
# The global fingerprint that gates a snapshot load: a digest of the inputs whose change requires a full
|
|
269
299
|
# rebuild — the engine version + schema, the engine's own SOURCE when the version does not pin it, the
|
|
@@ -303,6 +333,7 @@ module Rigor
|
|
|
303
333
|
"sig:#{digest_signature_paths(project_sig_roots(configuration))}",
|
|
304
334
|
"pre_eval:#{digest_pre_eval(configuration.pre_eval)}"
|
|
305
335
|
]
|
|
336
|
+
parts.concat(core_root_parts(configuration))
|
|
306
337
|
parts.concat(dependency_source_parts(configuration))
|
|
307
338
|
identity = EngineSource.process_identity
|
|
308
339
|
parts << "engine-source:#{identity}" if identity
|
|
@@ -326,6 +357,15 @@ module Rigor
|
|
|
326
357
|
nil
|
|
327
358
|
end
|
|
328
359
|
|
|
360
|
+
# Issue #2517 — a selected core is read like the project's own `sig/`, so an edit in place to one of its files
|
|
361
|
+
# must drop the snapshot (and the language server's session, which keys on this fingerprint). No part for the
|
|
362
|
+
# default core, so every other project's fingerprint is as it was.
|
|
363
|
+
def self.core_root_parts(configuration)
|
|
364
|
+
core_root = configuration.core_root
|
|
365
|
+
core_root.nil? ? [] : ["core:#{digest_signature_paths([core_root])}"]
|
|
366
|
+
end
|
|
367
|
+
private_class_method :core_root_parts
|
|
368
|
+
|
|
329
369
|
def self.required_features(configuration, roots)
|
|
330
370
|
files = Analysis::PathExpansion.ruby_files(roots, configuration.exclude_patterns,
|
|
331
371
|
base: configuration.exclude_base)
|
|
@@ -465,7 +505,9 @@ module Rigor
|
|
|
465
505
|
run_level_rows: data[:run_level_rows],
|
|
466
506
|
effect_plugin_digest: data[:effect_plugin_digest],
|
|
467
507
|
plugin_reads: data[:plugin_reads] || {},
|
|
468
|
-
|
|
508
|
+
plugin_disclosures: data.fetch(:plugin_disclosures, {}),
|
|
509
|
+
discovery_digests: data.fetch(:discovery_digests, {}),
|
|
510
|
+
synthetic_surface_digest: data[:synthetic_surface_digest]
|
|
469
511
|
)
|
|
470
512
|
end
|
|
471
513
|
private :payload_from
|
|
@@ -492,8 +534,8 @@ module Rigor
|
|
|
492
534
|
effects_identity: payload.effects_identity,
|
|
493
535
|
run_level_rows: payload.run_level_rows,
|
|
494
536
|
effect_plugin_digest: payload.effect_plugin_digest,
|
|
495
|
-
plugin_reads: payload.plugin_reads,
|
|
496
|
-
discovery_digests: payload.discovery_digests
|
|
537
|
+
plugin_reads: payload.plugin_reads, plugin_disclosures: payload.plugin_disclosures,
|
|
538
|
+
discovery_digests: payload.discovery_digests, synthetic_surface_digest: payload.synthetic_surface_digest
|
|
497
539
|
)
|
|
498
540
|
# #1507 — every `--incremental` run that analysed anything rewrites this whole blob, so its deflate is
|
|
499
541
|
# on the edit path; see {Store::DEFLATE_LEVEL}.
|
|
@@ -6,8 +6,8 @@ module Rigor
|
|
|
6
6
|
module Cache
|
|
7
7
|
# Base for the RBS-derived cache producers.
|
|
8
8
|
#
|
|
9
|
-
# Every producer (`RbsKnownClassNames`, `RbsConstantTable`, `RbsEnvironment`, the ancestor / type-param
|
|
10
|
-
#
|
|
9
|
+
# Every producer (`RbsKnownClassNames`, `RbsConstantTable`, `RbsEnvironment`, the ancestor / type-param
|
|
10
|
+
# tables, …) repeated the identical `fetch` wiring: build the RBS descriptor, then
|
|
11
11
|
# `store.fetch_or_compute` under the producer's id, yielding to the producer's `compute`. Only the
|
|
12
12
|
# `PRODUCER_ID` constant and the `compute(loader)` body actually differ between producers.
|
|
13
13
|
#
|
|
@@ -6,7 +6,7 @@ require_relative "rbs_cache_producer"
|
|
|
6
6
|
module Rigor
|
|
7
7
|
module Cache
|
|
8
8
|
# Cache producer that materialises the RBS-declared ancestor chain of every loaded class / module into a
|
|
9
|
-
# Marshal-clean
|
|
9
|
+
# Marshal-clean table. Ancestor names are top-level-stripped (e.g. `"Integer"` not
|
|
10
10
|
# `"::Integer"`) to match `Environment::RbsHierarchy#normalize_name`.
|
|
11
11
|
#
|
|
12
12
|
# The hierarchy is the substrate behind every `class_ordering` query, which is itself a hot path on the
|
|
@@ -6,8 +6,8 @@ require_relative "rbs_cache_producer"
|
|
|
6
6
|
module Rigor
|
|
7
7
|
module Cache
|
|
8
8
|
# Cache producer that materialises every loaded class's RBS-declared type-parameter names as a
|
|
9
|
-
# Marshal-clean
|
|
10
|
-
# `[:Elem]`, `"Hash"` → `[:K, :V]`).
|
|
9
|
+
# Marshal-clean table keyed by top-level-stripped class name (e.g. `"Array"` →
|
|
10
|
+
# `[:Elem]`, `"Hash"` → `[:K, :V]`).
|
|
11
11
|
#
|
|
12
12
|
# The dispatcher reads type-parameter names every time it builds a substitution map from a receiver's
|
|
13
13
|
# `type_args` into a method's return type — it is one of the hottest reflection lookups during analysis.
|
|
@@ -6,7 +6,7 @@ require_relative "rbs_cache_producer"
|
|
|
6
6
|
module Rigor
|
|
7
7
|
module Cache
|
|
8
8
|
# Cache producer that materialises every RBS-declared constant to its translated `Rigor::Type` form and
|
|
9
|
-
# stores the result as a
|
|
9
|
+
# stores the result as a table keyed by canonical constant name. This is the v0.0.8
|
|
10
10
|
# first cached producer per ADR-6 § 7; it caches a post-translation artefact so the cache value is
|
|
11
11
|
# `Marshal`-clean (RBS-native objects carry `RBS::Location`, which lacks `_dump_data`).
|
|
12
12
|
#
|
|
@@ -77,9 +77,57 @@ module Rigor
|
|
|
77
77
|
# reconstructs {.config_entries} without loading a plugin, so an entry there that it cannot rebuild
|
|
78
78
|
# would turn the warm fast lane into a permanent miss on every project that enables a bundled plugin.
|
|
79
79
|
def self.env_only_config_entries(loader)
|
|
80
|
-
[deferred_signature_paths_entry(loader)].compact
|
|
80
|
+
[deferred_signature_paths_entry(loader), project_signature_paths_entry(loader), core_root_entry(loader)].compact
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
+
# Issue #2517 — which directory the env loaded core from. The selected core's files are digested by
|
|
84
|
+
# {.file_entries} too, so this row is the identity of the choice and those rows its contents: switching
|
|
85
|
+
# between two roots with byte-identical files still re-keys. Absent for the default core, whose identity
|
|
86
|
+
# is the `rbs` gem row, so every project without the setting keeps its key.
|
|
87
|
+
def self.core_root_entry(loader)
|
|
88
|
+
core_root = selected_core_root(loader)
|
|
89
|
+
return nil if core_root.nil?
|
|
90
|
+
|
|
91
|
+
Descriptor::ConfigEntry.new(key: "rbs.core_root", value_hash: Digest::SHA256.hexdigest(core_root.to_s))
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private_class_method :core_root_entry
|
|
95
|
+
|
|
96
|
+
# The loader's issue #2517 core root as a Pathname, or nil for the default core.
|
|
97
|
+
def self.selected_core_root(loader)
|
|
98
|
+
core_root = loader.respond_to?(:core_root) ? loader.core_root : nil
|
|
99
|
+
core_root.nil? ? nil : Pathname(core_root)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
private_class_method :selected_core_root
|
|
103
|
+
|
|
104
|
+
# {.selected_core_root} as the signature roots it adds: none for the default core.
|
|
105
|
+
def self.core_root_dirs(loader)
|
|
106
|
+
core_root = selected_core_root(loader)
|
|
107
|
+
core_root.nil? ? [] : [core_root]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
private_class_method :core_root_dirs
|
|
111
|
+
|
|
112
|
+
# Issue #2422 — which of the loader's `signature_paths:` are the project's own changes the env built from
|
|
113
|
+
# byte-identical files: a bundled plugin's method composes with another source's as an overload, but stands
|
|
114
|
+
# down to the project's own. Only read when a plugin defers signatures, so a project without one keeps its
|
|
115
|
+
# key.
|
|
116
|
+
def self.project_signature_paths_entry(loader)
|
|
117
|
+
return nil unless loader.respond_to?(:project_signature_paths) && loader.respond_to?(:deferred_signature_paths)
|
|
118
|
+
return nil if Array(loader.deferred_signature_paths).empty?
|
|
119
|
+
|
|
120
|
+
own = Array(loader.project_signature_paths).map(&:to_s).sort
|
|
121
|
+
return nil if own.empty?
|
|
122
|
+
|
|
123
|
+
Descriptor::ConfigEntry.new(
|
|
124
|
+
key: "rbs.project_signature_paths",
|
|
125
|
+
value_hash: Digest::SHA256.hexdigest(own.join("\n"))
|
|
126
|
+
)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
private_class_method :project_signature_paths_entry
|
|
130
|
+
|
|
83
131
|
def self.deferred_signature_paths_entry(loader)
|
|
84
132
|
return nil unless loader.respond_to?(:deferred_signature_paths)
|
|
85
133
|
|
|
@@ -104,7 +152,9 @@ module Rigor
|
|
|
104
152
|
# value must be deterministic; `:stat` (ADR-87 WD1) for the validation-only run-dependency descriptor
|
|
105
153
|
# ({RunDescriptor#files}), where the stat tier short-circuits the SHA-256 on an unmoved file.
|
|
106
154
|
def self.file_entries(loader, comparator: :digest)
|
|
107
|
-
|
|
155
|
+
# Issue #2517 — a selected core is project input like `signature_paths:`, not the engine-versioned `rbs`
|
|
156
|
+
# gem tree, so an edit in place must move the key.
|
|
157
|
+
roots = core_root_dirs(loader) + loader.signature_paths +
|
|
108
158
|
Rigor::Environment::RbsLoader.vendored_gem_sig_paths +
|
|
109
159
|
Rigor::Environment::RbsLoader.core_overlay_sig_paths +
|
|
110
160
|
Rigor::Environment::RbsLoader.capability_role_sig_paths
|
|
@@ -149,7 +199,8 @@ module Rigor
|
|
|
149
199
|
def self.glob_entries(loader)
|
|
150
200
|
# Deduplicated by path: a root reachable twice (an explicit `signature_paths:` entry that is also a
|
|
151
201
|
# bundled plugin's `sig/`, #610) would otherwise contribute two rows whose stat signatures race.
|
|
152
|
-
|
|
202
|
+
# Issue #2517 — and the selected core's root, where a file appearing is as much a new input.
|
|
203
|
+
(core_root_dirs(loader) + loader.signature_paths).uniq(&:to_s).filter_map do |root|
|
|
153
204
|
next unless root.directory?
|
|
154
205
|
|
|
155
206
|
Descriptor::GlobEntry.compute(root: root.to_s, pattern: File.join("**", "*.rbs"), mode: :names)
|
|
@@ -33,7 +33,10 @@ module Rigor
|
|
|
33
33
|
signature_paths: loader.signature_paths,
|
|
34
34
|
virtual_rbs: loader.respond_to?(:virtual_rbs) ? loader.virtual_rbs : [],
|
|
35
35
|
deferred_signature_paths:
|
|
36
|
-
loader.respond_to?(:deferred_signature_paths) ? loader.deferred_signature_paths : []
|
|
36
|
+
loader.respond_to?(:deferred_signature_paths) ? loader.deferred_signature_paths : [],
|
|
37
|
+
project_signature_paths:
|
|
38
|
+
loader.respond_to?(:project_signature_paths) ? loader.project_signature_paths : [],
|
|
39
|
+
core_root: loader.respond_to?(:core_root) ? loader.core_root : nil
|
|
37
40
|
)
|
|
38
41
|
end
|
|
39
42
|
|
|
@@ -53,8 +53,8 @@ require_relative "annotation_location"
|
|
|
53
53
|
# differently, and only the latter reaches `marshal_load`), so without the bump a stale blob would keep
|
|
54
54
|
# reporting the moved position indefinitely.
|
|
55
55
|
#
|
|
56
|
-
# Idempotent:
|
|
57
|
-
# rbs that adds Marshal hooks itself) is a no-op.
|
|
56
|
+
# Idempotent: each hook is defined only when `method_defined?` reports it missing, so requiring this file twice
|
|
57
|
+
# (or against an upstream rbs that adds Marshal hooks itself) is a no-op.
|
|
58
58
|
#
|
|
59
59
|
# `RBS::TypeName` / `RBS::Namespace` carry a second, subtler Marshal hazard, introduced by rbs 4.1's
|
|
60
60
|
# flyweight interning (ruby/rbs#2957): both memoise their `#hash` into an `@hash` ivar, and that value is
|