rigortype 0.4.6 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -2
- data/data/core_overlay/bigdecimal.rbs +33 -0
- data/data/core_overlay/resolv.rbs +30 -0
- data/data/gem_overlay/activesupport/core_ext.rbs +45 -13
- data/data/gem_overlay/addressable/addressable.rbs +40 -0
- 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 +6 -3
- data/docs/handbook/11-sig-gen.md +85 -3
- data/docs/handbook/appendix-phpstan.md +4 -4
- data/docs/install.md +20 -0
- data/docs/manual/01-installation.md +67 -26
- data/docs/manual/02-cli-reference.md +455 -113
- data/docs/manual/03-configuration.md +76 -5
- data/docs/manual/04-diagnostics.md +5 -4
- data/docs/manual/06-baseline.md +6 -4
- data/docs/manual/08-skills.md +11 -0
- data/docs/manual/09-editor-integration.md +21 -2
- data/docs/manual/10-mcp-server.md +38 -2
- data/docs/manual/12-caching.md +4 -3
- data/docs/manual/14-rails-quickstart.md +1 -1
- data/docs/manual/19-effect-labels.md +3 -4
- data/docs/manual/plugins/rigor-actionpack.md +32 -15
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +23 -1
- data/docs/manual/plugins/rigor-sorbet.md +17 -3
- data/lib/rigor/analysis/baseline.rb +24 -27
- data/lib/rigor/analysis/check_rules/always_raises_shield.rb +147 -0
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +5 -6
- data/lib/rigor/analysis/check_rules/call_facts.rb +58 -0
- data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +12 -4
- data/lib/rigor/analysis/check_rules/duplicate_hash_key_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/inferred_param_guard.rb +85 -13
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +16 -4
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +6 -1
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +5 -8
- data/lib/rigor/analysis/check_rules/plugin_api_surface.rb +195 -0
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +41 -12
- data/lib/rigor/analysis/check_rules/rbs_receiver_surface.rb +27 -1
- data/lib/rigor/analysis/check_rules/rebinding_block_callees.rb +3 -3
- data/lib/rigor/analysis/check_rules/replaced_singleton_defs.rb +96 -0
- data/lib/rigor/analysis/check_rules/return_in_ensure_collector.rb +1 -2
- data/lib/rigor/analysis/check_rules/rule_ids.rb +9 -2
- 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 +2 -2
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules.rb +720 -141
- data/lib/rigor/analysis/crash_signature.rb +45 -3
- data/lib/rigor/analysis/dependency_recorder.rb +237 -80
- 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 +93 -6
- data/lib/rigor/analysis/fact_store.rb +3 -3
- data/lib/rigor/analysis/incremental.rb +11 -1
- data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +4 -3
- data/lib/rigor/analysis/incremental_run_slot.rb +2 -2
- data/lib/rigor/analysis/incremental_session.rb +306 -53
- data/lib/rigor/analysis/reachability/plugin_roots.rb +6 -3
- data/lib/rigor/analysis/rule_catalog.rb +39 -3
- data/lib/rigor/analysis/run_cache_key.rb +27 -3
- data/lib/rigor/analysis/run_disclosure_credit.rb +26 -6
- data/lib/rigor/analysis/run_stats.rb +2 -2
- data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +6 -2
- data/lib/rigor/analysis/runner/declaration_position.rb +8 -8
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +264 -112
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +4 -9
- data/lib/rigor/analysis/runner/pool_coordinator.rb +173 -328
- data/lib/rigor/analysis/runner/project_pre_passes.rb +4 -37
- 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/worker_payload.rb +36 -0
- data/lib/rigor/analysis/runner.rb +298 -109
- data/lib/rigor/analysis/self_call_resolution_recorder.rb +62 -23
- 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 +65 -71
- data/lib/rigor/bleeding_edge.rb +22 -10
- 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/file_digest.rb +39 -31
- data/lib/rigor/cache/incremental_snapshot.rb +95 -17
- 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 +90 -4
- data/lib/rigor/cache/rbs_environment.rb +8 -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 +160 -57
- data/lib/rigor/cli/catalogue.rb +256 -0
- data/lib/rigor/cli/check_command.rb +112 -104
- 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 +25 -20
- 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 +26 -18
- 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 +29 -10
- data/lib/rigor/cli/lsp_command.rb +250 -23
- data/lib/rigor/cli/mcp_command.rb +12 -7
- 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 +40 -1
- data/lib/rigor/cli/plugin_command.rb +93 -46
- data/lib/rigor/cli/plugins_command.rb +17 -18
- data/lib/rigor/cli/plugins_renderer.rb +10 -6
- 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 +21 -15
- data/lib/rigor/cli/sig_gen_command.rb +92 -27
- 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 +2 -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 +16 -11
- data/lib/rigor/cli/type_of_project_scope.rb +1 -4
- 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 +214 -56
- data/lib/rigor/config_audit.rb +33 -19
- data/lib/rigor/configuration/severity_profile.rb +14 -5
- data/lib/rigor/configuration.rb +104 -35
- data/lib/rigor/effects/collector.rb +53 -21
- 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 +64 -33
- data/lib/rigor/environment/class_registry.rb +3 -3
- data/lib/rigor/environment/constant_type_cache_holder.rb +5 -0
- data/lib/rigor/environment/core_root.rb +77 -0
- data/lib/rigor/environment/default_libraries.rb +18 -1
- data/lib/rigor/environment/deferred_signature_plan.rb +381 -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/hkt_registry_holder.rb +6 -0
- 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_collection_discovery.rb +123 -8
- data/lib/rigor/environment/rbs_coverage_report.rb +12 -11
- data/lib/rigor/environment/rbs_hierarchy.rb +12 -15
- data/lib/rigor/environment/rbs_loader.rb +772 -110
- data/lib/rigor/environment/reflection.rb +7 -7
- data/lib/rigor/environment/required_features.rb +0 -3
- data/lib/rigor/environment/ruby_library_roots.rb +1 -1
- data/lib/rigor/environment/vendored_signature_plan.rb +153 -0
- data/lib/rigor/environment.rb +169 -42
- data/lib/rigor/flow_contribution/merger.rb +4 -4
- data/lib/rigor/inference/acceptance.rb +136 -40
- data/lib/rigor/inference/alias_mutation_floor/foreign_locals.rb +117 -0
- data/lib/rigor/inference/alias_mutation_floor/memos.rb +85 -0
- data/lib/rigor/inference/alias_mutation_floor/reach.rb +119 -0
- data/lib/rigor/inference/alias_mutation_floor/site_collector.rb +252 -0
- data/lib/rigor/inference/alias_mutation_floor.rb +339 -0
- data/lib/rigor/inference/anonymous_meta_class.rb +18 -0
- data/lib/rigor/inference/block_auto_splat.rb +1 -1
- data/lib/rigor/inference/block_parameter_binder.rb +2 -3
- data/lib/rigor/inference/block_run_count.rb +185 -0
- data/lib/rigor/inference/budget_trace.rb +8 -2
- data/lib/rigor/inference/builtins/array_catalog.rb +2 -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 +88 -77
- data/lib/rigor/inference/callee_write_census.rb +815 -0
- data/lib/rigor/inference/captured_locals.rb +2 -0
- data/lib/rigor/inference/census_foreign_block.rb +354 -0
- data/lib/rigor/inference/clause_widening.rb +1 -1
- data/lib/rigor/inference/closure_escape_analyzer.rb +11 -4
- data/lib/rigor/inference/construction_escape.rb +258 -0
- data/lib/rigor/inference/declaration_walk/traversal.rb +1 -1
- data/lib/rigor/inference/declaration_walk.rb +4 -0
- data/lib/rigor/inference/deep_erasure.rb +39 -7
- data/lib/rigor/inference/def_handle.rb +1 -1
- data/lib/rigor/inference/def_node_resolver.rb +33 -15
- data/lib/rigor/inference/def_return_typer.rb +47 -5
- data/lib/rigor/inference/definer_resolution.rb +19 -9
- data/lib/rigor/inference/definers_index.rb +162 -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 +16 -0
- data/lib/rigor/inference/expression_typer.rb +1559 -320
- data/lib/rigor/inference/external_ancestor_resolution.rb +3 -4
- data/lib/rigor/inference/flow_tracer.rb +31 -14
- data/lib/rigor/inference/fork_map.rb +3 -0
- data/lib/rigor/inference/fresh_frame_blocks.rb +52 -1
- data/lib/rigor/inference/global_write_census.rb +81 -5
- 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/in_effect_refinements.rb +7 -0
- data/lib/rigor/inference/indexed_narrowing.rb +61 -15
- data/lib/rigor/inference/intervening_ivar_reset.rb +26 -4
- data/lib/rigor/inference/ivar_writer_census.rb +154 -8
- data/lib/rigor/inference/key_presence_guard.rb +51 -24
- data/lib/rigor/inference/last_line/self_evidence.rb +30 -0
- data/lib/rigor/inference/last_line.rb +5 -2
- data/lib/rigor/inference/loop_value_record.rb +66 -14
- data/lib/rigor/inference/match_rebinding/frame.rb +57 -0
- data/lib/rigor/inference/match_rebinding/yielding_match.rb +101 -0
- data/lib/rigor/inference/match_rebinding.rb +28 -5
- 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 +44 -30
- data/lib/rigor/inference/method_dispatcher/class_keyed_block_params.rb +65 -0
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +3 -3
- data/lib/rigor/inference/method_dispatcher/contested_overloads.rb +89 -0
- data/lib/rigor/inference/method_dispatcher/core_enumerable_receiver.rb +44 -0
- data/lib/rigor/inference/method_dispatcher/declared_constructor.rb +151 -0
- data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/imprecise_argument.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/interface_shape.rb +181 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/no_match_fallback.rb +54 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +51 -27
- data/lib/rigor/inference/method_dispatcher/random_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +606 -78
- 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 +3 -3
- data/lib/rigor/inference/method_dispatcher/set_folding.rb +9 -7
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +467 -84
- 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/singleton_type_params.rb +104 -0
- 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 +123 -25
- data/lib/rigor/inference/method_parameter_binder.rb +136 -56
- data/lib/rigor/inference/module_function_state/spellings.rb +2 -2
- data/lib/rigor/inference/module_function_state.rb +24 -3
- data/lib/rigor/inference/multi_target_binder.rb +2 -2
- data/lib/rigor/inference/mutation_rejoin.rb +240 -4
- data/lib/rigor/inference/mutation_widening.rb +199 -29
- data/lib/rigor/inference/narrowing.rb +238 -50
- data/lib/rigor/inference/operand_effects.rb +43 -2
- data/lib/rigor/inference/optimistic_origin.rb +134 -9
- data/lib/rigor/inference/origin_lookup.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/precision_scanner.rb +1 -1
- data/lib/rigor/inference/project_method_ownership.rb +30 -9
- data/lib/rigor/inference/project_patched_methods.rb +65 -13
- data/lib/rigor/inference/project_patched_scanner.rb +120 -25
- data/lib/rigor/inference/project_patched_visibility.rb +39 -3
- data/lib/rigor/inference/project_yielder.rb +11 -17
- data/lib/rigor/inference/rbs_type_translator.rb +68 -15
- data/lib/rigor/inference/receiver_alias.rb +20 -0
- data/lib/rigor/inference/receiver_writer_call.rb +67 -0
- data/lib/rigor/inference/recursion_rebinding.rb +157 -0
- data/lib/rigor/inference/refined_dispatch/constructed_class.rb +57 -17
- data/lib/rigor/inference/refined_dispatch/own_method.rb +51 -16
- data/lib/rigor/inference/refined_dispatch.rb +13 -0
- data/lib/rigor/inference/reflective_ivar_write.rb +19 -11
- data/lib/rigor/inference/remover_holder_scan.rb +287 -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 +0 -1
- data/lib/rigor/inference/scope_indexer/class_cvars_collector.rb +13 -6
- data/lib/rigor/inference/scope_indexer/constant_ivar_value.rb +93 -0
- data/lib/rigor/inference/scope_indexer/declared_param_writes.rb +70 -26
- 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 +295 -0
- data/lib/rigor/inference/scope_indexer/mixin_accumulator.rb +136 -9
- data/lib/rigor/inference/scope_indexer.rb +2213 -226
- data/lib/rigor/inference/self_call_ivar_writes.rb +103 -12
- data/lib/rigor/inference/self_preserving_block.rb +87 -0
- data/lib/rigor/inference/set_mutation.rb +189 -0
- data/lib/rigor/inference/singleton_hook_decline.rb +42 -8
- data/lib/rigor/inference/singleton_object_constant.rb +32 -2
- data/lib/rigor/inference/statement_evaluator.rb +3268 -358
- data/lib/rigor/inference/string_mutation.rb +14 -0
- data/lib/rigor/inference/struct_fold_safety.rb +4 -6
- data/lib/rigor/inference/synthetic_method_scanner.rb +40 -17
- data/lib/rigor/inference/toplevel_def_census.rb +67 -0
- data/lib/rigor/inference/unknown_store_widening.rb +103 -4
- data/lib/rigor/inference/unthreaded_rebinds.rb +2 -3
- data/lib/rigor/inference/untyped_rejoin.rb +1 -1
- data/lib/rigor/inference/void_tail_summary.rb +29 -9
- data/lib/rigor/language_server/buffer_table.rb +3 -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 +8 -3
- 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 +39 -1
- 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 +7 -3
- data/lib/rigor/language_server/signature_help_provider.rb +4 -4
- data/lib/rigor/lens/claims/comparison.rb +78 -0
- data/lib/rigor/lens/claims/request.rb +131 -0
- data/lib/rigor/lens/claims/type_reader.rb +216 -0
- data/lib/rigor/lens/claims.rb +208 -0
- data/lib/rigor/lens/contract_reader.rb +5 -0
- data/lib/rigor/lens/document.rb +1 -1
- data/lib/rigor/lens/file_reader.rb +21 -8
- data/lib/rigor/lens/plugins.rb +1 -1
- data/lib/rigor/lens/run.rb +8 -0
- data/lib/rigor/lens.rb +1 -1
- data/lib/rigor/library_probe.rb +68 -0
- data/lib/rigor/mcp/server.rb +73 -2
- data/lib/rigor/mcp.rb +1 -1
- data/lib/rigor/memo_audit.rb +282 -0
- data/lib/rigor/plugin/access_denied_error.rb +1 -2
- data/lib/rigor/plugin/base.rb +15 -2
- data/lib/rigor/plugin/bundled_catalog.rb +1 -12
- data/lib/rigor/plugin/io_boundary.rb +26 -4
- 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 +16 -16
- data/lib/rigor/plugin/registry.rb +16 -5
- 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 +48 -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 +44 -5
- data/lib/rigor/protection/mutation_cache.rb +4 -1
- 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 +81 -22
- data/lib/rigor/reflection/declaration_collectors.rb +55 -0
- data/lib/rigor/reflection/declarations.rb +58 -0
- data/lib/rigor/reflection/project_method.rb +177 -0
- data/lib/rigor/reflection.rb +2 -0
- data/lib/rigor/rooted_glob.rb +32 -1
- data/lib/rigor/run_scoped_slots.rb +38 -0
- data/lib/rigor/runtime/jit.rb +1 -1
- data/lib/rigor/scope/discovery_index.rb +168 -8
- data/lib/rigor/scope/resolution_chain/relevance.rb +14 -1
- data/lib/rigor/scope/resolution_chain.rb +901 -54
- data/lib/rigor/scope.rb +644 -37
- data/lib/rigor/sig_gen/bot_proposal_guard.rb +306 -0
- data/lib/rigor/sig_gen/classification.rb +18 -1
- data/lib/rigor/sig_gen/effect_annotation.rb +3 -3
- data/lib/rigor/sig_gen/generator.rb +588 -66
- 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 +37 -4
- data/lib/rigor/sig_gen/observation_collector.rb +14 -7
- 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/platform_guarded_files.rb +184 -0
- data/lib/rigor/sig_gen/renderer.rb +15 -9
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +62 -2
- 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 +238 -37
- data/lib/rigor/sig_gen.rb +1 -0
- data/lib/rigor/source/forwardable_delegators.rb +122 -0
- data/lib/rigor/source/node_children.rb +13 -0
- 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 +173 -21
- data/lib/rigor/type/constant.rb +4 -5
- data/lib/rigor/type/hash_shape.rb +21 -40
- data/lib/rigor/type/interface.rb +60 -0
- data/lib/rigor/type/union.rb +1 -1
- data/lib/rigor/type.rb +1 -0
- 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/type_of_memo/serving.rb +99 -0
- data/lib/rigor/type_of_memo/stats.rb +43 -0
- data/lib/rigor/type_of_memo.rb +337 -0
- data/lib/rigor/typing_state.rb +1094 -0
- 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 +38 -36
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +4 -2
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +6 -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 +3 -3
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +115 -36
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +3 -6
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +25 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +16 -6
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +4 -2
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +4 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +2 -1
- 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 +132 -33
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +20 -6
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +7 -4
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +54 -17
- data/plugins/rigor-activerecord/sig/active_record/relation.rbs +19 -5
- 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 +11 -14
- 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 +30 -9
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +55 -13
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_collector.rb +15 -21
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_discoverer.rb +1 -6
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_index.rb +3 -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 +1 -1
- 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 +8 -7
- 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-graphql/lib/rigor/plugin/graphql.rb +12 -2
- 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 +8 -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 +200 -4
- 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 +4 -3
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +2 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +5 -5
- 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 +3 -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 +210 -3
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +146 -7
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +2 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +52 -34
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +97 -24
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +2 -3
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_collector.rb +16 -16
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_discoverer.rb +4 -8
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_index.rb +4 -4
- data/sig/rigor/analysis/baseline.rbs +0 -3
- data/sig/rigor/analysis/check_rules/rule_walk.rbs +6 -0
- data/sig/rigor/analysis/fact_store.rbs +2 -2
- data/sig/rigor/analysis/reachability/scan_cache.rbs +1 -1
- data/sig/rigor/cache/descriptor.rbs +14 -0
- data/sig/rigor/cli/diff_command.rbs +1 -1
- data/sig/rigor/cli/explain_command.rbs +1 -1
- data/sig/rigor/effects/registry.rbs +2 -2
- data/sig/rigor/environment.rbs +4 -1
- data/sig/rigor/inference.rbs +4 -1
- data/sig/rigor/plugin/additional_initializer.rbs +0 -5
- data/sig/rigor/plugin/base.rbs +53 -18
- data/sig/rigor/plugin/effect_attribution.rbs +3 -3
- data/sig/rigor/plugin/effect_edge.rbs +1 -1
- data/sig/rigor/plugin/effect_entry_points.rbs +3 -3
- data/sig/rigor/plugin/interfaces.rbs +51 -0
- data/sig/rigor/plugin/io_boundary.rbs +3 -3
- data/sig/rigor/plugin/manifest.rbs +9 -9
- data/sig/rigor/plugin/node_context.rbs +21 -0
- data/sig/rigor/plugin/protocol_contract.rbs +3 -7
- data/sig/rigor/reflection.rbs +37 -0
- data/sig/rigor/scope.rbs +43 -4
- data/sig/rigor/trinary.rbs +1 -0
- data/sig/rigor/type.rbs +9 -3
- data/sig/rigor.rbs +3 -2
- data/skills/rigor-ask/SKILL.md +1 -0
- 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/01-detect.md +1 -0
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +17 -2
- data/skills/rigor-project-init/references/06-agent-contract.md +4 -4
- data/skills/rigor-rbs-contract/SKILL.md +147 -0
- data/skills/rigor-rbs-contract/references/01-finding-candidates.md +212 -0
- data/skills/rigor-rbs-contract/references/02-contract-rules.md +157 -0
- data/skills/rigor-rbs-contract/references/03-target-own-code.md +90 -0
- data/skills/rigor-rbs-contract/references/04-target-gem-rbs-collection.md +210 -0
- data/skills/rigor-rbs-contract/references/05-declaration-mutants.md +182 -0
- data/skills/rigor-rbs-setup/SKILL.md +3 -1
- data/skills/rigor-type-oracle/SKILL.md +26 -1
- data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +4 -3
- metadata +82 -3
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require "digest"
|
|
4
4
|
|
|
5
|
+
require_relative "../typing_state"
|
|
6
|
+
|
|
5
7
|
module Rigor
|
|
6
8
|
module Cache
|
|
7
9
|
# Per-run content-digest memo AND the ADR-87 stat-then-digest freshness choke point. Within a single
|
|
@@ -20,20 +22,38 @@ module Rigor
|
|
|
20
22
|
# zero SHA-256 bytes. The SHA-256 digest remains the sole change AUTHORITY — the stat tier only decides
|
|
21
23
|
# whether the digest needs recomputing.
|
|
22
24
|
#
|
|
23
|
-
# Soundness: the memo + recording-instant + strict flag are process-local (thread
|
|
24
|
-
# and never crossing a fork boundary), never persisted to disk, and scoped to exactly one
|
|
25
|
-
# {.with_run} (which installs a fresh table and restores the previous one on exit — a second run, or a run
|
|
25
|
+
# Soundness: the memo + recording-instant + strict flag are process-local (a per-thread {TypingState}
|
|
26
|
+
# Frame, so Ractor-safe and never crossing a fork boundary), never persisted to disk, and scoped to exactly one
|
|
27
|
+
# run via {.with_run} (which installs a fresh table and restores the previous one on exit — a second run, or a run
|
|
26
28
|
# that re-reads a file the user edited between runs, gets a clean table). Within a single run the analyzer
|
|
27
29
|
# already assumes the filesystem is stable — {Descriptor#fresh?} validates the whole dependency set against
|
|
28
30
|
# the live tree in one pass and never re-checks mid-run — so caching a coherent per-run snapshot changes
|
|
29
31
|
# nothing about what a run observes. Outside a run scope (no active table) every call digests directly,
|
|
30
32
|
# identical to a bare `Digest::SHA256.file`.
|
|
31
33
|
module FileDigest
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
# One run's state: the digest table, the stat table, the recording instant and the strict flag, installed
|
|
35
|
+
# together by {.with_run}.
|
|
36
|
+
Run = Data.define(:digests, :stats, :instant, :strict)
|
|
37
|
+
private_constant :Run
|
|
38
|
+
|
|
39
|
+
# ADR-129 WD1 — a Frame: {.with_run} installs the run and restores the previous one on the way out, and whether
|
|
40
|
+
# one is installed changes answers (outside a run every call digests or stats directly, the recording instant
|
|
41
|
+
# is the moment of the call, and validation is not strict). The installed {Run} is frozen; its two tables are
|
|
42
|
+
# extensional caches its owner fills in place without a touch (Memos by kind, whose entry is fixed once
|
|
43
|
+
# written): `digests` is keyed on the path and reads the file's bytes, `stats` is keyed on the path and reads
|
|
44
|
+
# its `File::Stat`, both under the run's premise that the filesystem is stable. The instant and the flag are
|
|
45
|
+
# read at install time.
|
|
46
|
+
RUN = TypingState.frame(
|
|
47
|
+
:file_digest_run,
|
|
48
|
+
memos: %i[digests stats],
|
|
49
|
+
reason: "installed per run by with_run; the digest and stat tables are extensional caches keyed on the path, " \
|
|
50
|
+
"filled in place, both reading the filesystem under the run's stable-filesystem premise, and the " \
|
|
51
|
+
"recording instant and strict flag are fixed at install",
|
|
52
|
+
# G1′: the run wraps the typing of every file, but the digest and stat lookups are the cache layer's, made while
|
|
53
|
+
# the RBS environment is prepared and its producers fetched, before anything types (#2883).
|
|
54
|
+
typing_never_reads: true
|
|
55
|
+
)
|
|
56
|
+
private_constant :RUN
|
|
37
57
|
|
|
38
58
|
# Set in the environment to force the strict digest-always validation path for a single run, regardless
|
|
39
59
|
# of the `cache.validation` config setting (the env wins). The escape hatch for a filesystem whose stat
|
|
@@ -46,21 +66,9 @@ module Rigor
|
|
|
46
66
|
# captured at run start — a file whose recorded mtime is not strictly older than it is treated as racy
|
|
47
67
|
# (always re-hashed), catching a file edited during the analysis window. `strict:` forces the
|
|
48
68
|
# digest-always path for `cache.validation: digest`.
|
|
49
|
-
def self.with_run(strict: false)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
previous_instant = Thread.current[INSTANT_KEY]
|
|
53
|
-
previous_strict = Thread.current[STRICT_KEY]
|
|
54
|
-
Thread.current[MEMO_KEY] = {}
|
|
55
|
-
Thread.current[STAT_KEY] = {}
|
|
56
|
-
Thread.current[INSTANT_KEY] = now_ns
|
|
57
|
-
Thread.current[STRICT_KEY] = strict
|
|
58
|
-
yield
|
|
59
|
-
ensure
|
|
60
|
-
Thread.current[MEMO_KEY] = previous_memo
|
|
61
|
-
Thread.current[STAT_KEY] = previous_stat
|
|
62
|
-
Thread.current[INSTANT_KEY] = previous_instant
|
|
63
|
-
Thread.current[STRICT_KEY] = previous_strict
|
|
69
|
+
def self.with_run(strict: false, &)
|
|
70
|
+
run = Run.new(digests: {}, stats: {}, instant: now_ns, strict: strict)
|
|
71
|
+
TypingState.current.with(RUN, run, &)
|
|
64
72
|
end
|
|
65
73
|
|
|
66
74
|
# The SHA-256 hex digest of `path`'s current content. Served from the active per-run table when one is
|
|
@@ -68,10 +76,10 @@ module Rigor
|
|
|
68
76
|
# read failure (missing / unreadable file) propagates exactly as `Digest::SHA256.file` would and is NOT
|
|
69
77
|
# memoised, so a caller's own rescue path is unchanged.
|
|
70
78
|
def self.hexdigest(path)
|
|
71
|
-
|
|
72
|
-
return Digest::SHA256.file(path).hexdigest if
|
|
79
|
+
run = TypingState.current[RUN]
|
|
80
|
+
return Digest::SHA256.file(path).hexdigest if run.nil?
|
|
73
81
|
|
|
74
|
-
|
|
82
|
+
run.digests[path] ||= Digest::SHA256.file(path).hexdigest
|
|
75
83
|
end
|
|
76
84
|
|
|
77
85
|
# @return whether digest-always validation is forced for this run. The env var wins over the
|
|
@@ -79,7 +87,7 @@ module Rigor
|
|
|
79
87
|
def self.strict_validation?
|
|
80
88
|
return true if ENV[STRICT_ENV] == "1"
|
|
81
89
|
|
|
82
|
-
|
|
90
|
+
TypingState.current[RUN]&.strict == true
|
|
83
91
|
end
|
|
84
92
|
|
|
85
93
|
# ADR-87 WD1 — packs the `:stat` FileEntry value: `"<digest> <size> <mtime_ns> <ctime_ns> <inode>
|
|
@@ -156,14 +164,14 @@ module Rigor
|
|
|
156
164
|
# describe that moment rather than an earlier probe's. A stat failure propagates un-memoised, exactly
|
|
157
165
|
# as {.hexdigest} treats a read failure.
|
|
158
166
|
def self.validation_stat(path)
|
|
159
|
-
|
|
160
|
-
return File.stat(path) if
|
|
167
|
+
run = TypingState.current[RUN]
|
|
168
|
+
return File.stat(path) if run.nil?
|
|
161
169
|
|
|
162
|
-
|
|
170
|
+
run.stats[path] ||= File.stat(path)
|
|
163
171
|
end
|
|
164
172
|
|
|
165
173
|
def self.recording_instant_ns
|
|
166
|
-
|
|
174
|
+
TypingState.current[RUN]&.instant || now_ns
|
|
167
175
|
end
|
|
168
176
|
|
|
169
177
|
# value layout: [digest, size, mtime_ns, ctime_ns, inode, recording_instant_ns]
|
|
@@ -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"
|
|
@@ -195,20 +196,43 @@ module Rigor
|
|
|
195
196
|
# 45: issue #1154 — each seed bundle's `global_write_census` also records the ivar writers the declared-parameter
|
|
196
197
|
# credit reads (`[:ivar_set, name]`, `[:ivar_set_class, class]`, `[:own_write, class, name, path]`), which a
|
|
197
198
|
# pre-45 bundle carries none of, so a warm run would credit an ivar write a cold run declines.
|
|
198
|
-
|
|
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
|
+
# 48: issue #1237 — a `return_summaries` key may carry a third element, `true`, for a call key a splat call
|
|
206
|
+
# observed, which the gate re-drives with no positional correspondence. A pre-48 summary holds such a call under a
|
|
207
|
+
# positional key the engine bound as one argument, so a warm run would re-drive it the old way.
|
|
208
|
+
# 49: issue #3116 — a `return_summaries` entry for a def observed under more keys than the per-def cap is
|
|
209
|
+
# `{ keys: [], returns: [], effects:, overflow: true }`. A pre-49 summary holds the first eight keys of such a
|
|
210
|
+
# def with no marker, so a warm run would skip the reader of a key it never recorded.
|
|
211
|
+
# 50: issue #3160 — a `return_summaries` entry holds every key under which a current reader observes the def,
|
|
212
|
+
# merged across the runs that observed them, and a def whose keys cannot all be listed has no entry (the
|
|
213
|
+
# `overflow` form of 49 is gone). A pre-50 summary holds only what the last run that analysed the def's file
|
|
214
|
+
# saw, so a warm run would skip a reader added, or left out of that run, since.
|
|
215
|
+
# 51: issue #3180 — a reader the ADR-89 WD2 gate skipped holds the dependency edges the gate's probe recorded
|
|
216
|
+
# for the def it passed, and the summaries hold the keys that probe observed. A pre-51 snapshot's skipped
|
|
217
|
+
# readers lack the edges and keys of whatever a gate-passed def came to reach, so a warm run would skip them.
|
|
218
|
+
# 52: issues #3186 / #3187 — a `return_summaries` entry also holds `guard_constants`, the published-constant
|
|
219
|
+
# spellings the truthiness rule's one hop reads in the def's body, and a gate-skipped reader holds the plugin
|
|
220
|
+
# reads and run-scoped registrations the gate's probe made. A pre-52 snapshot's skipped readers lack those
|
|
221
|
+
# plugin rows, so a warm run would serve them past an edit of what the plugin read.
|
|
222
|
+
SCHEMA = 52
|
|
199
223
|
|
|
200
224
|
# The persisted per-file state.
|
|
201
225
|
# `cache` maps an analyzed file to its diagnostics.
|
|
202
|
-
# `sources` maps a consumer to the
|
|
226
|
+
# `sources` maps a consumer to the source files it read from.
|
|
203
227
|
# `digests` maps a file to its content digest at analysis time.
|
|
204
228
|
# `analyzed` is the ordered analyzed-file list.
|
|
205
229
|
# ADR-46 slice 4:
|
|
206
|
-
# `symbol_sources` maps a consumer to { source_path →
|
|
207
|
-
# `ancestry_sources` maps a consumer to
|
|
230
|
+
# `symbol_sources` maps a consumer to { source_path → the "ClassName#method" names it read }.
|
|
231
|
+
# `ancestry_sources` maps a consumer to the source paths it read for class ancestry.
|
|
208
232
|
# `symbol_fingerprints` maps a path to { "ClassName#method" => sha256_hex }.
|
|
209
233
|
# ADR-46 slice 3:
|
|
210
|
-
# `missing` maps a consumer to
|
|
211
|
-
# `class_decls` maps a path to
|
|
234
|
+
# `missing` maps a consumer to the "kind:name" keys it looked up and missed.
|
|
235
|
+
# `class_decls` maps a path to the qualified class names it declares.
|
|
212
236
|
# Issue #644:
|
|
213
237
|
# `constant_decls` maps a path to that file's constant PUBLICATION CENSUS,
|
|
214
238
|
# `{qualified name => [literal] | :unpublishable}`. The descriptor is what the recheck diffs: a name's
|
|
@@ -226,10 +250,15 @@ module Rigor
|
|
|
226
250
|
# fingerprint cannot see.
|
|
227
251
|
# ADR-89 WD2:
|
|
228
252
|
# `return_summaries` maps a `[path, "Class#method" | "Class.method"]` to the callee's persisted
|
|
229
|
-
# behavioural surface `{ keys:, returns:, effects: }` — the observed `[receiver, arg_types]`
|
|
230
|
-
# (
|
|
231
|
-
#
|
|
232
|
-
#
|
|
253
|
+
# behavioural surface `{ keys:, returns:, effects:, guard_constants: }` — the observed `[receiver, arg_types]`
|
|
254
|
+
# call keys (issue #1237: `[receiver, arg_types, true]` for a key a splat call observed)
|
|
255
|
+
# (Marshal-clean type tuples), their `describe(:short)` return descriptors, the content-mutated
|
|
256
|
+
# parameter positions, and (issue #3186) the published-constant spellings the body reads.
|
|
257
|
+
# A recheck re-evaluates a declaration-stable changed callee at these keys and,
|
|
258
|
+
# when every return, the effects and the spellings are unchanged, skips its symbol dependents.
|
|
259
|
+
# Issues #3116 / #3160 — an entry
|
|
260
|
+
# holds every key under which a current symbol dependent observes the def; a def whose keys cannot all be
|
|
261
|
+
# listed (more than the per-def cap, among others) has no entry, and the recheck never skips its dependents.
|
|
233
262
|
# ADR-67 WD6c lift:
|
|
234
263
|
# `param_table` is the `parameter_inference:` seed table (`[class, method, kind] => {param => Type}`)
|
|
235
264
|
# the run that wrote the snapshot seeded its analysis from — `{}` when the gate is off. A recheck
|
|
@@ -279,12 +308,14 @@ module Rigor
|
|
|
279
308
|
end
|
|
280
309
|
end
|
|
281
310
|
|
|
282
|
-
# Issues #796 / #794 — the
|
|
283
|
-
#
|
|
284
|
-
#
|
|
285
|
-
#
|
|
286
|
-
#
|
|
287
|
-
|
|
311
|
+
# Issues #796 / #794 — the run-level rows the snapshot carries: one member per run-level fact declared
|
|
312
|
+
# `replay` ({Analysis::Runner::RunLevelFacts}, ADR-116 WD3). Today that is `definition_build_failures`,
|
|
313
|
+
# the reported per-class detail list ({Environment::RbsLoader#definition_build_failures}), and
|
|
314
|
+
# `hkt_scan_failure`, the `[error_class, first_line, frame, stage]` tuple
|
|
315
|
+
# ({Rigor::Environment#hkt_scan_failure}), nil when the scan succeeded — which is why the presence of
|
|
316
|
+
# this object, not the tuple, is what says a replay is available. Declaring another fact `replay`
|
|
317
|
+
# changes this shape, so it bumps {SCHEMA}.
|
|
318
|
+
RunLevelRows = Data.define(*Analysis::Runner::RunLevelFacts.replayable_names)
|
|
288
319
|
|
|
289
320
|
# The global fingerprint that gates a snapshot load: a digest of the inputs whose change requires a full
|
|
290
321
|
# rebuild — the engine version + schema, the engine's own SOURCE when the version does not pin it, the
|
|
@@ -324,7 +355,7 @@ module Rigor
|
|
|
324
355
|
"sig:#{digest_signature_paths(project_sig_roots(configuration))}",
|
|
325
356
|
"pre_eval:#{digest_pre_eval(configuration.pre_eval)}"
|
|
326
357
|
]
|
|
327
|
-
parts.concat(
|
|
358
|
+
parts.concat(project_input_parts(configuration))
|
|
328
359
|
identity = EngineSource.process_identity
|
|
329
360
|
parts << "engine-source:#{identity}" if identity
|
|
330
361
|
# Issue #1700 — the gated vendored signatures the run's source activates. A file that gains or drops a
|
|
@@ -347,6 +378,37 @@ module Rigor
|
|
|
347
378
|
nil
|
|
348
379
|
end
|
|
349
380
|
|
|
381
|
+
# Issue #2517 — a selected core is read like the project's own `sig/`, so an edit in place to one of its files
|
|
382
|
+
# must drop the snapshot (and the language server's session, which keys on this fingerprint). No part for the
|
|
383
|
+
# default core, so every other project's fingerprint is as it was.
|
|
384
|
+
def self.extra_signature_parts(configuration)
|
|
385
|
+
core_root_parts(configuration) + bundle_sig_parts(configuration)
|
|
386
|
+
end
|
|
387
|
+
private_class_method :extra_signature_parts
|
|
388
|
+
|
|
389
|
+
def self.core_root_parts(configuration)
|
|
390
|
+
core_root = configuration.core_root
|
|
391
|
+
core_root.nil? ? [] : ["core:#{digest_signature_paths([core_root])}"]
|
|
392
|
+
end
|
|
393
|
+
private_class_method :core_root_parts
|
|
394
|
+
|
|
395
|
+
# Issue #2987 — the bundle gems' own `sig/` directories the environment loads: which gems have one and what
|
|
396
|
+
# their `.rbs` files hold. The lockfile digest above covers a gem's version, not a `sig/` appearing under an
|
|
397
|
+
# unchanged version, nor an edit in place to one. Shared with the language server's session key. No part for a
|
|
398
|
+
# project whose bundle holds none, so its fingerprint is as it was.
|
|
399
|
+
def self.bundle_sig_parts(configuration)
|
|
400
|
+
locked = Environment::LockfileResolver.locked_gems(
|
|
401
|
+
lockfile_path: configuration.bundler_lockfile, project_root: Dir.pwd,
|
|
402
|
+
auto_detect: configuration.bundler_auto_detect
|
|
403
|
+
)
|
|
404
|
+
dirs = Environment::BundleSigDiscovery.discover(
|
|
405
|
+
bundle_path: configuration.bundler_bundle_path, project_root: Dir.pwd,
|
|
406
|
+
auto_detect: configuration.bundler_auto_detect, locked_gems: locked.empty? ? nil : locked
|
|
407
|
+
).map(&:to_s).sort
|
|
408
|
+
dirs.empty? ? [] : ["bundle-sig:#{dirs.join("\n")}:#{digest_signature_paths(dirs)}"]
|
|
409
|
+
end
|
|
410
|
+
private_class_method :bundle_sig_parts
|
|
411
|
+
|
|
350
412
|
def self.required_features(configuration, roots)
|
|
351
413
|
files = Analysis::PathExpansion.ruby_files(roots, configuration.exclude_patterns,
|
|
352
414
|
base: configuration.exclude_base)
|
|
@@ -364,6 +426,22 @@ module Rigor
|
|
|
364
426
|
end
|
|
365
427
|
private_class_method :dependency_source_parts
|
|
366
428
|
|
|
429
|
+
# The parts read off the project beside its configuration, in the order the fingerprint has always joined them:
|
|
430
|
+
# the extra signature roots, the `dependencies.source_inference` gems, and (#3030) the collection setup hint.
|
|
431
|
+
def self.project_input_parts(configuration)
|
|
432
|
+
extra_signature_parts(configuration) + dependency_source_parts(configuration) +
|
|
433
|
+
collection_setup_hint_parts(configuration)
|
|
434
|
+
end
|
|
435
|
+
private_class_method :project_input_parts
|
|
436
|
+
|
|
437
|
+
# Issue #3030 — the `rbs.coverage.collection-not-installed` hint, a run-level row read off the working directory
|
|
438
|
+
# that no other part covers. No part without a hint, so every other project's fingerprint is as it was.
|
|
439
|
+
def self.collection_setup_hint_parts(configuration)
|
|
440
|
+
hint = Analysis::RunCacheKey.collection_setup_hint(configuration)
|
|
441
|
+
hint ? ["rbs-collection-hint:#{hint}"] : []
|
|
442
|
+
end
|
|
443
|
+
private_class_method :collection_setup_hint_parts
|
|
444
|
+
|
|
367
445
|
def self.digest_file_if_present(path)
|
|
368
446
|
path = path&.to_s
|
|
369
447
|
path && File.file?(path) ? Digest::SHA256.file(path).hexdigest : "absent"
|
|
@@ -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,58 @@ 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)
|
|
80
|
+
[deferred_signature_paths_entry(loader), project_signature_paths_entry(loader), core_root_entry(loader),
|
|
81
|
+
subordinate_signature_paths_entry(loader), collection_signature_paths_entry(loader)].compact
|
|
81
82
|
end
|
|
82
83
|
|
|
84
|
+
# Issue #2517 — which directory the env loaded core from. The selected core's files are digested by
|
|
85
|
+
# {.file_entries} too, so this row is the identity of the choice and those rows its contents: switching
|
|
86
|
+
# between two roots with byte-identical files still re-keys. Absent for the default core, whose identity
|
|
87
|
+
# is the `rbs` gem row, so every project without the setting keeps its key.
|
|
88
|
+
def self.core_root_entry(loader)
|
|
89
|
+
core_root = selected_core_root(loader)
|
|
90
|
+
return nil if core_root.nil?
|
|
91
|
+
|
|
92
|
+
Descriptor::ConfigEntry.new(key: "rbs.core_root", value_hash: Digest::SHA256.hexdigest(core_root.to_s))
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
private_class_method :core_root_entry
|
|
96
|
+
|
|
97
|
+
# The loader's issue #2517 core root as a Pathname, or nil for the default core.
|
|
98
|
+
def self.selected_core_root(loader)
|
|
99
|
+
core_root = loader.respond_to?(:core_root) ? loader.core_root : nil
|
|
100
|
+
core_root.nil? ? nil : Pathname(core_root)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private_class_method :selected_core_root
|
|
104
|
+
|
|
105
|
+
# {.selected_core_root} as the signature roots it adds: none for the default core.
|
|
106
|
+
def self.core_root_dirs(loader)
|
|
107
|
+
core_root = selected_core_root(loader)
|
|
108
|
+
core_root.nil? ? [] : [core_root]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
private_class_method :core_root_dirs
|
|
112
|
+
|
|
113
|
+
# Issue #2422 — which of the loader's `signature_paths:` are the project's own changes the env built from
|
|
114
|
+
# byte-identical files: a bundled plugin's method composes with another source's as an overload, but stands
|
|
115
|
+
# down to the project's own. Only read when a plugin defers signatures, so a project without one keeps its
|
|
116
|
+
# key.
|
|
117
|
+
def self.project_signature_paths_entry(loader)
|
|
118
|
+
return nil unless loader.respond_to?(:project_signature_paths) && loader.respond_to?(:deferred_signature_paths)
|
|
119
|
+
return nil if Array(loader.deferred_signature_paths).empty?
|
|
120
|
+
|
|
121
|
+
own = Array(loader.project_signature_paths).map(&:to_s).sort
|
|
122
|
+
return nil if own.empty?
|
|
123
|
+
|
|
124
|
+
Descriptor::ConfigEntry.new(
|
|
125
|
+
key: "rbs.project_signature_paths",
|
|
126
|
+
value_hash: Digest::SHA256.hexdigest(own.join("\n"))
|
|
127
|
+
)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
private_class_method :project_signature_paths_entry
|
|
131
|
+
|
|
83
132
|
def self.deferred_signature_paths_entry(loader)
|
|
84
133
|
return nil unless loader.respond_to?(:deferred_signature_paths)
|
|
85
134
|
|
|
@@ -94,6 +143,40 @@ module Rigor
|
|
|
94
143
|
|
|
95
144
|
private_class_method :deferred_signature_paths_entry
|
|
96
145
|
|
|
146
|
+
# Issue #2978 — which of the loader's `signature_paths:` stand down member by member to the rest (a bundle gem's
|
|
147
|
+
# collection copy behind its own `sig/`) changes the env built from byte-identical files, as the deferred
|
|
148
|
+
# partition does. Absent when there is none, so every other project keeps its key.
|
|
149
|
+
def self.subordinate_signature_paths_entry(loader)
|
|
150
|
+
return nil unless loader.respond_to?(:subordinate_signature_paths)
|
|
151
|
+
|
|
152
|
+
subordinate = Array(loader.subordinate_signature_paths).map(&:to_s).sort
|
|
153
|
+
return nil if subordinate.empty?
|
|
154
|
+
|
|
155
|
+
Descriptor::ConfigEntry.new(
|
|
156
|
+
key: "rbs.subordinate_signature_paths",
|
|
157
|
+
value_hash: Digest::SHA256.hexdigest(subordinate.join("\n"))
|
|
158
|
+
)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
private_class_method :subordinate_signature_paths_entry
|
|
162
|
+
|
|
163
|
+
# Issue #3030 — which of the loader's `signature_paths:` are `rbs collection` gem directories decides whether
|
|
164
|
+
# their `_`-prefixed directories load, so it changes the env built from byte-identical files. Absent when
|
|
165
|
+
# there is none, so every project without a collection lockfile keeps its key.
|
|
166
|
+
def self.collection_signature_paths_entry(loader)
|
|
167
|
+
return nil unless loader.respond_to?(:collection_signature_paths)
|
|
168
|
+
|
|
169
|
+
collection = Array(loader.collection_signature_paths).map(&:to_s).sort
|
|
170
|
+
return nil if collection.empty?
|
|
171
|
+
|
|
172
|
+
Descriptor::ConfigEntry.new(
|
|
173
|
+
key: "rbs.collection_signature_paths",
|
|
174
|
+
value_hash: Digest::SHA256.hexdigest(collection.join("\n"))
|
|
175
|
+
)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
private_class_method :collection_signature_paths_entry
|
|
179
|
+
|
|
97
180
|
# Public (ADR-87 WD4) so the boot-slimming run-cache probe reconstructs the identical `gems` +
|
|
98
181
|
# `rbs.libraries` key slots the runner writes, from the config-derived library list, without a loader.
|
|
99
182
|
def self.rbs_gem_entry
|
|
@@ -104,7 +187,9 @@ module Rigor
|
|
|
104
187
|
# value must be deterministic; `:stat` (ADR-87 WD1) for the validation-only run-dependency descriptor
|
|
105
188
|
# ({RunDescriptor#files}), where the stat tier short-circuits the SHA-256 on an unmoved file.
|
|
106
189
|
def self.file_entries(loader, comparator: :digest)
|
|
107
|
-
|
|
190
|
+
# Issue #2517 — a selected core is project input like `signature_paths:`, not the engine-versioned `rbs`
|
|
191
|
+
# gem tree, so an edit in place must move the key.
|
|
192
|
+
roots = core_root_dirs(loader) + loader.signature_paths +
|
|
108
193
|
Rigor::Environment::RbsLoader.vendored_gem_sig_paths +
|
|
109
194
|
Rigor::Environment::RbsLoader.core_overlay_sig_paths +
|
|
110
195
|
Rigor::Environment::RbsLoader.capability_role_sig_paths
|
|
@@ -149,7 +234,8 @@ module Rigor
|
|
|
149
234
|
def self.glob_entries(loader)
|
|
150
235
|
# Deduplicated by path: a root reachable twice (an explicit `signature_paths:` entry that is also a
|
|
151
236
|
# bundled plugin's `sig/`, #610) would otherwise contribute two rows whose stat signatures race.
|
|
152
|
-
|
|
237
|
+
# Issue #2517 — and the selected core's root, where a file appearing is as much a new input.
|
|
238
|
+
(core_root_dirs(loader) + loader.signature_paths).uniq(&:to_s).filter_map do |root|
|
|
153
239
|
next unless root.directory?
|
|
154
240
|
|
|
155
241
|
Descriptor::GlobEntry.compute(root: root.to_s, pattern: File.join("**", "*.rbs"), mode: :names)
|
|
@@ -157,7 +243,7 @@ module Rigor
|
|
|
157
243
|
end
|
|
158
244
|
|
|
159
245
|
# @param library_names — the loader's merged library list (or, on the WD4 probe
|
|
160
|
-
# path, `Environment::
|
|
246
|
+
# path, `Environment::BaseLibraries.resolve` reconstructed without a loader).
|
|
161
247
|
def self.libraries_entry(library_names)
|
|
162
248
|
sorted = library_names.map(&:to_s).sort
|
|
163
249
|
Descriptor::ConfigEntry.new(
|
|
@@ -33,7 +33,14 @@ 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,
|
|
40
|
+
subordinate_signature_paths:
|
|
41
|
+
loader.respond_to?(:subordinate_signature_paths) ? loader.subordinate_signature_paths : [],
|
|
42
|
+
collection_signature_paths:
|
|
43
|
+
loader.respond_to?(:collection_signature_paths) ? loader.collection_signature_paths : []
|
|
37
44
|
)
|
|
38
45
|
end
|
|
39
46
|
|
|
@@ -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
|
|
@@ -7,7 +7,7 @@ module Rigor
|
|
|
7
7
|
module Cache
|
|
8
8
|
# Cache producer that materialises the set of every RBS-declared class / module / alias name (top-level
|
|
9
9
|
# prefixed, e.g. `"::Math"`) currently loaded into the environment. Marshal-clean — the cache value is a
|
|
10
|
-
#
|
|
10
|
+
# Set of names.
|
|
11
11
|
#
|
|
12
12
|
# The set lets `RbsLoader#class_known?` answer point lookups in O(1) without re-parsing the name on each
|
|
13
13
|
# call, and lets a warm process skip the env walk entirely (the env still has to be built to enumerate
|
data/lib/rigor/cache/store.rb
CHANGED
|
@@ -135,14 +135,6 @@ module Rigor
|
|
|
135
135
|
end
|
|
136
136
|
end
|
|
137
137
|
|
|
138
|
-
# Walks the on-disk cache rooted at `root` and reports a producer-level inventory. Used by
|
|
139
|
-
# `rigor check --cache-stats` to surface cache size and per-producer entry counts without depending on
|
|
140
|
-
# in-process counters (which only reflect the current run).
|
|
141
|
-
#
|
|
142
|
-
# @return `{ root:, schema_version:, total_entries:, total_bytes:, producers: [{ id:, entries:,
|
|
143
|
-
# bytes: }, ...] }`. When the root does not exist or has no schema-version marker, `schema_version` is
|
|
144
|
-
# nil and the producer list is empty.
|
|
145
|
-
#
|
|
146
138
|
# The `schema_version.txt` marker content. Covers BOTH invalidation axes: the descriptor schema and the
|
|
147
139
|
# on-disk byte layout ({FORMAT_VERSION}, ADR-54). A format bump leaves the old entries permanently
|
|
148
140
|
# unreadable (header mismatch → miss) but, alone, would never reclaim their bytes — they can sit below
|
|
@@ -152,6 +144,13 @@ module Rigor
|
|
|
152
144
|
"#{PAYLOAD_ABI_VERSION}.#{Descriptor::SCHEMA_VERSION}.#{FORMAT_VERSION}"
|
|
153
145
|
end
|
|
154
146
|
|
|
147
|
+
# Walks the on-disk cache rooted at `root` and reports a producer-level inventory. Used by
|
|
148
|
+
# `rigor check --cache-stats` to surface cache size and per-producer entry counts without depending on
|
|
149
|
+
# in-process counters (which only reflect the current run).
|
|
150
|
+
#
|
|
151
|
+
# @return `{ root:, schema_version:, total_entries:, total_bytes:, producers: [{ id:, entries:,
|
|
152
|
+
# bytes: }, ...] }`. When the root does not exist or has no schema-version marker, `schema_version` is
|
|
153
|
+
# nil and the producer list is empty.
|
|
155
154
|
def self.disk_inventory(root:)
|
|
156
155
|
root_s = root.to_s
|
|
157
156
|
marker = File.join(root_s, "schema_version.txt")
|
|
@@ -360,7 +359,8 @@ module Rigor
|
|
|
360
359
|
# size-based LRU pass below stays gated on `max_bytes:` being configured: it walks all remaining
|
|
361
360
|
# `.entry` files, sorts by mtime ascending (oldest = least recently used), and unlinks from the oldest
|
|
362
361
|
# until the total is at or below the cap. Touch-on-disk-read ({read_entry}) is the cross-process LRU
|
|
363
|
-
# signal:
|
|
362
|
+
# signal: a disk hit (not an in-process-memo hit) updates the mtime when `max_bytes:` is set, so
|
|
363
|
+
# recently-read entries survive
|
|
364
364
|
# the eviction pass. Any FS error is swallowed — eviction must never break a run.
|
|
365
365
|
def evict!
|
|
366
366
|
return if @read_only
|
|
@@ -591,7 +591,8 @@ module Rigor
|
|
|
591
591
|
# — one check per Store is enough; a benign double-check under a thread race would just repeat
|
|
592
592
|
# idempotent work.
|
|
593
593
|
#
|
|
594
|
-
# A writable store clears the cache root and rewrites the marker on a stale
|
|
594
|
+
# A writable store clears the cache root and rewrites the marker on a stale marker (a missing or empty
|
|
595
|
+
# one is rewritten without clearing), then reports
|
|
595
596
|
# available. A read-only store never touches the root — no mkdir, no marker write, no destructive clear
|
|
596
597
|
# — so it reports available ONLY when the on-disk marker already matches current exactly; a stale or
|
|
597
598
|
# missing marker (e.g. a Rigor upgrade with no writable run yet, as in LSP / editor mode) reports
|
data/lib/rigor/ci_detector.rb
CHANGED
|
@@ -20,7 +20,7 @@ module Rigor
|
|
|
20
20
|
# non-CLI consumers exist: {Configuration#cache_validation_strict?} resolves the `auto` cache-validation default
|
|
21
21
|
# through it (a fresh CI checkout regenerates every stat tuple, so ADR-87's stat tier cannot work there).
|
|
22
22
|
# Detection is fully testable; callers pass `ENV`.
|
|
23
|
-
# `RIGOR_CI_DETECT=0` (or `false`/`no`) disables it globally — the seam the spec suite uses for determinism.
|
|
23
|
+
# `RIGOR_CI_DETECT=0` (or `false`/`no`/`off`) disables it globally — the seam the spec suite uses for determinism.
|
|
24
24
|
module CiDetector
|
|
25
25
|
Platform = Struct.new(:id, :name, :format, :tier, keyword_init: true) do
|
|
26
26
|
def native_stdout? = tier == :native_stdout
|