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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d2aa3cbe98e027e6ed461d3252980ae558778e4df0b2c78f658b848e73b13d8b
|
|
4
|
+
data.tar.gz: 611f238af77124e90cab5844f65be0720898b93469eb7a908d1e82eb4d9a1177
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8b82ef7bdde5d2f8ca978379190effc8730bd6dcb7224207282b9b820d06a2853cc61f87314ad6b8b7a0d81351f3aedd869d1f8449bb6f75e74f83baa56590b8
|
|
7
|
+
data.tar.gz: fe1685b7aad2412ea38090bdc53e350972c25522036330375eba7424457e086057018bad9827c35c1e4e0c65ca48d496bb54e5a8f58f0213668f4609053c7fdd
|
data/README.md
CHANGED
|
@@ -20,6 +20,8 @@ rigor check app lib # find bugs in the code you already have
|
|
|
20
20
|
global `-g` install keeps it off your project's pins. See
|
|
21
21
|
[Get started](#get-started-in-one-prompt).)
|
|
22
22
|
|
|
23
|
+
If your project's bundle also lists `rbs` (directly, or through Steep or `rbs_rails`), the `rbs` that `gem:rigortype` puts on `PATH` can shadow it; see the [install guide's note on `rbs` shadowing](docs/install.md#case-a--mise-is-available-recommended).
|
|
24
|
+
|
|
23
25
|
No annotations required, no runtime dependency, no changes to your
|
|
24
26
|
code — and any RBS you do add, Rigor reads and uses. Rigor parses Ruby
|
|
25
27
|
with
|
|
@@ -131,7 +133,7 @@ and [CI guide](https://rigor.typedduck.fail/manual/11-ci/).
|
|
|
131
133
|
|
|
132
134
|
```sh
|
|
133
135
|
rigor check lib # find bugs (caches under .rigor/ — gitignore it)
|
|
134
|
-
rigor init # drop a starter .rigor.yml
|
|
136
|
+
rigor init # drop a starter .rigor.yml (suggests plugins from Gemfile.lock)
|
|
135
137
|
rigor annotate lib/foo.rb # reprint a file with inferred types in the margin
|
|
136
138
|
rigor triage lib # summarise diagnostics: distribution, hotspots
|
|
137
139
|
rigor sig-gen --diff lib/foo.rb # emit RBS from inference (--write to save)
|
|
@@ -232,7 +234,7 @@ rigor docs --list # list every bundled page
|
|
|
232
234
|
|
|
233
235
|
## Status
|
|
234
236
|
|
|
235
|
-
Current release: **`v0.4.
|
|
237
|
+
Current release: **`v0.4.8`** (2026-11-15) — on the
|
|
236
238
|
`0.4.x` line, continuing the evaluation era opened by `v0.2.0`, the first
|
|
237
239
|
publicly-announced (general / evaluation) release. The line publishes
|
|
238
240
|
an enumerated [compatibility surface](docs/compatibility.md) as a
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Rigor core overlay — supplemental core signatures.
|
|
2
|
+
#
|
|
3
|
+
# --- BigDecimal precision readers (issue #2969) ---
|
|
4
|
+
#
|
|
5
|
+
# rbs 4.2 ships `stdlib/bigdecimal/0/big_decimal.rbs` without `precision`, `scale`,
|
|
6
|
+
# `precision_scale` or `n_significant_digits`, and the bigdecimal gem's own `sig/` (4.1.3)
|
|
7
|
+
# omits them too, so `BigDecimal("1.5").precision` reported `call.undefined-method` on correct code.
|
|
8
|
+
#
|
|
9
|
+
# Upstream: bigdecimal 4.1.3 `ext/bigdecimal/bigdecimal.c` registers the four readers as instance
|
|
10
|
+
# methods (`rb_define_method(rb_cBigDecimal, "precision", ...)`, and likewise for the other three).
|
|
11
|
+
# Their documented results: `precision -> integer` (decimal digits), `scale -> integer`,
|
|
12
|
+
# `precision_scale -> [integer, integer]`, and `n_significant_digits -> integer`.
|
|
13
|
+
#
|
|
14
|
+
# bigdecimal is a bundled gem, not a default library, so this file is gated on it
|
|
15
|
+
# (`Rigor::Environment::RbsLoader::LIBRARY_SUPPLEMENT_CORE_OVERLAYS`). Without the library the file would
|
|
16
|
+
# open a phantom `BigDecimal` that nothing else declares.
|
|
17
|
+
#
|
|
18
|
+
# The methods sit on a module the class includes, not as direct `def`s, so a later rbs or a project
|
|
19
|
+
# `sig/` that declares one of them directly overrides it instead of raising
|
|
20
|
+
# `DuplicatedMethodDefinitionError` (the same shape as `process.rbs` and `ruby41_core_overlay`).
|
|
21
|
+
|
|
22
|
+
module RigorCoreOverlay
|
|
23
|
+
module BigDecimalPrecision
|
|
24
|
+
def precision: () -> Integer
|
|
25
|
+
def scale: () -> Integer
|
|
26
|
+
def precision_scale: () -> [Integer, Integer]
|
|
27
|
+
def n_significant_digits: () -> Integer
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class BigDecimal
|
|
32
|
+
include RigorCoreOverlay::BigDecimalPrecision
|
|
33
|
+
end
|
|
@@ -29,3 +29,33 @@ class Resolv
|
|
|
29
29
|
def initialize: (?(Array[Resolv::Hosts | Resolv::DNS] | Hash[Symbol, untyped])? resolvers, ?use_ipv6: bool?) -> untyped
|
|
30
30
|
| ...
|
|
31
31
|
end
|
|
32
|
+
|
|
33
|
+
# --- Resolv::DNS#getresources / #getresource / #each_resource ---
|
|
34
|
+
#
|
|
35
|
+
# `rbs` declares the three typeclass lookups as answering the base class
|
|
36
|
+
# whatever the typeclass argument names:
|
|
37
|
+
#
|
|
38
|
+
# def getresources: (dns_name name, singleton(Resolv::DNS::Query) typeclass) -> Array[Resolv::DNS::Resource]
|
|
39
|
+
#
|
|
40
|
+
# so `dns.getresources(d, Resolv::DNS::Resource::IN::MX).map(&:exchange)`
|
|
41
|
+
# false-fires `call.undefined-method` (`exchange` is declared on
|
|
42
|
+
# `Resolv::DNS::Resource::MX`, not on `Resource`). At runtime every returned
|
|
43
|
+
# record is an instance of the typeclass (rigortype/rigor#2828).
|
|
44
|
+
#
|
|
45
|
+
# The overlay prepends a generic overload binding `T` from `singleton(T)`, so
|
|
46
|
+
# the answer is `Array[Resolv::DNS::Resource::IN::MX]`. An argument the
|
|
47
|
+
# binder cannot read as a class object under the `Resource` bound leaves `T`
|
|
48
|
+
# unbound, and the base overload (`| ...`) still accepts every `Query`
|
|
49
|
+
# typeclass the upstream signature does.
|
|
50
|
+
class Resolv
|
|
51
|
+
class DNS
|
|
52
|
+
def each_resource: [T < Resolv::DNS::Resource] (Resolv::DNS::dns_name name, singleton(T) typeclass) { (T) -> void } -> void
|
|
53
|
+
| ...
|
|
54
|
+
|
|
55
|
+
def getresource: [T < Resolv::DNS::Resource] (Resolv::DNS::dns_name name, singleton(T) typeclass) -> T
|
|
56
|
+
| ...
|
|
57
|
+
|
|
58
|
+
def getresources: [T < Resolv::DNS::Resource] (Resolv::DNS::dns_name name, singleton(T) typeclass) -> Array[T]
|
|
59
|
+
| ...
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -347,6 +347,35 @@ class Float
|
|
|
347
347
|
def gigabytes: () -> Float
|
|
348
348
|
end
|
|
349
349
|
|
|
350
|
+
# ---------------------------------------------------------------
|
|
351
|
+
# NumericWithFormat — ActiveSupport's `core_ext/numeric/conversions`, included into Integer, Float and
|
|
352
|
+
# BigDecimal. Declared on the module and included, not as a `def` on each class, so a project `sig/` that
|
|
353
|
+
# declares `Integer#to_fs` itself overrides it instead of raising `DuplicatedMethodDefinitionError` (the
|
|
354
|
+
# `process.rbs` shape). Not pure: the Symbol formats read `I18n` for their locale. An Integer or String
|
|
355
|
+
# format is `to_s(format)`, and no format is `to_s`, so every form answers a String. `options` is any
|
|
356
|
+
# Hash-like value: ActiveSupport calls `symbolize_keys` on it, so String keys and a HashWithIndifferentAccess
|
|
357
|
+
# are both valid.
|
|
358
|
+
# ---------------------------------------------------------------
|
|
359
|
+
|
|
360
|
+
module ActiveSupport
|
|
361
|
+
module NumericWithFormat
|
|
362
|
+
def to_fs: (?(Symbol | Integer | String | nil) format, ?Hash[untyped, untyped]? options) -> String
|
|
363
|
+
def to_formatted_s: (?(Symbol | Integer | String | nil) format, ?Hash[untyped, untyped]? options) -> String
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
class Integer
|
|
368
|
+
include ActiveSupport::NumericWithFormat
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
class Float
|
|
372
|
+
include ActiveSupport::NumericWithFormat
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
class BigDecimal
|
|
376
|
+
include ActiveSupport::NumericWithFormat
|
|
377
|
+
end
|
|
378
|
+
|
|
350
379
|
# ---------------------------------------------------------------
|
|
351
380
|
# ActiveSupport::Duration — issue #632
|
|
352
381
|
# ---------------------------------------------------------------
|
|
@@ -898,31 +927,34 @@ end
|
|
|
898
927
|
|
|
899
928
|
class Hash[unchecked out K, unchecked out V]
|
|
900
929
|
# `core_ext/hash/keys`
|
|
901
|
-
|
|
930
|
+
# `key.to_sym rescue key` keeps a key without `to_sym`, so no one key type is right: `Hash[untyped, V]` here,
|
|
931
|
+
# and with the plugin `dynamic_return` hook (#2433) maps each key member where it can.
|
|
932
|
+
def symbolize_keys: () -> Hash[untyped, V]
|
|
902
933
|
def symbolize_keys!: () -> self
|
|
903
934
|
def deep_symbolize_keys: () -> Hash[untyped, untyped]
|
|
904
|
-
def deep_symbolize_keys!: () ->
|
|
935
|
+
def deep_symbolize_keys!: () -> Hash[untyped, untyped]
|
|
905
936
|
def stringify_keys: () -> Hash[String, V]
|
|
906
|
-
def stringify_keys!: () ->
|
|
937
|
+
def stringify_keys!: () -> Hash[String, V]
|
|
907
938
|
def deep_stringify_keys: () -> Hash[untyped, untyped]
|
|
908
|
-
def deep_stringify_keys!: () ->
|
|
939
|
+
def deep_stringify_keys!: () -> Hash[untyped, untyped]
|
|
909
940
|
def assert_valid_keys: (*K | Array[K]) -> self
|
|
910
|
-
def deep_transform_keys: () { (K) ->
|
|
911
|
-
def deep_transform_keys!: () { (K) ->
|
|
941
|
+
def deep_transform_keys: [X] () { (K) -> X } -> Hash[X, untyped]
|
|
942
|
+
def deep_transform_keys!: [X] () { (K) -> X } -> Hash[X, untyped]
|
|
912
943
|
def deep_transform_values: () { (V) -> untyped } -> Hash[K, untyped]
|
|
913
|
-
def deep_transform_values!: () { (V) -> untyped } ->
|
|
944
|
+
def deep_transform_values!: () { (V) -> untyped } -> Hash[K, untyped]
|
|
914
945
|
# `alias_method`s of `symbolize_keys` / `symbolize_keys!`.
|
|
915
|
-
def to_options: () -> Hash[
|
|
946
|
+
def to_options: () -> Hash[untyped, V]
|
|
916
947
|
def to_options!: () -> self
|
|
917
948
|
|
|
918
949
|
# `core_ext/hash/deep_dup`
|
|
919
950
|
def deep_dup: () -> Hash[K, V]
|
|
920
951
|
|
|
921
|
-
# `core_ext/hash/deep_merge`
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
952
|
+
# `core_ext/hash/deep_merge` — the twin of the plugin's rows (#2424 review): the argument's keys join the
|
|
953
|
+
# receiver's, and a nested merge makes a value neither side declares, so values read `untyped`.
|
|
954
|
+
def deep_merge: [A, B] (Hash[A, B] other_hash) -> Hash[K | A, untyped]
|
|
955
|
+
| [A, B] (Hash[A, B] other_hash) { (K | A, untyped, untyped) -> untyped } -> Hash[K | A, untyped]
|
|
956
|
+
def deep_merge!: [A, B] (Hash[A, B] other_hash) -> Hash[K | A, untyped]
|
|
957
|
+
| [A, B] (Hash[A, B] other_hash) { (K | A, untyped, untyped) -> untyped } -> Hash[K | A, untyped]
|
|
926
958
|
# `other.is_a?(Hash)` — the hook `ActiveSupport::DeepMergeable` asks before
|
|
927
959
|
# recursing into a value. `:nodoc:`, but public.
|
|
928
960
|
def deep_merge?: (untyped other) -> bool
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Addressable — `rbs collection` correction overlay (issue #2857).
|
|
2
|
+
#
|
|
3
|
+
# gem_rbs_collection's `gems/addressable/*/addressable.rbs` declares
|
|
4
|
+
# `Addressable::URI.parse` as `(String | URI uri) -> instance`, but
|
|
5
|
+
# `Addressable::URI.parse(nil)` returns nil, so `Addressable::URI.parse(x)`
|
|
6
|
+
# on a `String?` — the mastodon `fetch_link_card_service.rb` shape — drew a
|
|
7
|
+
# false `call.argument-type-mismatch` on correct code.
|
|
8
|
+
#
|
|
9
|
+
# Unlike the activesupport overlay this directory does NOT ride the ADR-72
|
|
10
|
+
# `:missing` gate: it loads only when `rbs collection` supplies the gem's
|
|
11
|
+
# RBS (`:rbs_collection` coverage — `Environment::GEM_OVERLAY_COVERAGE_SOURCES`).
|
|
12
|
+
# The deferred-signature plan (#2422) then composes this declaration over the
|
|
13
|
+
# collection's copy as an overload continuation, so `parse(nil)` binds nil
|
|
14
|
+
# while `parse(String | URI)` keeps the URI answer and a `String?` argument
|
|
15
|
+
# mismatches nothing. Under `:missing` coverage — no sigs at all — the
|
|
16
|
+
# overlay stays unloaded on purpose: this partial `Addressable::URI`
|
|
17
|
+
# declaration would make every member it omits (`host`, `path`, …) a false
|
|
18
|
+
# `call.undefined-method`, which is worse than the `Dynamic` silence a
|
|
19
|
+
# sig-less gem already has.
|
|
20
|
+
module Addressable
|
|
21
|
+
class URI
|
|
22
|
+
# Two arms, URI-carrying first — the order is load-bearing, not cosmetic.
|
|
23
|
+
# `Addressable::URI` is RBS-known but not loadable in the analyzer's host
|
|
24
|
+
# process, so `NilClass`-vs-`Addressable::URI` acceptance answers `maybe`,
|
|
25
|
+
# and the overload selector's strict pass takes the FIRST maybe-match: a
|
|
26
|
+
# leading `(::NilClass)` arm would shadow this one and type
|
|
27
|
+
# `parse(existing_uri)` as `nil`. With the URI arm first it answers `yes`
|
|
28
|
+
# and wins; `nil` still reaches the second arm.
|
|
29
|
+
#
|
|
30
|
+
# `::NilClass`, not the `nil` keyword: they accept the same arguments, but
|
|
31
|
+
# RBS types `nil` as `Types::Bases::Nil`, which the
|
|
32
|
+
# `call.argument-type-mismatch` non-nil channel reads as "undecidable →
|
|
33
|
+
# admits", silently dropping `Addressable::URI.parse(123)`. `NilClass` is
|
|
34
|
+
# a `ClassInstance`, so the channel still refutes what no overload admits.
|
|
35
|
+
#
|
|
36
|
+
# The collection's own `(String | URI uri) -> instance` stays reachable as
|
|
37
|
+
# the `| ...` fallback the deferred plan appends.
|
|
38
|
+
def self.parse: (String | URI uri) -> URI | (::NilClass) -> nil
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -150,7 +150,7 @@ module Bundler
|
|
|
150
150
|
# `#initialize`, `#specs` — declared by `sig/shims/bundler.rbs` with the same types.
|
|
151
151
|
def platforms: () -> Array[untyped]
|
|
152
152
|
def sources: () -> Array[untyped]
|
|
153
|
-
def dependencies: () ->
|
|
153
|
+
def dependencies: () -> Hash[String, Dependency]
|
|
154
154
|
def ruby_version: () -> untyped
|
|
155
155
|
def bundler_version: () -> untyped
|
|
156
156
|
end
|
|
@@ -112,8 +112,9 @@ class Gem::Specification
|
|
|
112
112
|
|
|
113
113
|
# Instance-side surface widely used by bundler / rubygems
|
|
114
114
|
# internals. `attr_accessor` mirrors the writer + reader pair
|
|
115
|
-
# so the survey's `.name=` / `.version=` / `.
|
|
116
|
-
# `.
|
|
115
|
+
# so the survey's `.name=` / `.version=` / `.loaded_from=` /
|
|
116
|
+
# `.post_install_message=` writes resolve too. `.full_gem_path` is declared on `Gem::BasicSpecification`,
|
|
117
|
+
# which this class inherits from.
|
|
117
118
|
def activate: () -> untyped
|
|
118
119
|
def specification_version: () -> Integer
|
|
119
120
|
def files: () -> Array[String]
|
|
@@ -127,13 +128,13 @@ class Gem::Specification
|
|
|
127
128
|
# `#version`'s READER is declared by `sig/shims/rubygems.rbs` (`attr_reader version (): Version`);
|
|
128
129
|
# only the writer is ours.
|
|
129
130
|
def version=: (Gem::Version) -> Gem::Version
|
|
130
|
-
attr_accessor full_gem_path: String
|
|
131
131
|
attr_accessor loaded_from: String?
|
|
132
132
|
attr_accessor post_install_message: String?
|
|
133
133
|
end
|
|
134
134
|
|
|
135
135
|
class Gem::BasicSpecification
|
|
136
136
|
def version: () -> Gem::Version
|
|
137
|
+
attr_accessor full_gem_path: String
|
|
137
138
|
def executables: () -> Array[String]
|
|
138
139
|
def name: () -> String
|
|
139
140
|
def full_name: () -> String
|
|
@@ -59,7 +59,7 @@ mise use gem:rigortype
|
|
|
59
59
|
With mise activated in your shell, `rigor` is on your `PATH`. The
|
|
60
60
|
gem is named `rigortype` (the name `rigor` was taken on RubyGems);
|
|
61
61
|
the executable it installs is `rigor`. If you already have Ruby
|
|
62
|
-
4.0, `gem install rigortype` works too.
|
|
62
|
+
4.0, `gem install rigortype` works too. If the project's bundle lists `rbs`, the `rbs` that `gem:rigortype` puts on `PATH` can shadow it; see the [install guide's note on `rbs` shadowing](../install.md#case-a--mise-is-available-recommended).
|
|
63
63
|
|
|
64
64
|
For shell activation and shims, `asdf`, and developing inside a
|
|
65
65
|
container, see [Installing Rigor](../manual/01-installation.md);
|
|
@@ -283,8 +283,11 @@ If you used the [AI-assisted setup](#the-fast-path-let-an-ai-agent-set-it-up),
|
|
|
283
283
|
the `rigor-project-init` skill already wrote one for you. To
|
|
284
284
|
write a starter by hand, `rigor init` emits `.rigor.dist.yml`
|
|
285
285
|
— the project default that gets committed, with `paths` and a
|
|
286
|
-
`severity_profile` filled in
|
|
287
|
-
|
|
286
|
+
`severity_profile` filled in. When your `Gemfile.lock` declares a
|
|
287
|
+
gem a bundled plugin models, the template suggests that plugin
|
|
288
|
+
under `plugins:`, commented out, for you to enable. `target_ruby`
|
|
289
|
+
is commented out until you set it to your project's Ruby, and the
|
|
290
|
+
rest is commented out too. That is all most projects need; the key
|
|
288
291
|
reference, the JSON-schema editor integration, and `includes:`
|
|
289
292
|
composition are in
|
|
290
293
|
[Configuration](../manual/03-configuration.md).
|
data/docs/handbook/11-sig-gen.md
CHANGED
|
@@ -155,10 +155,41 @@ The `sig.skipped.*` reasons are:
|
|
|
155
155
|
generic by an inline declaration and `sig/` does not declare
|
|
156
156
|
it yet, or names its type parameters otherwise. See
|
|
157
157
|
[Classes made generic inline](#classes-made-generic-inline).
|
|
158
|
+
- `sig.skipped.generic-reopening` — the method's class, or one
|
|
159
|
+
it is nested in, is declared generic by loaded RBS with a
|
|
160
|
+
type parameter that has a bound or a default, and `sig/`
|
|
161
|
+
does not declare it. See
|
|
162
|
+
[Reopening a generic class](#reopening-a-generic-class).
|
|
158
163
|
- `sig.skipped.inline-differs` — the method is declared
|
|
159
164
|
inline and in `sig/`, and the two disagree. A refusal:
|
|
160
165
|
`--write` and `--check` exit `1`. See
|
|
161
166
|
[Methods declared inline](#methods-declared-inline).
|
|
167
|
+
- `sig.skipped.overridden-bot` — the method's body never
|
|
168
|
+
returns (its inferred return is `bot`), and the analysed
|
|
169
|
+
code defines the method again, with `def` or
|
|
170
|
+
`define_method`: in a subclass, signed or not, in a class
|
|
171
|
+
that includes the method's module, in a module included
|
|
172
|
+
later or prepended, or as an extending class's own
|
|
173
|
+
singleton method. `bot` would describe only the base body
|
|
174
|
+
the overrides replace. A class left with nothing to write
|
|
175
|
+
because of this is still written as an empty class, so its
|
|
176
|
+
subclasses keep their signatures, unless your `sig/` or a
|
|
177
|
+
gem's signatures already declare it.
|
|
178
|
+
- `sig.skipped.abstract-method` — the method's inferred return
|
|
179
|
+
is `bot` from an abstract-style raise: `NotImplementedError`,
|
|
180
|
+
an error class named `Abstract…` or `NotImplemented…`, or a
|
|
181
|
+
message that asks for the method to be implemented or
|
|
182
|
+
overridden, or to define it by name ("please define
|
|
183
|
+
about"; not "you must define a block"). The
|
|
184
|
+
implementations may live outside the analysed code, as in a
|
|
185
|
+
plugin gem, so no `bot` is proposed.
|
|
186
|
+
- `sig.skipped.template-method` — the method's inferred return
|
|
187
|
+
is `bot`, its body does not end in a direct `raise`, `fail`,
|
|
188
|
+
`throw`, `exit` or `abort`, and it calls a method the
|
|
189
|
+
analysed code overrides or declares abstract, directly or
|
|
190
|
+
through self-dispatched calls. The call is matched by name,
|
|
191
|
+
whatever the receiver. A `bot` that ends in a direct
|
|
192
|
+
`throw` or a raise nothing overrides is still proposed.
|
|
162
193
|
- `sig.skipped.top-level-def` — a plain top-level `def`, which
|
|
163
194
|
defines a private `Object` method. sig-gen lists it (file,
|
|
164
195
|
method name and this reason in `--format=json`) but writes no
|
|
@@ -180,6 +211,15 @@ The `sig.skipped.*` reasons are:
|
|
|
180
211
|
down with it. The rest of the signatures are unaffected;
|
|
181
212
|
the skipped method is reported on stderr, and it is worth
|
|
182
213
|
reporting to us.
|
|
214
|
+
- `sig.skipped.platform-guarded` — the method is defined in
|
|
215
|
+
a file Ruby loads only under a `RUBY_ENGINE`,
|
|
216
|
+
`RUBY_PLATFORM` or `defined?(…)` require guard (the
|
|
217
|
+
`if RUBY_ENGINE == 'truffleruby'` → `require
|
|
218
|
+
"stackprof/truffleruby"` shape), so it is not an ordinary
|
|
219
|
+
definition for every platform. sig-gen withholds the
|
|
220
|
+
proposal when another scanned file also defines the
|
|
221
|
+
method, or when the inferred return is `bot` — the shape
|
|
222
|
+
a raising stub takes (#3035).
|
|
183
223
|
|
|
184
224
|
### Tighter returns keep the declared parameters
|
|
185
225
|
|
|
@@ -330,10 +370,34 @@ so a return inferred for the new line would describe
|
|
|
330
370
|
parameters that are about to change. Delete the `sig/` member
|
|
331
371
|
and re-run; sig-gen then writes the method afresh.
|
|
332
372
|
|
|
373
|
+
### Reopening a generic class
|
|
374
|
+
|
|
375
|
+
When your code reopens a class that loaded RBS declares
|
|
376
|
+
generic — `class Array`, `class Hash`, a gem's class, or one
|
|
377
|
+
your `sig/` declares — sig-gen writes the header with that
|
|
378
|
+
declaration's type parameters: `class Array[unchecked out E]`.
|
|
379
|
+
rbs rejects a reopening whose parameters differ, so a bare
|
|
380
|
+
`class Array` would fail the class, and every class whose
|
|
381
|
+
signature mentions it, with `GenericParameterMismatchError`.
|
|
382
|
+
The members still say `untyped` for the element type, and a
|
|
383
|
+
class whose name matches a copied parameter is written
|
|
384
|
+
anchored (`::E`), since a bare `E` would name the parameter.
|
|
385
|
+
|
|
386
|
+
The parameters are copied only when every one is plain: a
|
|
387
|
+
name, a variance and `unchecked`. A bound or a default
|
|
388
|
+
(`class Box[T < Comparable]`) is a type written for the
|
|
389
|
+
declaring file's namespace and could mean another class
|
|
390
|
+
where sig-gen writes, so that class's methods, and those of
|
|
391
|
+
classes nested in it, are skipped as
|
|
392
|
+
`sig.skipped.generic-reopening`. Declare the class in `sig/`
|
|
393
|
+
with its parameters and sig-gen writes the members into that
|
|
394
|
+
declaration. A file that already declares the class keeps its
|
|
395
|
+
own header.
|
|
396
|
+
|
|
333
397
|
### Classes made generic inline
|
|
334
398
|
|
|
335
|
-
sig-gen does not
|
|
336
|
-
declared generic inline (`# @rbs generic T`) is therefore not
|
|
399
|
+
sig-gen does not copy type parameters from an inline
|
|
400
|
+
declaration. A class declared generic inline (`# @rbs generic T`) is therefore not
|
|
337
401
|
opened in `sig/`: a header without its parameters would make
|
|
338
402
|
rbs reject the class, and every class whose signature mentions
|
|
339
403
|
it, with `GenericParameterMismatchError`. Its methods, and
|
|
@@ -626,6 +690,24 @@ list is the current state):
|
|
|
626
690
|
are recognised as user-authored and never produce a
|
|
627
691
|
duplicate `def` insertion.
|
|
628
692
|
|
|
693
|
+
Two rules shape the class declarations and type names around
|
|
694
|
+
those methods:
|
|
695
|
+
|
|
696
|
+
- **A subclass of a core or stdlib class** is declared even
|
|
697
|
+
when it has no method of its own to emit, so a method
|
|
698
|
+
returning one resolves: `class MyHash < Hash; end` is
|
|
699
|
+
written `class MyHash < ::Hash[untyped, untyped]`. The
|
|
700
|
+
declaration goes into the file written for its source file,
|
|
701
|
+
so it appears only when that source file has at least one
|
|
702
|
+
method to emit. A class some signature already declares is
|
|
703
|
+
left to that declaration.
|
|
704
|
+
- **A type name a namespace shadows** is written with a
|
|
705
|
+
leading `::`. Inside a `module Foo` that declares a
|
|
706
|
+
`Foo::Set`, a method returning a core `Set` is written
|
|
707
|
+
`-> ::Set[untyped]`, because RBS would read a bare `Set`
|
|
708
|
+
there as `Foo::Set`. Where nothing shadows the name, it is
|
|
709
|
+
written bare as before.
|
|
710
|
+
|
|
629
711
|
Method shapes the generator does **not** cover yet:
|
|
630
712
|
|
|
631
713
|
- `define_method(:name) { ... }`.
|
|
@@ -643,7 +725,7 @@ two are wired today, one is reserved.
|
|
|
643
725
|
| Policy | Behaviour |
|
|
644
726
|
| --- | --- |
|
|
645
727
|
| `untyped` (default) | Every parameter is spelled `untyped`. No inference-derived parameter contract is imposed on future callers. The user retains complete authorship over parameter typing. |
|
|
646
|
-
| `observed` | Collect argument types from every call site under `--observe=PATH...` (defaults to the configured `test_paths:`, or whichever of `spec/` and `test/` exist), union per parameter position, erase to RBS, emit the union. With no test root to observe, or a declared root that does not exist or is not read, sig-gen says so on stderr, and `--format=json` carries the same fact in a top-level `observation` key (below). |
|
|
728
|
+
| `observed` | Collect argument types from every call site under `--observe=PATH...` (defaults to the configured `test_paths:`, or whichever of `spec/` and `test/` exist), union per parameter position, erase to RBS, emit the union. A literal argument is widened to its class first, so `"hello"` proposes `String` (#2254). With no test root to observe, or a declared root that does not exist or is not read, sig-gen says so on stderr, and `--format=json` carries the same fact in a top-level `observation` key (below). |
|
|
647
729
|
| `observed-strict` | Reserved. Will additionally widen to capability roles (`_ToStr`, `_ToS`, …) once the role catalog ships. Currently rejected with a usage error. |
|
|
648
730
|
|
|
649
731
|
Under `--params=observed`, the `--print` / `--diff` JSON payload gains
|
|
@@ -20,7 +20,7 @@ unchanged. This appendix maps the vocabulary.
|
|
|
20
20
|
| Default behaviour | Inference, fall back silent | Inference, fall back silent |
|
|
21
21
|
| "Levels" | 0 – 10 (numeric) | `lenient` / `balanced` / `strict` (named) |
|
|
22
22
|
| Per-rule control | `ignoreErrors:` regex, level demotion | `disable:`, `severity_overrides:` |
|
|
23
|
-
| Baseline | `phpstan-baseline.neon` | `.rigor-baseline.yml` (managed) / `rigor.
|
|
23
|
+
| Baseline | `phpstan-baseline.neon` | `.rigor-baseline.yml` (managed) / `rigor-check.json` (ad-hoc) |
|
|
24
24
|
| Stub format | PHP stub files | RBS files |
|
|
25
25
|
| Custom narrowing | Type-Specifying Extensions | Plugins (Chapter 9) |
|
|
26
26
|
| Custom return shape | Dynamic Return Type Extensions | Plugin `dynamic_return` |
|
|
@@ -140,10 +140,10 @@ severity controls, and includes.
|
|
|
140
140
|
| `ignoreErrors:` (regex / pattern) | `disable:` (rule identifier or wildcard) |
|
|
141
141
|
| `parameters: ignoreErrors:` per-path | `# rigor:disable-file <rule>` at the file head |
|
|
142
142
|
| `includes:` | `includes:` |
|
|
143
|
-
| `phpstan-baseline.neon` | `.rigor-baseline.yml` (managed) — or `rigor.
|
|
144
|
-
| `phpstan analyse --generate-baseline` | `rigor baseline generate` (managed) — or `rigor check --format=json > rigor.
|
|
143
|
+
| `phpstan-baseline.neon` | `.rigor-baseline.yml` (managed) — or `rigor-check.json` (ad-hoc) |
|
|
144
|
+
| `phpstan analyse --generate-baseline` | `rigor baseline generate` (managed) — or `rigor check --format=json > rigor-check.json` (ad-hoc) |
|
|
145
145
|
| `phpstan analyse` | `rigor check` |
|
|
146
|
-
| `phpstan analyse --baseline` | `rigor check` with `baseline: .rigor-baseline.yml` configured (managed) — or `rigor diff rigor.
|
|
146
|
+
| `phpstan analyse --baseline` | `rigor check` with `baseline: .rigor-baseline.yml` configured (managed) — or `rigor diff rigor-check.json` (ad-hoc) |
|
|
147
147
|
| Path resolution: relative to declaring file | Path resolution: relative to declaring file (same rule). |
|
|
148
148
|
|
|
149
149
|
Rigor has two baseline mechanisms: a **managed** baseline
|
data/docs/install.md
CHANGED
|
@@ -109,6 +109,26 @@ A user-wide `~/.config/mise/config.toml` entry for `gem:rigortype`
|
|
|
109
109
|
keeps applying outside this project. Mention it if it names an older
|
|
110
110
|
version, but do not edit global config without the user's consent.
|
|
111
111
|
|
|
112
|
+
`gem:rigortype` also puts an `rbs` on `PATH`: mise wraps every
|
|
113
|
+
executable the gem's dependencies install, and that wrapper runs with
|
|
114
|
+
rigortype's private `GEM_HOME`. When `rbs` is in the project's bundle
|
|
115
|
+
(`Gemfile.lock` lists it, directly or through Steep or `rbs_rails`)
|
|
116
|
+
and the bundle uses the default path, `bundle exec rbs` runs the
|
|
117
|
+
wrapper instead of the project's `rbs`. A git-sourced gem then fails
|
|
118
|
+
with `is not yet checked out` under rigortype's `GEM_HOME`. A bundle
|
|
119
|
+
installed under a configured path such as `vendor/bundle` is not
|
|
120
|
+
affected, because `bundle exec` puts that path's `bin` first. Only
|
|
121
|
+
when `Gemfile.lock` lists `rbs`, run `mise exec -- bundle exec which
|
|
122
|
+
rbs` (the shell you are in has not picked up the new tool yet, so a
|
|
123
|
+
bare `bundle exec which rbs` can miss it). If it prints a path under
|
|
124
|
+
`installs/gem-rigortype/`, tell the user, and tell them the fix is
|
|
125
|
+
local to this checkout: `bundle config set --local path vendor/bundle`
|
|
126
|
+
followed by `bundle install` writes an untracked `.bundle/config`
|
|
127
|
+
(teammates and CI keep the default path), puts the bundle in
|
|
128
|
+
`vendor/`, and makes Rigor read each bundled gem's shipped `sig/`
|
|
129
|
+
(ADR-27). Offer it; do not change the bundle path without their
|
|
130
|
+
consent.
|
|
131
|
+
|
|
112
132
|
Then verify:
|
|
113
133
|
|
|
114
134
|
```sh
|
|
@@ -28,6 +28,14 @@ so nothing is lost by installing it separately.
|
|
|
28
28
|
> [Rails quickstart](14-rails-quickstart.md)). The channels below
|
|
29
29
|
> are the manual route.
|
|
30
30
|
|
|
31
|
+
> **Only trying Rigor in VS Code?** When the
|
|
32
|
+
> [Rigor extension](../../editors/vscode/README.md) finds no `rigor`,
|
|
33
|
+
> it offers to install one into its own storage, using a Ruby 4.0
|
|
34
|
+
> already on the machine (or one `mise install ruby@4.0` provides).
|
|
35
|
+
> That install serves the editor only and is never used for a project
|
|
36
|
+
> that pins `rigortype`; for the command line and CI, use a channel
|
|
37
|
+
> below.
|
|
38
|
+
|
|
31
39
|
### Set up in your language
|
|
32
40
|
|
|
33
41
|
The prompt above is plain natural language — your agent follows the
|
|
@@ -269,6 +277,8 @@ A few things worth knowing if you have not used mise before:
|
|
|
269
277
|
The gem is `rigortype`; the executable it installs (and the only
|
|
270
278
|
command you run) is `rigor`.
|
|
271
279
|
|
|
280
|
+
If the project's bundle lists `rbs`, the `rbs` that `gem:rigortype` puts on `PATH` can shadow the project's own; see the [install guide's note on `rbs` shadowing](../install.md#case-a--mise-is-available-recommended).
|
|
281
|
+
|
|
272
282
|
### Putting `rigor` on your PATH
|
|
273
283
|
|
|
274
284
|
Installing the tool is not enough on its own — `rigor` reaches your
|
|
@@ -356,8 +366,63 @@ gem install rigortype
|
|
|
356
366
|
`asdf` has no general-purpose gem backend, so the gem itself is
|
|
357
367
|
installed with `gem install` rather than an `asdf` command. `mise`
|
|
358
368
|
(above) is the more integrated option because its `gem:` backend
|
|
359
|
-
records the gem in the same config that records Ruby, and — as
|
|
360
|
-
|
|
369
|
+
records the gem in the same config that records Ruby, and — as
|
|
370
|
+
[Simple alternative](#simple-alternative--gem-install) explains —
|
|
371
|
+
keeps the two from interfering.
|
|
372
|
+
|
|
373
|
+
## Secondary — a pinned bundle
|
|
374
|
+
|
|
375
|
+
The rule at the top of this chapter is about your *application's*
|
|
376
|
+
`Gemfile` — the one Bundler resolves against your app's gems, and whose
|
|
377
|
+
entries `Bundler.require` loads at boot. It is not a rule against
|
|
378
|
+
Bundler. A `Gemfile` holding nothing but Rigor, resolved separately and
|
|
379
|
+
selected with `BUNDLE_GEMFILE`, keeps every property the prohibition
|
|
380
|
+
exists to protect: your application's dependency graph never meets
|
|
381
|
+
Rigor's, and your application's Ruby is never constrained by Rigor's.
|
|
382
|
+
|
|
383
|
+
Commit it, with its `Gemfile.lock`, at `.github/rigor/`, the path Rigor's
|
|
384
|
+
CI template uses. The VS Code extension runs it (discovery kind
|
|
385
|
+
`pinned-bundle`, under a Ruby it finds the way it does for its managed
|
|
386
|
+
Rigor, preferring one that matches the lockfile's `RUBY VERSION` or
|
|
387
|
+
the Gemfile's `ruby` line; `rigor.server.bundleGemfile` names another
|
|
388
|
+
location), and never a different Rigor while it pins one.
|
|
389
|
+
`rigor doctor` does not recognise it yet
|
|
390
|
+
([#2751](https://github.com/rigortype/rigor/issues/2751)):
|
|
391
|
+
|
|
392
|
+
```ruby
|
|
393
|
+
# .github/rigor/Gemfile
|
|
394
|
+
source "https://rubygems.org"
|
|
395
|
+
ruby ">= 4.0.0", "< 4.1"
|
|
396
|
+
gem "rigortype", "~> 0.4"
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
Each command has to run under a Ruby 4.0, which is usually not your
|
|
400
|
+
project's Ruby, so select it on the command line:
|
|
401
|
+
|
|
402
|
+
```sh
|
|
403
|
+
# with mise
|
|
404
|
+
BUNDLE_GEMFILE=.github/rigor/Gemfile mise exec ruby@4.0 -- bundle install
|
|
405
|
+
BUNDLE_GEMFILE=.github/rigor/Gemfile mise exec ruby@4.0 -- bundle exec rigor check
|
|
406
|
+
# with rbenv
|
|
407
|
+
BUNDLE_GEMFILE=.github/rigor/Gemfile RBENV_VERSION=4.0.5 bundle exec rigor check
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
A `.ruby-version` inside `.github/rigor/` does not select it, because
|
|
411
|
+
Rigor runs from the project root, and neither does a Bundler binstub,
|
|
412
|
+
whose `#!/usr/bin/env ruby` runs the project's Ruby.
|
|
413
|
+
|
|
414
|
+
The same pin then serves local runs and CI, Dependabot can keep it
|
|
415
|
+
current (see [Pinning Rigor's version](11-ci.md#pinning-rigors-version)
|
|
416
|
+
in the CI chapter), and it is where a third-party Rigor plugin gem
|
|
417
|
+
goes. What it does **not** do is provide Ruby: every `bundle exec`
|
|
418
|
+
must already run under a Ruby 4.0, which the `ruby` line checks. Only
|
|
419
|
+
`rigortype` is pinned exactly; the lockfile records the dependency
|
|
420
|
+
versions Bundler resolved when you installed.
|
|
421
|
+
|
|
422
|
+
It is more moving parts than `mise use --pin gem:rigortype`, which
|
|
423
|
+
records the version and the Ruby in one place and needs no `bundle
|
|
424
|
+
exec`. Reach for it when your team already runs everything through
|
|
425
|
+
Bundler, or needs a plugin gem — not as a first choice.
|
|
361
426
|
|
|
362
427
|
## Simple alternative — gem install
|
|
363
428
|
|
|
@@ -386,30 +451,6 @@ reach it. A `gem install` under a Ruby 4.0 you never switch away from
|
|
|
386
451
|
is perfectly fine; one that shares a Ruby with projects you switch
|
|
387
452
|
between is a footgun.
|
|
388
453
|
|
|
389
|
-
## If you want Bundler to manage the version
|
|
390
|
-
|
|
391
|
-
The rule at the top of this chapter is about your *application's*
|
|
392
|
-
`Gemfile` — the one Bundler resolves against your app's gems, and whose
|
|
393
|
-
entries `Bundler.require` loads at boot. It is not a rule against
|
|
394
|
-
Bundler. A `Gemfile` holding nothing but Rigor, resolved separately and
|
|
395
|
-
selected with `BUNDLE_GEMFILE`, keeps every property the prohibition
|
|
396
|
-
exists to protect: your application's dependency graph never meets
|
|
397
|
-
Rigor's, and your application's Ruby is never constrained by Rigor's.
|
|
398
|
-
|
|
399
|
-
That arrangement — a `Gemfile` under `.github/rigor/`, plus the
|
|
400
|
-
Dependabot config that keeps it current — is written up under
|
|
401
|
-
[Pinning Rigor's version](11-ci.md#pinning-rigors-version) in the CI
|
|
402
|
-
chapter. Nothing about it is CI-specific:
|
|
403
|
-
|
|
404
|
-
```sh
|
|
405
|
-
BUNDLE_GEMFILE=.github/rigor/Gemfile bundle exec rigor check
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
It is more moving parts than `mise use --pin gem:rigortype`, which
|
|
409
|
-
records the same version in one line and needs no `bundle exec`. Reach
|
|
410
|
-
for it when your team already runs everything through Bundler and wants
|
|
411
|
-
Rigor on the same footing — not as a first choice.
|
|
412
|
-
|
|
413
454
|
## Nix
|
|
414
455
|
|
|
415
456
|
If you use Nix, Rigor's flake exposes the executable as a package,
|