rigortype 0.3.8 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/data/capability_roles/capability_roles.rbs +36 -0
- data/data/core_overlay/enumerable.rbs +51 -0
- data/data/core_overlay/enumerator.rbs +84 -0
- data/data/core_overlay/hash_rbs3.rbs +41 -0
- data/data/core_overlay/process.rbs +40 -0
- data/data/core_overlay/string_io.rbs +33 -0
- data/data/effects/core.yml +3 -3
- data/data/gem_overlay/activesupport/core_ext.rbs +236 -17
- data/docs/handbook/02-everyday-types.md +17 -14
- data/docs/handbook/03-narrowing.md +132 -14
- data/docs/handbook/04-tuples-and-shapes.md +8 -6
- data/docs/handbook/05-methods-and-blocks.md +1 -1
- data/docs/handbook/06-classes.md +2 -2
- data/docs/handbook/07-rbs-and-extended.md +19 -1
- data/docs/handbook/10-sorbet.md +9 -10
- data/docs/handbook/11-sig-gen.md +525 -13
- data/docs/handbook/README.md +1 -1
- data/docs/handbook/appendix-elixir.md +2 -2
- data/docs/handbook/appendix-go.md +2 -2
- data/docs/handbook/appendix-java-csharp.md +2 -2
- data/docs/handbook/appendix-mypy.md +2 -2
- data/docs/handbook/appendix-phpstan.md +1 -1
- data/docs/handbook/appendix-rust.md +1 -1
- data/docs/handbook/appendix-type-theory.md +4 -4
- data/docs/handbook/appendix-typescript.md +1 -1
- data/docs/llms.txt +2 -0
- data/docs/manual/02-cli-reference.md +95 -6
- data/docs/manual/03-configuration.md +18 -0
- data/docs/manual/04-diagnostics.md +15 -0
- data/docs/manual/07-plugins.md +15 -5
- data/docs/manual/08-skills.md +23 -2
- data/docs/manual/10-mcp-server.md +3 -2
- data/docs/manual/11-ci.md +9 -0
- data/docs/manual/15-type-protection-coverage.md +8 -0
- data/docs/manual/16-rbs-extended-annotations.md +46 -8
- data/docs/manual/18-removing-dead-code.md +10 -8
- data/docs/manual/19-effect-labels.md +10 -0
- data/docs/manual/plugins/README.md +7 -0
- data/docs/manual/plugins/rigor-actioncable.md +8 -1
- data/docs/manual/plugins/rigor-actionmailer.md +7 -0
- data/docs/manual/plugins/rigor-actionpack.md +261 -0
- data/docs/manual/plugins/rigor-active-model-serializers.md +153 -0
- data/docs/manual/plugins/rigor-activejob.md +7 -0
- data/docs/manual/plugins/rigor-activerecord.md +138 -4
- data/docs/manual/plugins/rigor-activestorage.md +8 -1
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +43 -7
- data/docs/manual/plugins/rigor-grape.md +106 -0
- data/docs/manual/plugins/rigor-graphql.md +23 -2
- data/docs/manual/plugins/rigor-pundit.md +8 -1
- data/docs/manual/plugins/rigor-rails-i18n.md +10 -5
- data/docs/manual/plugins/rigor-rails-routes.md +7 -0
- data/docs/manual/plugins/rigor-rbs-inline.md +229 -1
- data/docs/manual/plugins/rigor-sidekiq.md +8 -1
- data/docs/manual/plugins/rigor-sorbet.md +21 -5
- data/exe/rigor +19 -4
- data/lib/rigor/analysis/baseline.rb +3 -3
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +1 -1
- data/lib/rigor/analysis/check_rules/dead_version_guard_arms.rb +1 -5
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +167 -2
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +10 -2
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +189 -0
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +6 -4
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +15 -6
- data/lib/rigor/analysis/check_rules/rule_ids.rb +21 -6
- data/lib/rigor/analysis/check_rules/rule_walk.rb +41 -5
- data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +1 -1
- data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +1 -1
- data/lib/rigor/analysis/check_rules/source_arity.rb +323 -0
- data/lib/rigor/analysis/check_rules/special_global_setters.rb +146 -0
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +38 -4
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +0 -1
- data/lib/rigor/analysis/check_rules.rb +718 -79
- data/lib/rigor/analysis/crash_signature.rb +8 -24
- data/lib/rigor/analysis/dependency_recorder.rb +23 -0
- data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +1 -1
- data/lib/rigor/analysis/dependency_source_inference/builder.rb +0 -2
- data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +0 -2
- data/lib/rigor/analysis/dependency_source_inference/index.rb +5 -5
- data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +1 -2
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
- data/lib/rigor/analysis/effects_cache_probe.rb +3 -4
- data/lib/rigor/analysis/erb_template_detector.rb +1 -2
- data/lib/rigor/analysis/fact_store.rb +15 -1
- data/lib/rigor/analysis/incremental.rb +42 -0
- data/lib/rigor/analysis/incremental_session.rb +117 -26
- data/lib/rigor/analysis/plugin_fact_fingerprint.rb +0 -1
- data/lib/rigor/analysis/project_scan.rb +11 -1
- data/lib/rigor/analysis/reachability/graph.rb +3 -5
- data/lib/rigor/analysis/reachability/plugin_roots.rb +5 -5
- data/lib/rigor/analysis/reachability/project_files.rb +2 -2
- data/lib/rigor/analysis/reachability/scan.rb +5 -5
- data/lib/rigor/analysis/reachability/scan_cache.rb +3 -2
- data/lib/rigor/analysis/reachability/signature_scan.rb +2 -2
- data/lib/rigor/analysis/result.rb +1 -3
- data/lib/rigor/analysis/rule_catalog.rb +131 -1
- data/lib/rigor/analysis/run_cache_key.rb +21 -12
- data/lib/rigor/analysis/run_cache_probe.rb +3 -5
- data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +6 -8
- data/lib/rigor/analysis/runner/declaration_position.rb +1 -2
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +340 -33
- data/lib/rigor/analysis/runner/effect_annotation_residual_pass.rb +2 -3
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +18 -14
- data/lib/rigor/analysis/runner/pool_coordinator.rb +357 -97
- data/lib/rigor/analysis/runner/project_pre_passes.rb +38 -13
- data/lib/rigor/analysis/runner/run_snapshots.rb +6 -1
- data/lib/rigor/analysis/runner.rb +407 -51
- data/lib/rigor/analysis/template_unit_collector.rb +303 -0
- data/lib/rigor/analysis/template_unit_paths.rb +91 -0
- data/lib/rigor/analysis/template_unit_positions.rb +293 -0
- data/lib/rigor/analysis/template_units.rb +399 -0
- data/lib/rigor/analysis/worker_session.rb +62 -20
- data/lib/rigor/bleeding_edge.rb +10 -24
- data/lib/rigor/builtins/hkt_builtins.rb +3 -2
- data/lib/rigor/builtins/imported_refinements.rb +159 -21
- data/lib/rigor/builtins/predefined_constant_refinements.rb +5 -7
- data/lib/rigor/builtins/regex_refinement.rb +21 -13
- data/lib/rigor/builtins/static_return_refinements.rb +7 -6
- data/lib/rigor/cache/annotation_location.rb +2 -4
- data/lib/rigor/cache/descriptor.rb +63 -20
- data/lib/rigor/cache/engine_source.rb +33 -5
- data/lib/rigor/cache/file_digest.rb +9 -1
- data/lib/rigor/cache/incremental_snapshot.rb +72 -6
- data/lib/rigor/cache/rbs_cache_producer.rb +4 -0
- data/lib/rigor/cache/rbs_class_ancestor_table.rb +0 -3
- data/lib/rigor/cache/rbs_class_type_param_names.rb +0 -3
- data/lib/rigor/cache/rbs_constant_table.rb +0 -3
- data/lib/rigor/cache/rbs_descriptor.rb +112 -14
- data/lib/rigor/cache/rbs_environment.rb +8 -4
- data/lib/rigor/cache/rbs_known_class_names.rb +0 -3
- data/lib/rigor/cache/store.rb +76 -32
- data/lib/rigor/ci_detector.rb +1 -0
- data/lib/rigor/cli/annotate_command.rb +5 -6
- data/lib/rigor/cli/check_command.rb +57 -10
- data/lib/rigor/cli/check_invocation.rb +6 -11
- data/lib/rigor/cli/check_runner_factory.rb +1 -5
- data/lib/rigor/cli/coverage_command.rb +1 -1
- data/lib/rigor/cli/coverage_mutation.rb +12 -3
- data/lib/rigor/cli/coverage_scan.rb +1 -5
- data/lib/rigor/cli/diff_command.rb +1 -1
- data/lib/rigor/cli/doc_links.rb +4 -4
- data/lib/rigor/cli/docs_command.rb +6 -6
- data/lib/rigor/cli/doctor_command.rb +85 -38
- data/lib/rigor/cli/effects_command.rb +2 -2
- data/lib/rigor/cli/effects_diff_renderer.rb +3 -3
- data/lib/rigor/cli/effects_snapshot_command.rb +1 -1
- data/lib/rigor/cli/explain_command.rb +34 -1
- data/lib/rigor/cli/fused_protection_report.rb +7 -1
- data/lib/rigor/cli/lsp_command.rb +1 -1
- data/lib/rigor/cli/mcp_command.rb +1 -1
- data/lib/rigor/cli/measurement_integrity_warning.rb +4 -5
- data/lib/rigor/cli/mutation_fork_scan.rb +6 -6
- data/lib/rigor/cli/mutation_protection_report.rb +7 -1
- data/lib/rigor/cli/plugin_command.rb +4 -4
- data/lib/rigor/cli/plugins_command.rb +2 -1
- data/lib/rigor/cli/prism_colorizer.rb +1 -2
- data/lib/rigor/cli/protection_fork_scan.rb +6 -6
- data/lib/rigor/cli/show_bleedingedge_command.rb +1 -1
- data/lib/rigor/cli/sig_gen_command.rb +212 -31
- data/lib/rigor/cli/skill_command.rb +2 -2
- data/lib/rigor/cli/skill_deep_probe.rb +4 -4
- data/lib/rigor/cli/skill_describe.rb +35 -35
- data/lib/rigor/cli/trace_command.rb +4 -4
- data/lib/rigor/cli/trace_renderer.rb +5 -6
- data/lib/rigor/cli/triage_command.rb +1 -1
- data/lib/rigor/cli/type_of_command.rb +29 -11
- data/lib/rigor/cli/type_of_renderer.rb +20 -9
- data/lib/rigor/cli/type_of_template_probe.rb +189 -0
- data/lib/rigor/cli/type_scan_command.rb +4 -4
- data/lib/rigor/cli/unused_command.rb +11 -3
- data/lib/rigor/cli/upgrade_command.rb +1 -1
- data/lib/rigor/cli.rb +89 -9
- data/lib/rigor/config_audit.rb +30 -5
- data/lib/rigor/configuration/severity_profile.rb +25 -9
- data/lib/rigor/configuration.rb +109 -7
- data/lib/rigor/effects/ancestry_recorder.rb +191 -0
- data/lib/rigor/effects/attribution.rb +12 -5
- data/lib/rigor/effects/callee_rule.rb +368 -0
- data/lib/rigor/effects/catalog.rb +7 -4
- data/lib/rigor/effects/collector.rb +11 -5
- data/lib/rigor/effects/config_envelopes.rb +15 -10
- data/lib/rigor/effects/definition_context.rb +179 -0
- data/lib/rigor/effects/definition_lines.rb +25 -6
- data/lib/rigor/effects/effect_table.rb +11 -4
- data/lib/rigor/effects/entry_points.rb +0 -2
- data/lib/rigor/effects/envelope_check.rb +9 -9
- data/lib/rigor/effects/envelope_index.rb +20 -8
- data/lib/rigor/effects/file_collection.rb +59 -5
- data/lib/rigor/effects/framework_units.rb +5 -7
- data/lib/rigor/effects/identity.rb +20 -6
- data/lib/rigor/effects/inline_anchor.rb +7 -7
- data/lib/rigor/effects/label_intent.rb +3 -4
- data/lib/rigor/effects/liskov_check.rb +8 -8
- data/lib/rigor/effects/local_ownership.rb +38 -12
- data/lib/rigor/effects/method_key.rb +22 -1
- data/lib/rigor/effects/mutation_classifier.rb +23 -12
- data/lib/rigor/effects/plugin_facts.rb +47 -37
- data/lib/rigor/effects/propagator.rb +297 -19
- data/lib/rigor/effects/registry.rb +1 -1
- data/lib/rigor/effects/scanner.rb +122 -73
- data/lib/rigor/effects/signature_sources.rb +4 -6
- data/lib/rigor/effects/snapshot.rb +12 -11
- data/lib/rigor/effects/snapshot_diff.rb +1 -1
- data/lib/rigor/effects/summary.rb +27 -4
- data/lib/rigor/effects/unit_scan.rb +393 -38
- data/lib/rigor/effects/unknown_label_check.rb +3 -8
- data/lib/rigor/effects/unknown_label_report.rb +3 -4
- data/lib/rigor/effects/visibility.rb +101 -0
- data/lib/rigor/environment/bundle_sig_discovery.rb +6 -6
- data/lib/rigor/environment/class_registry.rb +3 -1
- data/lib/rigor/environment/failure_slot.rb +2 -2
- data/lib/rigor/environment/installed_gem_set.rb +85 -0
- data/lib/rigor/environment/lockfile_resolver.rb +68 -4
- data/lib/rigor/environment/member_consistency/comparator.rb +708 -0
- data/lib/rigor/environment/member_consistency.rb +298 -0
- data/lib/rigor/environment/missing_gem_constant_index.rb +4 -4
- data/lib/rigor/environment/rbs_collection_discovery.rb +5 -5
- data/lib/rigor/environment/rbs_coverage_report.rb +5 -5
- data/lib/rigor/environment/rbs_hierarchy.rb +3 -1
- data/lib/rigor/environment/rbs_loader.rb +674 -79
- data/lib/rigor/environment.rb +174 -24
- data/lib/rigor/flow_contribution/merger.rb +0 -2
- data/lib/rigor/flow_contribution.rb +11 -13
- data/lib/rigor/hashing/xxh3.rb +264 -0
- data/lib/rigor/inference/acceptance.rb +292 -17
- data/lib/rigor/inference/block_auto_splat.rb +216 -0
- data/lib/rigor/inference/block_call_timing.rb +338 -0
- data/lib/rigor/inference/block_parameter_binder.rb +75 -30
- data/lib/rigor/inference/block_repetition.rb +71 -0
- data/lib/rigor/inference/body_fixpoint.rb +7 -6
- data/lib/rigor/inference/budget_trace.rb +3 -6
- data/lib/rigor/inference/builtins/method_catalog.rb +2 -1
- data/lib/rigor/inference/builtins/string_catalog.rb +1 -1
- data/lib/rigor/inference/captured_locals.rb +389 -18
- data/lib/rigor/inference/closure_escape_analyzer.rb +159 -17
- data/lib/rigor/inference/content_join.rb +200 -27
- data/lib/rigor/inference/coverage_scanner.rb +4 -6
- data/lib/rigor/inference/def_return_typer.rb +11 -7
- data/lib/rigor/inference/define_method_block_self.rb +64 -0
- data/lib/rigor/inference/dynamic_origin.rb +1 -1
- data/lib/rigor/inference/element_read_widening.rb +180 -0
- data/lib/rigor/inference/error_info.rb +196 -0
- data/lib/rigor/inference/expression_typer.rb +2124 -468
- data/lib/rigor/inference/external_ancestor_resolution.rb +267 -0
- data/lib/rigor/inference/fork_map.rb +5 -7
- data/lib/rigor/inference/fresh_frame_blocks.rb +127 -0
- data/lib/rigor/inference/global_write_census.rb +239 -0
- data/lib/rigor/inference/guard_rebinding.rb +447 -0
- data/lib/rigor/inference/hash_lookup_mutation.rb +88 -0
- data/lib/rigor/inference/hkt_reducer.rb +2 -3
- data/lib/rigor/inference/hkt_registry.rb +4 -7
- data/lib/rigor/inference/index_write_widening.rb +16 -7
- data/lib/rigor/inference/indexed_narrowing.rb +61 -9
- data/lib/rigor/inference/jump_targets.rb +82 -0
- data/lib/rigor/inference/last_line/implicit_self.rb +210 -0
- data/lib/rigor/inference/last_line/self_evidence.rb +329 -0
- data/lib/rigor/inference/last_line.rb +340 -0
- data/lib/rigor/inference/last_status.rb +144 -0
- data/lib/rigor/inference/macro_block_self_type.rb +168 -21
- data/lib/rigor/inference/match_rebinding/calls.rb +281 -0
- data/lib/rigor/inference/match_rebinding/frame.rb +148 -0
- data/lib/rigor/inference/match_rebinding/operands.rb +236 -0
- data/lib/rigor/inference/match_rebinding/self_calls.rb +83 -0
- data/lib/rigor/inference/match_rebinding.rb +392 -0
- data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +36 -0
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +87 -33
- data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +305 -19
- data/lib/rigor/inference/method_dispatcher/data_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +147 -0
- data/lib/rigor/inference/method_dispatcher/file_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/hash_transform_keys_folding.rb +191 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +6 -2
- data/lib/rigor/inference/method_dispatcher/json_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +7 -1
- data/lib/rigor/inference/method_dispatcher/match_data_folding.rb +159 -0
- data/lib/rigor/inference/method_dispatcher/math_folding.rb +41 -3
- data/lib/rigor/inference/method_dispatcher/method_folding.rb +2 -5
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +165 -111
- data/lib/rigor/inference/method_dispatcher/process_folding.rb +56 -0
- data/lib/rigor/inference/method_dispatcher/proven_overload.rb +72 -0
- data/lib/rigor/inference/method_dispatcher/random_folding.rb +82 -0
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +1046 -69
- data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +25 -4
- data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +2 -8
- data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/self_substitute.rb +142 -0
- data/lib/rigor/inference/method_dispatcher/set_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +129 -54
- data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +1 -2
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -6
- data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +85 -4
- data/lib/rigor/inference/method_dispatcher/time_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/universal_object_dispatch.rb +1 -2
- data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher.rb +225 -25
- data/lib/rigor/inference/method_parameter_binder.rb +12 -9
- data/lib/rigor/inference/multi_target_binder.rb +341 -55
- data/lib/rigor/inference/mutation_rejoin.rb +171 -0
- data/lib/rigor/inference/mutation_widening.rb +156 -85
- data/lib/rigor/inference/narrowing.rb +835 -162
- data/lib/rigor/inference/operand_effects.rb +167 -0
- data/lib/rigor/inference/operand_walk.rb +88 -0
- data/lib/rigor/inference/optimistic_origin.rb +153 -16
- data/lib/rigor/inference/origin_lookup.rb +2 -3
- data/lib/rigor/inference/parameter_inference_collector.rb +7 -7
- data/lib/rigor/inference/pre_eval_constants.rb +6 -5
- data/lib/rigor/inference/precision_scanner.rb +3 -4
- data/lib/rigor/inference/project_method_ownership.rb +136 -0
- data/lib/rigor/inference/project_patched_methods.rb +9 -4
- data/lib/rigor/inference/project_patched_scanner.rb +10 -6
- data/lib/rigor/inference/protection_scanner.rb +1 -2
- data/lib/rigor/inference/range_constant.rb +57 -0
- data/lib/rigor/inference/rbs_type_translator.rb +49 -11
- data/lib/rigor/inference/receiver_alias.rb +93 -4
- data/lib/rigor/inference/receiver_blind_block.rb +219 -0
- data/lib/rigor/inference/refinement_mutation.rb +76 -0
- data/lib/rigor/inference/repeated_or_writes.rb +463 -0
- data/lib/rigor/inference/return_barrier.rb +54 -0
- data/lib/rigor/inference/rewrite_mutation.rb +120 -0
- data/lib/rigor/inference/scope_indexer.rb +5228 -627
- data/lib/rigor/inference/statement_evaluator.rb +3452 -595
- data/lib/rigor/inference/stored_block_call.rb +54 -0
- data/lib/rigor/inference/string_mutation.rb +97 -0
- data/lib/rigor/inference/struct_fold_safety.rb +6 -7
- data/lib/rigor/inference/synthetic_method_index.rb +1 -2
- data/lib/rigor/inference/synthetic_method_scanner.rb +4 -6
- data/lib/rigor/inference/unknown_store_widening.rb +200 -0
- data/lib/rigor/inference/unthreaded_rebinds.rb +282 -0
- data/lib/rigor/inference/version_guard.rb +28 -21
- data/lib/rigor/inference/void_origin.rb +3 -3
- data/lib/rigor/inference/void_tail_summary.rb +2 -4
- data/lib/rigor/language_server/buffer_table.rb +4 -4
- data/lib/rigor/language_server/completion_provider.rb +1 -1
- data/lib/rigor/language_server/debouncer.rb +0 -1
- data/lib/rigor/language_server/diagnostic_publisher.rb +7 -6
- data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
- data/lib/rigor/language_server/folding_range_provider.rb +1 -1
- data/lib/rigor/language_server/hover_provider.rb +1 -1
- data/lib/rigor/language_server/hover_renderer.rb +4 -4
- data/lib/rigor/language_server/incremental_sync.rb +6 -6
- data/lib/rigor/language_server/project_context.rb +7 -8
- data/lib/rigor/language_server/publish_batcher.rb +2 -2
- data/lib/rigor/language_server/selection_range_provider.rb +2 -2
- data/lib/rigor/language_server/server.rb +9 -9
- data/lib/rigor/language_server/signature_help_provider.rb +1 -1
- data/lib/rigor/language_server/uri.rb +1 -1
- data/lib/rigor/mcp/server.rb +2 -1
- data/lib/rigor/plugin/base.rb +258 -26
- data/lib/rigor/plugin/box_probe.rb +91 -0
- data/lib/rigor/plugin/bundled_catalog.rb +167 -0
- data/lib/rigor/plugin/effect_attribution.rb +65 -11
- data/lib/rigor/plugin/effect_entry_points.rb +3 -3
- data/lib/rigor/plugin/fact_store.rb +6 -6
- data/lib/rigor/plugin/io_boundary.rb +93 -8
- data/lib/rigor/plugin/isolation.rb +29 -6
- data/lib/rigor/plugin/loader.rb +33 -13
- data/lib/rigor/plugin/macro/block_as_method.rb +45 -6
- data/lib/rigor/plugin/macro/heredoc_template.rb +1 -1
- data/lib/rigor/plugin/macro/trait_registry.rb +1 -1
- data/lib/rigor/plugin/manifest.rb +94 -11
- data/lib/rigor/plugin/registry.rb +76 -12
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +21 -4
- data/lib/rigor/plugin/template_unit.rb +196 -0
- data/lib/rigor/plugin/trust_policy.rb +2 -4
- data/lib/rigor/plugin/type_node_resolver.rb +3 -3
- data/lib/rigor/plugin.rb +1 -0
- data/lib/rigor/plugin_gap_advisory.rb +96 -0
- data/lib/rigor/project_environment.rb +138 -0
- data/lib/rigor/protection/analysis_guard.rb +93 -14
- data/lib/rigor/protection/closure_kill_oracle.rb +67 -23
- data/lib/rigor/protection/dependency_closure.rb +5 -8
- data/lib/rigor/protection/diagnostic_oracle.rb +2 -2
- data/lib/rigor/protection/discovery_seed.rb +14 -12
- data/lib/rigor/protection/kill_signature.rb +1 -4
- data/lib/rigor/protection/measurement_integrity.rb +1 -3
- data/lib/rigor/protection/mutation_cache.rb +7 -11
- data/lib/rigor/protection/mutation_scanner.rb +12 -15
- data/lib/rigor/protection/mutator.rb +2 -1
- data/lib/rigor/protection/test_suite_oracle.rb +5 -5
- data/lib/rigor/rbs_extended/conformance_checker.rb +4 -3
- data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
- data/lib/rigor/rbs_extended/reporter.rb +36 -10
- data/lib/rigor/rbs_extended.rb +88 -21
- data/lib/rigor/reflection/constant_ancestors.rb +97 -0
- data/lib/rigor/reflection/constant_path.rb +139 -0
- data/lib/rigor/reflection.rb +93 -110
- data/lib/rigor/runtime/jit.rb +6 -8
- data/lib/rigor/scope/discovery_index.rb +165 -2
- data/lib/rigor/scope.rb +1041 -32
- data/lib/rigor/sig_gen/alias_index.rb +289 -0
- data/lib/rigor/sig_gen/classification.rb +22 -5
- data/lib/rigor/sig_gen/declaration_equivalence.rb +127 -0
- data/lib/rigor/sig_gen/effect_annotation.rb +202 -0
- data/lib/rigor/sig_gen/generator.rb +673 -53
- data/lib/rigor/sig_gen/inline_declarations.rb +184 -0
- data/lib/rigor/sig_gen/layout_index.rb +3 -4
- data/lib/rigor/sig_gen/meta_class_shape.rb +3 -5
- data/lib/rigor/sig_gen/method_candidate.rb +47 -3
- data/lib/rigor/sig_gen/observation_collector.rb +18 -16
- data/lib/rigor/sig_gen/path_mapper.rb +4 -6
- data/lib/rigor/sig_gen/rbs_validity.rb +4 -4
- data/lib/rigor/sig_gen/renderer.rb +128 -14
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +154 -0
- data/lib/rigor/sig_gen/superclass_spelling.rb +27 -0
- data/lib/rigor/sig_gen/type_elaborator.rb +1 -3
- data/lib/rigor/sig_gen/write_result.rb +19 -3
- data/lib/rigor/sig_gen/writer.rb +189 -41
- data/lib/rigor/sig_gen.rb +3 -0
- data/lib/rigor/signature_path_audit.rb +153 -6
- data/lib/rigor/source/literals.rb +0 -23
- data/lib/rigor/source/node_children.rb +0 -2
- data/lib/rigor/source/node_locator.rb +5 -11
- data/lib/rigor/source/node_walker.rb +0 -6
- data/lib/rigor/source/parameter_envelope.rb +72 -0
- data/lib/rigor/source.rb +1 -0
- data/lib/rigor/triage/catalogue.rb +1 -3
- data/lib/rigor/triage.rb +3 -5
- data/lib/rigor/type/accepts_result.rb +24 -6
- data/lib/rigor/type/combinator.rb +144 -5
- data/lib/rigor/type/data_class.rb +2 -2
- data/lib/rigor/type/data_instance.rb +4 -4
- data/lib/rigor/type/difference.rb +1 -0
- data/lib/rigor/type/float_range.rb +128 -0
- data/lib/rigor/type/hash_shape.rb +6 -6
- data/lib/rigor/type/integer_range.rb +13 -8
- data/lib/rigor/type/nominal.rb +8 -2
- data/lib/rigor/type/refined.rb +4 -3
- data/lib/rigor/type/struct_class.rb +3 -3
- data/lib/rigor/type/struct_instance.rb +4 -4
- data/lib/rigor/type.rb +1 -0
- data/lib/rigor/type_node/generic.rb +1 -1
- data/lib/rigor/type_node/range_literal.rb +25 -0
- data/lib/rigor/type_node/resolver_chain.rb +1 -1
- data/lib/rigor/type_node.rb +1 -0
- data/lib/rigor/version.rb +1 -1
- data/lib/rigor.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +0 -4
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +0 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +0 -2
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/effects.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +10 -5
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +0 -4
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +3 -5
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +1 -4
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +14 -4
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +32 -30
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +0 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -3
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +96 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/effects.rb +65 -8
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +270 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/render_locals.rb +402 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +370 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_units.rb +132 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +264 -3
- data/plugins/rigor-actionpack/sig/action_controller.rbs +71 -0
- data/plugins/rigor-actionpack/sig/action_view.rbs +43 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_discoverer.rb +220 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_index.rb +56 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +263 -0
- data/plugins/rigor-active-model-serializers/lib/rigor-active-model-serializers.rb +7 -0
- data/plugins/rigor-active-model-serializers/sig/active_model_serializers.rbs +45 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +0 -4
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +2 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +0 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +0 -2
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/recurring_scan.rb +1 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +10 -5
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +35 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +72 -12
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +383 -7
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +14 -6
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +1 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +1 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +322 -41
- data/plugins/rigor-activerecord/sig/active_record/framework.rbs +123 -0
- data/plugins/rigor-activerecord/sig/active_record/relation.rbs +206 -31
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +26 -14
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +9 -2
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +9 -2
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +290 -19
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +1 -0
- data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +3 -0
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +9 -7
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +7 -3
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +1 -0
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +8 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +11 -7
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -11
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +9 -4
- data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +2 -0
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +0 -5
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +0 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +0 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +8 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/types.rb +1 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +36 -4
- data/plugins/rigor-ffi-rzmq/lib/rigor/plugin/ffi_rzmq.rb +1 -0
- data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +141 -0
- data/plugins/rigor-grape/lib/rigor-grape.rb +6 -0
- data/plugins/rigor-grape/sig/grape.rbs +263 -0
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +8 -6
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +78 -5
- data/plugins/rigor-graphql/sig/graphql.rbs +485 -0
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +1 -0
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +2 -1
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +2 -3
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +1 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +0 -5
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/authorization_scan.rb +2 -2
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +0 -1
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +0 -1
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +12 -7
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +0 -12
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +1 -3
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +0 -1
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +36 -37
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/acronyms.rb +5 -5
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +0 -10
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +5 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +3 -2
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/grape_api_discoverer.rb +2 -2
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +2 -2
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +9 -10
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +2 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +10 -17
- data/plugins/rigor-railties/lib/rigor/plugin/railties.rb +1 -0
- data/plugins/rigor-rbnacl/lib/rigor/plugin/rbnacl.rb +13 -1
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline/same_line_annotations.rb +149 -0
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +324 -18
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +0 -3
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +0 -3
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +1 -5
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +2 -3
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +1 -0
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +0 -3
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +1 -0
- data/plugins/rigor-sassc/lib/rigor/plugin/sassc.rb +1 -0
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +1 -9
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +1 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +0 -4
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/effects.rb +1 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/schedule_scan.rb +2 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +0 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +0 -2
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +10 -5
- data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +1 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +2 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +1 -4
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +3 -9
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +4 -4
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +1 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +3 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +7 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +51 -6
- data/plugins/rigor-sorbet/sig/sorbet.rbs +277 -0
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +1 -0
- data/sig/rigor/analysis/baseline.rbs +69 -7
- data/sig/rigor/analysis/fact_store.rbs +1 -1
- data/sig/rigor/analysis/project_scan.rbs +74 -0
- data/sig/rigor/analysis/reachability/scan_cache.rbs +12 -0
- data/sig/rigor/cache.rbs +2 -3
- data/sig/rigor/effects/config_envelopes.rbs +100 -0
- data/sig/rigor/effects/effect_table.rbs +60 -0
- data/sig/rigor/effects/envelope.rbs +97 -0
- data/sig/rigor/effects/envelope_index.rbs +33 -0
- data/sig/rigor/effects/file_collection.rbs +81 -0
- data/sig/rigor/effects/label.rbs +26 -0
- data/sig/rigor/effects/label_set.rbs +46 -0
- data/sig/rigor/effects/method_key.rbs +24 -0
- data/sig/rigor/effects/origin.rbs +50 -0
- data/sig/rigor/effects/plugin_facts.rbs +141 -0
- data/sig/rigor/effects/registry.rbs +68 -0
- data/sig/rigor/effects/summary.rbs +50 -0
- data/sig/rigor/effects/taint_cause.rbs +12 -0
- data/sig/rigor/environment.rbs +17 -10
- data/sig/rigor/inference/optimistic_origin.rbs +10 -0
- data/sig/rigor/inference.rbs +9 -14
- data/sig/rigor/plugin/additional_initializer.rbs +36 -0
- data/sig/rigor/plugin/base.rbs +30 -7
- data/sig/rigor/plugin/effect_ancestry.rbs +27 -0
- data/sig/rigor/plugin/effect_attribution.rbs +66 -0
- data/sig/rigor/plugin/effect_edge.rbs +33 -0
- data/sig/rigor/plugin/effect_entry_points.rbs +25 -0
- data/sig/rigor/plugin/io_boundary.rbs +4 -0
- data/sig/rigor/plugin/loader.rbs +3 -3
- data/sig/rigor/plugin/manifest.rbs +51 -11
- data/sig/rigor/plugin/protocol_contract.rbs +68 -0
- data/sig/rigor/plugin/registry.rbs +62 -1
- data/sig/rigor/plugin.rbs +1 -1
- data/sig/rigor/rbs_extended.rbs +1 -1
- data/sig/rigor/reflection.rbs +9 -6
- data/sig/rigor/scope.rbs +148 -12
- data/sig/rigor/sig_gen/skip_reason_catalog.rbs +21 -0
- data/sig/rigor/source.rbs +4 -4
- data/sig/rigor/testing.rbs +10 -4
- data/sig/rigor/type.rbs +33 -1
- data/sig/rigor.rbs +39 -20
- data/skills/rigor-ask/SKILL.md +16 -11
- data/skills/rigor-baseline-reduce/SKILL.md +4 -6
- data/skills/rigor-ci-setup/SKILL.md +17 -21
- data/skills/rigor-doctor/SKILL.md +24 -22
- data/skills/rigor-doctor/references/01-checks.md +97 -33
- data/skills/rigor-editor-setup/SKILL.md +6 -4
- data/skills/rigor-mcp-setup/SKILL.md +5 -4
- data/skills/rigor-monkeypatch-resolve/SKILL.md +5 -3
- data/skills/rigor-next-steps/SKILL.md +4 -2
- data/skills/rigor-plugin-author/SKILL.md +19 -23
- data/skills/rigor-plugin-author/references/01-plan-and-scaffold.md +9 -8
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +25 -27
- data/skills/rigor-plugin-author/references/03-test-and-ship.md +6 -8
- data/skills/rigor-plugin-review/SKILL.md +6 -4
- data/skills/rigor-plugin-review/references/01-best-practices-checklist.md +2 -1
- data/skills/rigor-plugin-tune/SKILL.md +4 -2
- data/skills/rigor-project-init/SKILL.md +15 -10
- data/skills/rigor-project-init/references/01-detect.md +13 -9
- data/skills/rigor-project-init/references/02-configure.md +43 -14
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +14 -14
- data/skills/rigor-project-init/references/04-sig-uplift.md +27 -14
- data/skills/rigor-project-init/references/06-agent-contract.md +67 -0
- data/skills/rigor-protection-uplift/SKILL.md +4 -6
- data/skills/rigor-rbs-setup/SKILL.md +4 -2
- data/skills/rigor-type-oracle/SKILL.md +226 -0
- data/skills/rigor-type-oracle/references/01-oracle-commands.md +265 -0
- data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +52 -0
- data/skills/rigor-type-oracle/references/03-gap-protocol.md +125 -0
- data/skills/rigor-unused-adjudicate/SKILL.md +12 -7
- data/skills/rigor-upgrade/SKILL.md +13 -8
- metadata +133 -3
- data/lib/rigor/cli/probe_environment.rb +0 -85
- data/sig/rigor/inference/builtins/numeric_catalog.rbs +0 -3
data/lib/rigor/bleeding_edge.rb
CHANGED
|
@@ -51,14 +51,14 @@ module Rigor
|
|
|
51
51
|
# migration note and a user's `bleeding_edge:` list both key on.
|
|
52
52
|
#
|
|
53
53
|
# @!attribute id
|
|
54
|
-
# @return
|
|
54
|
+
# @return the stable feature id (contract vocabulary).
|
|
55
55
|
# @!attribute summary
|
|
56
|
-
# @return
|
|
56
|
+
# @return a one-line description of what it changes. For a `:behaviour`
|
|
57
57
|
# feature this is the *whole* explanation — there is no severity diff to read.
|
|
58
58
|
# @!attribute kind
|
|
59
|
-
# @return
|
|
59
|
+
# @return one of {KINDS}.
|
|
60
60
|
# @!attribute severity_overrides
|
|
61
|
-
# @return
|
|
61
|
+
# @return canonical rule id → the severity this feature
|
|
62
62
|
# imposes. Composed *below* the user's own `severity_overrides:` and *above* the
|
|
63
63
|
# active `severity_profile` (see {Configuration::SeverityProfile.resolve}). Empty for
|
|
64
64
|
# a `:behaviour` feature.
|
|
@@ -76,12 +76,10 @@ module Rigor
|
|
|
76
76
|
super
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
# @return [Boolean]
|
|
80
79
|
def severity?
|
|
81
80
|
kind == :severity
|
|
82
81
|
end
|
|
83
82
|
|
|
84
|
-
# @return [Boolean]
|
|
85
83
|
def behaviour?
|
|
86
84
|
kind == :behaviour
|
|
87
85
|
end
|
|
@@ -193,36 +191,28 @@ module Rigor
|
|
|
193
191
|
# cleanup can lag graduation by as many releases as it takes. The id also stays in the
|
|
194
192
|
# contract vocabulary the CHANGELOG migration note keys on. Entries are removed only once
|
|
195
193
|
# no call site names them.
|
|
196
|
-
#
|
|
197
|
-
# @return [Array<String>]
|
|
198
194
|
GRADUATED = [].freeze
|
|
199
195
|
|
|
200
196
|
module_function
|
|
201
197
|
|
|
202
|
-
# @return [Array<Feature>] the whole overlay.
|
|
203
198
|
def features
|
|
204
199
|
FEATURES
|
|
205
200
|
end
|
|
206
201
|
|
|
207
|
-
# @return [Array<String>] every feature id in the overlay.
|
|
208
202
|
def feature_ids
|
|
209
203
|
FEATURES.map(&:id)
|
|
210
204
|
end
|
|
211
205
|
|
|
212
|
-
# @param id [String]
|
|
213
|
-
# @return [Feature, nil]
|
|
214
206
|
def feature(id)
|
|
215
207
|
FEATURES.find { |f| f.id == id }
|
|
216
208
|
end
|
|
217
209
|
|
|
218
|
-
# @
|
|
219
|
-
# @return [Boolean] whether the id has graduated to default-on ({GRADUATED}).
|
|
210
|
+
# @return whether the id has graduated to default-on ({GRADUATED}).
|
|
220
211
|
def graduated?(id)
|
|
221
212
|
GRADUATED.include?(id)
|
|
222
213
|
end
|
|
223
214
|
|
|
224
|
-
# @
|
|
225
|
-
# @return [Boolean] whether the id names a feature this gem knows at all — queued or
|
|
215
|
+
# @return whether the id names a feature this gem knows at all — queued or
|
|
226
216
|
# graduated. Distinct from "adopted"; see {Configuration#bleeding_edge_active?}.
|
|
227
217
|
def known_id?(id)
|
|
228
218
|
graduated?(id) || FEATURES.any? { |f| f.id == id }
|
|
@@ -234,10 +224,9 @@ module Rigor
|
|
|
234
224
|
# `severity_overrides:` keeps an unknown rule id inert until it lands (robust across gem
|
|
235
225
|
# versions).
|
|
236
226
|
#
|
|
237
|
-
# @param selector
|
|
227
|
+
# @param selector — `{ "mode" => "none" }`,
|
|
238
228
|
# `{ "mode" => "all" }`, `{ "mode" => "all", "except" => [ids] }`,
|
|
239
229
|
# or `{ "mode" => "list", "ids" => [ids] }`.
|
|
240
|
-
# @return [Array<Feature>]
|
|
241
230
|
def active_features(selector)
|
|
242
231
|
case selector["mode"]
|
|
243
232
|
when "all"
|
|
@@ -254,8 +243,7 @@ module Rigor
|
|
|
254
243
|
# The merged severity-override map the active features impose for a selector. Frozen so
|
|
255
244
|
# the result is `Ractor.shareable?`.
|
|
256
245
|
#
|
|
257
|
-
# @param selector
|
|
258
|
-
# @return [Hash{String => Symbol}]
|
|
246
|
+
# @param selector — see {#active_features}.
|
|
259
247
|
def severity_overrides_for(selector)
|
|
260
248
|
active_features(selector).each_with_object({}) do |feature, acc|
|
|
261
249
|
acc.merge!(feature.severity_overrides)
|
|
@@ -267,8 +255,7 @@ module Rigor
|
|
|
267
255
|
# Precomputed once per Configuration; frozen (with frozen members) so the carrier stays
|
|
268
256
|
# `Ractor.shareable?` across the worker boundary.
|
|
269
257
|
#
|
|
270
|
-
# @param selector
|
|
271
|
-
# @return [Set<String>]
|
|
258
|
+
# @param selector — see {#active_features}.
|
|
272
259
|
def active_ids_for(selector)
|
|
273
260
|
Set.new(active_features(selector).map(&:id)).freeze
|
|
274
261
|
end
|
|
@@ -276,8 +263,7 @@ module Rigor
|
|
|
276
263
|
# Feature ids named by a selector that are NOT in the overlay (typo / graduated / from a
|
|
277
264
|
# newer gem). Surfaced by `rigor show-bleedingedge` as a hint; never an error.
|
|
278
265
|
#
|
|
279
|
-
# @param selector
|
|
280
|
-
# @return [Array<String>]
|
|
266
|
+
# @param selector — see {#active_features}.
|
|
281
267
|
def unknown_selected_ids(selector)
|
|
282
268
|
named =
|
|
283
269
|
case selector["mode"]
|
|
@@ -118,7 +118,7 @@ module Rigor
|
|
|
118
118
|
)
|
|
119
119
|
end
|
|
120
120
|
|
|
121
|
-
# @return
|
|
121
|
+
# @return frozen registry
|
|
122
122
|
# pre-seeded with all bundled HKT registrations +
|
|
123
123
|
# bodies. Allocated fresh each call rather than
|
|
124
124
|
# memoised — memoisation through a module-level
|
|
@@ -241,8 +241,9 @@ module Rigor
|
|
|
241
241
|
["CSV", :readlines, :singleton] => CSV_PARSED_SPEC,
|
|
242
242
|
["CSV", :parse_line, :singleton] => CSV_ROW_SPEC
|
|
243
243
|
}.freeze
|
|
244
|
+
Ractor.make_shareable(METHOD_RETURN_OVERRIDES)
|
|
244
245
|
|
|
245
|
-
# @return
|
|
246
|
+
# @return the reduced HKT type for
|
|
246
247
|
# the given (class_name, method_name, kind) triple,
|
|
247
248
|
# or `nil` when no built-in override is registered.
|
|
248
249
|
# When `arg_types` is supplied AND the entry carries a
|
|
@@ -31,11 +31,12 @@ module Rigor
|
|
|
31
31
|
# - **No-argument refinement names** (`non-empty-string`, `non-zero-int`,
|
|
32
32
|
# `lowercase-string`, …) live in `REGISTRY` and resolve through `lookup(name)`.
|
|
33
33
|
# - **Parameterised refinement payloads** (`non-empty-array[Integer]`,
|
|
34
|
-
# `non-empty-hash[Symbol, Integer]`, `int<5, 10>`)
|
|
35
|
-
# full grammar is documented on `Parser`. The two
|
|
36
|
-
# no-arg head names; the parameterised head names live
|
|
37
|
-
# (square-bracket form, type args)
|
|
38
|
-
#
|
|
34
|
+
# `non-empty-hash[Symbol, Integer]`, `Integer[5..10]`, and the deprecated `int<5, 10>`)
|
|
35
|
+
# are accepted by `parse(payload)`. The full grammar is documented on `Parser`. The two
|
|
36
|
+
# surfaces share `REGISTRY` for the no-arg head names; the parameterised head names live
|
|
37
|
+
# in `PARAMETERISED_TYPE_BUILDERS` (square-bracket form, type args), `RANGE_HEAD_BUILDERS`
|
|
38
|
+
# (a numeric class over a range literal) and `PARAMETERISED_INT_BUILDERS` (the deprecated
|
|
39
|
+
# angle-bracket form, integer bounds).
|
|
39
40
|
module ImportedRefinements
|
|
40
41
|
REGISTRY = {
|
|
41
42
|
"non-empty-string" => -> { Type::Combinator.non_empty_string },
|
|
@@ -58,8 +59,12 @@ module Rigor
|
|
|
58
59
|
"non-empty-lowercase-string" => -> { Type::Combinator.non_empty_lowercase_string },
|
|
59
60
|
"non-empty-uppercase-string" => -> { Type::Combinator.non_empty_uppercase_string },
|
|
60
61
|
"literal-string" => -> { Type::Combinator.literal_string },
|
|
61
|
-
"non-empty-literal-string" => -> { Type::Combinator.non_empty_literal_string }
|
|
62
|
+
"non-empty-literal-string" => -> { Type::Combinator.non_empty_literal_string },
|
|
63
|
+
# ADR-109 WD4 — names for the two Float ranges people mean most; each is an alias of a range.
|
|
64
|
+
"non-nan-float" => -> { Type::Combinator.non_nan_float },
|
|
65
|
+
"finite-float" => -> { Type::Combinator.finite_float }
|
|
62
66
|
}.freeze
|
|
67
|
+
Ractor.make_shareable(REGISTRY)
|
|
63
68
|
private_constant :REGISTRY
|
|
64
69
|
|
|
65
70
|
# `name[T]` / `name[K, V]` — type-arg parameterised refinements. Each builder takes an
|
|
@@ -137,49 +142,91 @@ module Rigor
|
|
|
137
142
|
Type::Combinator.readonly_of(args.first)
|
|
138
143
|
}
|
|
139
144
|
}.freeze
|
|
145
|
+
Ractor.make_shareable(PARAMETERISED_TYPE_BUILDERS)
|
|
140
146
|
private_constant :PARAMETERISED_TYPE_BUILDERS
|
|
141
147
|
|
|
142
|
-
# `
|
|
148
|
+
# `Class[range]` — a numeric class head bounded by a Ruby range literal (ADR-109). The
|
|
149
|
+
# builder receives the `Range` value and returns the carrier, or `nil` when the range is
|
|
150
|
+
# empty or its endpoints are not literals of the head class; `nil` surfaces as the ordinary
|
|
151
|
+
# unresolved-payload diagnostic. `Float` joins this table with the `FloatRange` carrier.
|
|
152
|
+
RANGE_HEAD_BUILDERS = {
|
|
153
|
+
"Integer" => lambda { |range|
|
|
154
|
+
lo = range.begin
|
|
155
|
+
hi = range.end
|
|
156
|
+
return nil unless (lo.nil? || lo.is_a?(Integer)) && (hi.nil? || hi.is_a?(Integer))
|
|
157
|
+
|
|
158
|
+
# `1...10` is the set `1..9`: Integer ranges canonicalise to the closed form.
|
|
159
|
+
hi -= 1 if range.exclude_end? && hi.is_a?(Integer)
|
|
160
|
+
return nil if lo.is_a?(Integer) && hi.is_a?(Integer) && lo > hi
|
|
161
|
+
|
|
162
|
+
Type::Combinator.integer_range(lo || Type::IntegerRange::NEG_INFINITY, hi || Type::IntegerRange::POS_INFINITY)
|
|
163
|
+
},
|
|
164
|
+
# ADR-109 WD4 — `Float[R]` is the set of Floats `R.cover?` accepts. A missing or `nil` endpoint
|
|
165
|
+
# is the infinity on that side, except that `nil..nil` covers NaN in Ruby and so is `Float`
|
|
166
|
+
# itself; an Integer endpoint coerces (`(0..1).cover?(0.5)` is true); an exclusive end is kept
|
|
167
|
+
# (the carrier canonicalises it for equality), and an empty range declines.
|
|
168
|
+
"Float" => lambda { |range|
|
|
169
|
+
return Type::Combinator.nominal_of("Float") if range.begin.nil? && range.end.nil?
|
|
170
|
+
|
|
171
|
+
lo = ImportedRefinements.float_range_endpoint(range.begin, -Float::INFINITY)
|
|
172
|
+
hi = ImportedRefinements.float_range_endpoint(range.end, Float::INFINITY)
|
|
173
|
+
return nil if lo.nil? || hi.nil?
|
|
174
|
+
|
|
175
|
+
exclusive = range.exclude_end? && !range.end.nil?
|
|
176
|
+
return nil if lo > (exclusive ? hi.prev_float : hi)
|
|
177
|
+
|
|
178
|
+
Type::Combinator.float_range(lo, hi, exclude_end: exclusive)
|
|
179
|
+
}
|
|
180
|
+
}.freeze
|
|
181
|
+
Ractor.make_shareable(RANGE_HEAD_BUILDERS)
|
|
182
|
+
private_constant :RANGE_HEAD_BUILDERS
|
|
183
|
+
|
|
184
|
+
# `name<min, max>` — the PHPStan-style integer-bound form ADR-109 deprecates: still parsed so
|
|
185
|
+
# signatures written against v0.1–v0.3 keep resolving, never displayed. Each builder takes an
|
|
143
186
|
# `Array<Integer>` and returns a `Rigor::Type` (or `nil`). Bounds are signed integer
|
|
144
|
-
# literals
|
|
145
|
-
#
|
|
187
|
+
# literals. A reversed pair (`min` > `max`) is declined as `nil` like every other shape
|
|
188
|
+
# mismatch, so the caller surfaces `dynamic.rbs-extended.unresolved` at the annotation;
|
|
189
|
+
# `Type::IntegerRange` raises on it instead, and that `ArgumentError` used to escape as an
|
|
190
|
+
# `internal analyzer error` that abandoned the whole Ruby file.
|
|
146
191
|
PARAMETERISED_INT_BUILDERS = {
|
|
147
192
|
"int" => lambda { |bounds|
|
|
148
193
|
return nil unless bounds.size == 2
|
|
194
|
+
return nil if bounds[0] > bounds[1]
|
|
149
195
|
|
|
150
196
|
Type::Combinator.integer_range(bounds[0], bounds[1])
|
|
151
197
|
}
|
|
152
198
|
}.freeze
|
|
199
|
+
Ractor.make_shareable(PARAMETERISED_INT_BUILDERS)
|
|
153
200
|
private_constant :PARAMETERISED_INT_BUILDERS
|
|
154
201
|
|
|
155
202
|
module_function
|
|
156
203
|
|
|
157
|
-
# @param name
|
|
158
|
-
# @return
|
|
204
|
+
# @param name — kebab-case refinement name.
|
|
205
|
+
# @return the matching refinement carrier, or `nil` if the name is
|
|
159
206
|
# not registered.
|
|
160
207
|
def lookup(name)
|
|
161
208
|
builder = REGISTRY[name.to_s]
|
|
162
209
|
builder&.call
|
|
163
210
|
end
|
|
164
211
|
|
|
165
|
-
# @param payload
|
|
212
|
+
# @param payload — the trailing payload of a `rigor:v1:return:` (or sibling)
|
|
166
213
|
# directive. Accepts the bare-name forms `lookup` already handles plus the
|
|
167
214
|
# parameterised forms documented on {Parser}.
|
|
168
|
-
# @param name_scope
|
|
215
|
+
# @param name_scope —
|
|
169
216
|
# ADR-13 slice 3 — when provided, the parser consults the scope's `#resolver` chain
|
|
170
217
|
# after the built-in registry and built-in parametric forms but before the RBS
|
|
171
218
|
# Nominal fallback. `nil` (default) preserves the slice-1 / slice-2 behaviour of
|
|
172
219
|
# consulting only built-ins + RBS.
|
|
173
|
-
# @param reporter
|
|
220
|
+
# @param reporter —
|
|
174
221
|
# ADR-13 slice 3b — collector that the Resolver feeds `dynamic.shape.lossy-projection`
|
|
175
222
|
# events into when a shape-projection head (`pick_of`, `omit_of`, `partial_of`,
|
|
176
223
|
# `required_of`, `readonly_of`) is applied to a carrier that does not preserve shape
|
|
177
224
|
# information. `nil` (default) suppresses event accumulation; legacy call sites that
|
|
178
225
|
# have no reporter to thread keep the pre-slice-3b silent fall-through.
|
|
179
|
-
# @param source_location
|
|
226
|
+
# @param source_location — location attribution for the events the
|
|
180
227
|
# Resolver records. Carries the annotation's filename / line / column so the runner
|
|
181
228
|
# can stamp diagnostics with the user-visible source site.
|
|
182
|
-
# @return
|
|
229
|
+
# @return the resolved refinement carrier, or `nil` when the payload
|
|
183
230
|
# is unparseable or names a refinement / class no registered source resolved.
|
|
184
231
|
def parse(payload, name_scope: nil, reporter: nil, source_location: nil)
|
|
185
232
|
Parser.new(
|
|
@@ -201,6 +248,20 @@ module Rigor
|
|
|
201
248
|
PARAMETERISED_INT_BUILDERS[name]
|
|
202
249
|
end
|
|
203
250
|
|
|
251
|
+
def range_head_builder(name)
|
|
252
|
+
RANGE_HEAD_BUILDERS[name]
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# A Float-head range endpoint as a double: `nil` (absent) is `default`, an Integer literal
|
|
256
|
+
# coerces, a non-NaN Float stands, anything else declines with `nil`.
|
|
257
|
+
def float_range_endpoint(value, default)
|
|
258
|
+
case value
|
|
259
|
+
when nil then default
|
|
260
|
+
when Integer then value.to_f
|
|
261
|
+
when Float then value.nan? ? nil : value
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
204
265
|
def known?(name)
|
|
205
266
|
REGISTRY.key?(name.to_s) ||
|
|
206
267
|
PARAMETERISED_TYPE_BUILDERS.key?(name.to_s) ||
|
|
@@ -219,8 +280,10 @@ module Rigor
|
|
|
219
280
|
# parametric := simple_name '[' type_arg_list ']'
|
|
220
281
|
# | simple_name '<' int_bound_list '>'
|
|
221
282
|
# type_arg_list := type_arg (',' type_arg)*
|
|
222
|
-
# type_arg := type | class_name
|
|
283
|
+
# type_arg := range_literal | type | class_name
|
|
223
284
|
# class_name := /[A-Z][A-Za-z0-9_]*(?:::[A-Z][A-Za-z0-9_]*)*/
|
|
285
|
+
# range_literal := endpoint? ('..' | '...') endpoint? (at least one side written)
|
|
286
|
+
# endpoint := signed_int | 'nil'
|
|
224
287
|
# int_bound_list := signed_int (',' signed_int)*
|
|
225
288
|
# signed_int := /-?\d+/
|
|
226
289
|
#
|
|
@@ -274,7 +337,16 @@ module Rigor
|
|
|
274
337
|
# delimiter.
|
|
275
338
|
SYMBOL_LITERAL = /:(?<value>[a-zA-Z_][a-zA-Z0-9_]*[?!=]?)/
|
|
276
339
|
STRING_LITERAL = /"(?<value>[^"\\]*)"/
|
|
277
|
-
|
|
340
|
+
# ADR-109 — a Ruby range literal at type-arg position, `1..10` / `1...10` / `1..` / `..10` /
|
|
341
|
+
# `nil..nil`, and for the Float head `0.0...1.0` / `1e-3..` / `-Float::INFINITY..Float::MAX`.
|
|
342
|
+
# Tried before the class-name and integer scans so `Float::INFINITY..` and `1..10` are not
|
|
343
|
+
# consumed as a class name or a bare integer; the operator is mandatory, so a bare integer or
|
|
344
|
+
# constant never matches. `..` with nothing on either side is not Ruby and is rejected after
|
|
345
|
+
# the match.
|
|
346
|
+
RANGE_ENDPOINT = /-?(?:\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|Float::INFINITY|Float::MAX)|nil/
|
|
347
|
+
RANGE_LITERAL = /(?<lo>#{RANGE_ENDPOINT})?\s*(?<op>\.\.\.?)\s*(?<hi>#{RANGE_ENDPOINT})?/
|
|
348
|
+
private_constant :SIMPLE_NAME, :CLASS_NAME, :SIGNED_INT, :SYMBOL_LITERAL, :STRING_LITERAL,
|
|
349
|
+
:RANGE_ENDPOINT, :RANGE_LITERAL
|
|
278
350
|
|
|
279
351
|
def parse_type_ast
|
|
280
352
|
if (class_name = @scanner.scan(CLASS_NAME))
|
|
@@ -382,7 +454,9 @@ module Rigor
|
|
|
382
454
|
end
|
|
383
455
|
|
|
384
456
|
def parse_single_type_arg_ast
|
|
385
|
-
if (
|
|
457
|
+
if (range = scan_range_literal)
|
|
458
|
+
range
|
|
459
|
+
elsif (class_name = @scanner.scan(CLASS_NAME))
|
|
386
460
|
parse_class_arg_tail_ast(class_name)
|
|
387
461
|
elsif (literal = @scanner.scan(SIGNED_INT))
|
|
388
462
|
TypeNode::IntegerLiteral.new(value: Integer(literal))
|
|
@@ -421,6 +495,36 @@ module Rigor
|
|
|
421
495
|
Integer(literal)
|
|
422
496
|
end
|
|
423
497
|
|
|
498
|
+
# Returns a {TypeNode::RangeLiteral} when the scanner sits on a Ruby range literal, `nil`
|
|
499
|
+
# (without consuming input) otherwise. `nil` and an absent endpoint both become Ruby's
|
|
500
|
+
# `nil` endpoint; the two spellings denote the same range.
|
|
501
|
+
def scan_range_literal
|
|
502
|
+
return nil unless @scanner.scan(RANGE_LITERAL)
|
|
503
|
+
|
|
504
|
+
lo = @scanner[:lo]
|
|
505
|
+
hi = @scanner[:hi]
|
|
506
|
+
return nil if lo.nil? && hi.nil?
|
|
507
|
+
|
|
508
|
+
TypeNode::RangeLiteral.new(
|
|
509
|
+
value: Range.new(range_endpoint(lo), range_endpoint(hi), @scanner[:op] == "...")
|
|
510
|
+
)
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
# The endpoint as the Ruby value the token denotes: an Integer literal stays an Integer (the
|
|
514
|
+
# `Integer` head needs to tell `1` from `1.0`), a Float literal or one of the four spelled
|
|
515
|
+
# constants becomes the double.
|
|
516
|
+
def range_endpoint(token)
|
|
517
|
+
case token
|
|
518
|
+
when nil, "nil" then nil
|
|
519
|
+
when "Float::INFINITY" then Float::INFINITY
|
|
520
|
+
when "-Float::INFINITY" then -Float::INFINITY
|
|
521
|
+
when "Float::MAX" then Float::MAX
|
|
522
|
+
when "-Float::MAX" then -Float::MAX
|
|
523
|
+
when /[.eE]/ then Float(token)
|
|
524
|
+
else Integer(token)
|
|
525
|
+
end
|
|
526
|
+
end
|
|
527
|
+
|
|
424
528
|
def skip_ws
|
|
425
529
|
@scanner.skip(/\s+/)
|
|
426
530
|
end
|
|
@@ -463,7 +567,7 @@ module Rigor
|
|
|
463
567
|
# `StringLiteral`) carries a Ruby value that lifts directly to a `Constant<value>`
|
|
464
568
|
# carrier through the same helper.
|
|
465
569
|
LITERAL_AST_NODES = [
|
|
466
|
-
TypeNode::IntegerLiteral, TypeNode::SymbolLiteral, TypeNode::StringLiteral
|
|
570
|
+
TypeNode::IntegerLiteral, TypeNode::SymbolLiteral, TypeNode::StringLiteral, TypeNode::RangeLiteral
|
|
467
571
|
].freeze
|
|
468
572
|
private_constant :LITERAL_AST_NODES
|
|
469
573
|
|
|
@@ -519,6 +623,11 @@ module Rigor
|
|
|
519
623
|
end
|
|
520
624
|
|
|
521
625
|
def resolve_generic(node)
|
|
626
|
+
# ADR-109 — `Integer[1..10]`. A range literal under a numeric head is that head's range
|
|
627
|
+
# refinement or nothing: an empty or malformed range declines here rather than falling
|
|
628
|
+
# through to a `Nominal[Integer, [Constant<Range>]]` the RBS fallback would otherwise build.
|
|
629
|
+
return resolve_range_head(node) if range_headed?(node)
|
|
630
|
+
|
|
522
631
|
builtin = try_builtin_parametric(node)
|
|
523
632
|
return builtin unless builtin.nil?
|
|
524
633
|
|
|
@@ -547,6 +656,19 @@ module Rigor
|
|
|
547
656
|
try_parametric_type_builder(node) || try_parametric_int_builder(node)
|
|
548
657
|
end
|
|
549
658
|
|
|
659
|
+
def range_headed?(node)
|
|
660
|
+
!ImportedRefinements.range_head_builder(node.head).nil? &&
|
|
661
|
+
node.args.any?(TypeNode::RangeLiteral)
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
# Exactly one range literal under the head; `Integer[1..10, 3]` is not a range refinement.
|
|
665
|
+
# Anything else under the same head (`Integer[Foo]`) keeps its pre-ADR-109 path.
|
|
666
|
+
def resolve_range_head(node)
|
|
667
|
+
return nil unless node.args.size == 1
|
|
668
|
+
|
|
669
|
+
ImportedRefinements.range_head_builder(node.head).call(node.args.first.value)
|
|
670
|
+
end
|
|
671
|
+
|
|
550
672
|
def try_parametric_type_builder(node)
|
|
551
673
|
builder = ImportedRefinements.parametric_type_builder(node.head)
|
|
552
674
|
return nil if builder.nil?
|
|
@@ -585,7 +707,23 @@ module Rigor
|
|
|
585
707
|
bounds = node.args.map { |a| a.is_a?(TypeNode::IntegerLiteral) ? a.value : nil }
|
|
586
708
|
return nil if bounds.any?(&:nil?)
|
|
587
709
|
|
|
588
|
-
builder.call(bounds)
|
|
710
|
+
result = builder.call(bounds)
|
|
711
|
+
record_deprecated_form(node, bounds, result) unless result.nil?
|
|
712
|
+
result
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
# ADR-109 WD3 — the angle-bracket form still resolves, and the run says so once per annotation with
|
|
716
|
+
# the spelling the same type now displays as. Recorded only when the payload resolved: an
|
|
717
|
+
# unresolvable one already surfaces as `dynamic.rbs-extended.unresolved`, and a second row for it
|
|
718
|
+
# would name a replacement for something that never parsed.
|
|
719
|
+
def record_deprecated_form(node, bounds, result)
|
|
720
|
+
return if @reporter.nil?
|
|
721
|
+
|
|
722
|
+
path, line, column = RbsExtended::Reporter.position_of(@source_location)
|
|
723
|
+
@reporter.record_deprecated_form(
|
|
724
|
+
payload: "#{node.head}<#{bounds.join(', ')}>", replacement: result.describe,
|
|
725
|
+
path: path, line: line, column: column
|
|
726
|
+
)
|
|
589
727
|
end
|
|
590
728
|
|
|
591
729
|
def resolve_args(args)
|
|
@@ -117,8 +117,7 @@ module Rigor
|
|
|
117
117
|
|
|
118
118
|
# --- private ------------------------------------------------------
|
|
119
119
|
|
|
120
|
-
# @param value
|
|
121
|
-
# @return [Rigor::Type]
|
|
120
|
+
# @param value — a non-empty string
|
|
122
121
|
def self.classify_string(value)
|
|
123
122
|
if Type::Refined.ruby_numeric_literal?(value)
|
|
124
123
|
NUMERIC_STRING
|
|
@@ -133,8 +132,7 @@ module Rigor
|
|
|
133
132
|
# Called ONLY with the names in {RUNTIME_STRING_CONSTANTS} — Rigor's own source — and only
|
|
134
133
|
# while this file is being loaded. It is never handed a name from the analysed program.
|
|
135
134
|
#
|
|
136
|
-
# @param name
|
|
137
|
-
# @return [String, nil]
|
|
135
|
+
# @param name — a qualified constant path without a leading "::"
|
|
138
136
|
def self.runtime_string_value(name)
|
|
139
137
|
mod = ::Object
|
|
140
138
|
name.split("::").each do |part|
|
|
@@ -161,7 +159,7 @@ module Rigor
|
|
|
161
159
|
end
|
|
162
160
|
private_class_method :runtime_string_value
|
|
163
161
|
|
|
164
|
-
# @return
|
|
162
|
+
# @return frozen, built once at load time.
|
|
165
163
|
def self.build_runtime_string_refinements
|
|
166
164
|
RUNTIME_STRING_CONSTANTS.each_with_object({}) do |name, table|
|
|
167
165
|
value = runtime_string_value(name)
|
|
@@ -175,9 +173,9 @@ module Rigor
|
|
|
175
173
|
|
|
176
174
|
# --- public API ---------------------------------------------------
|
|
177
175
|
|
|
178
|
-
# @param name
|
|
176
|
+
# @param name — unqualified constant name (e.g. `"Math::PI"`,
|
|
179
177
|
# `"RUBY_VERSION"`, `"Ruby::ENGINE"`)
|
|
180
|
-
# @return
|
|
178
|
+
# @return refined type, or nil to fall through
|
|
181
179
|
def self.lookup(name)
|
|
182
180
|
FOLDED_CONSTANTS[name] || RUNTIME_STRING_REFINEMENTS[name]
|
|
183
181
|
end
|
|
@@ -20,14 +20,22 @@ module Rigor
|
|
|
20
20
|
# `{n,m}` forms with `n >= 1`):
|
|
21
21
|
#
|
|
22
22
|
# - `\d`, `[0-9]` -> decimal-int-string
|
|
23
|
-
# - `\h` ->
|
|
24
|
-
# - `[0-9a-fA-F]` ->
|
|
25
|
-
# - `[0-9a-f]`, `[0-9A-F]` ->
|
|
26
|
-
# - `[0-7]` ->
|
|
23
|
+
# - `\h` -> non-empty-string
|
|
24
|
+
# - `[0-9a-fA-F]` -> non-empty-string
|
|
25
|
+
# - `[0-9a-f]`, `[0-9A-F]` -> non-empty-string
|
|
26
|
+
# - `[0-7]` -> non-empty-string
|
|
27
27
|
# - `[a-z]` -> lowercase-string
|
|
28
28
|
# - `[A-Z]` -> uppercase-string
|
|
29
29
|
# - `[[:digit:]]` -> numeric-string
|
|
30
30
|
#
|
|
31
|
+
# #1004 — the hex/octal digit classes do NOT map to `hex-int-string` / `octal-int-string`.
|
|
32
|
+
# Those refinements' predicates (`Type::Refined` PREDICATES, in `type/refined.rb`) REQUIRE the
|
|
33
|
+
# conventional `0x` / `0o` prefix, but a bare digit class like `[0-9a-fA-F]+` matches "ff" —
|
|
34
|
+
# a string with no prefix at all. Mapping a matched digit run to a refinement its own
|
|
35
|
+
# predicate rejects is unsound (worse than the plain `String` it replaces), so these rows
|
|
36
|
+
# drop to `non-empty-string`: the `+` / `{n,}` (n >= 1) quantifier already guarantees the
|
|
37
|
+
# captured run is never empty, and that much is true regardless of prefix.
|
|
38
|
+
#
|
|
31
39
|
# Anything outside the table returns `nil` so the calling narrowing site falls back to
|
|
32
40
|
# its previous behaviour (plain `String`). Arbitrary regex semantic equivalence is
|
|
33
41
|
# undecidable, so the table is intentionally a small audited set of canonical shapes
|
|
@@ -46,11 +54,11 @@ module Rigor
|
|
|
46
54
|
RULES = Ractor.make_shareable([
|
|
47
55
|
[/\A\\d#{QUANTIFIER_SOURCE}\z/, :decimal_int_string],
|
|
48
56
|
[/\A\[0-9\]#{QUANTIFIER_SOURCE}\z/, :decimal_int_string],
|
|
49
|
-
[/\A\\h#{QUANTIFIER_SOURCE}\z/, :
|
|
50
|
-
[/\A\[0-9a-fA-F\]#{QUANTIFIER_SOURCE}\z/, :
|
|
51
|
-
[/\A\[0-9a-f\]#{QUANTIFIER_SOURCE}\z/, :
|
|
52
|
-
[/\A\[0-9A-F\]#{QUANTIFIER_SOURCE}\z/, :
|
|
53
|
-
[/\A\[0-7\]#{QUANTIFIER_SOURCE}\z/, :
|
|
57
|
+
[/\A\\h#{QUANTIFIER_SOURCE}\z/, :non_empty_string],
|
|
58
|
+
[/\A\[0-9a-fA-F\]#{QUANTIFIER_SOURCE}\z/, :non_empty_string],
|
|
59
|
+
[/\A\[0-9a-f\]#{QUANTIFIER_SOURCE}\z/, :non_empty_string],
|
|
60
|
+
[/\A\[0-9A-F\]#{QUANTIFIER_SOURCE}\z/, :non_empty_string],
|
|
61
|
+
[/\A\[0-7\]#{QUANTIFIER_SOURCE}\z/, :non_empty_string],
|
|
54
62
|
[/\A\[a-z\]#{QUANTIFIER_SOURCE}\z/, :lowercase_string],
|
|
55
63
|
[/\A\[A-Z\]#{QUANTIFIER_SOURCE}\z/, :uppercase_string],
|
|
56
64
|
[/\A\[\[:digit:\]\]#{QUANTIFIER_SOURCE}\z/, :numeric_string]
|
|
@@ -62,11 +70,11 @@ module Rigor
|
|
|
62
70
|
|
|
63
71
|
module_function
|
|
64
72
|
|
|
65
|
-
# @param body
|
|
73
|
+
# @param body — a regex sub-pattern, typically the inner body of a
|
|
66
74
|
# `(?<name>body)` named capture. Anchors (`\A`, `\z`, `^`, `$`) are not stripped — the
|
|
67
75
|
# recogniser table targets bodies that the regex engine treats as anchored to the
|
|
68
76
|
# capture group bounds.
|
|
69
|
-
# @return
|
|
77
|
+
# @return the matching imported refinement carrier, or `nil` if
|
|
70
78
|
# `body` is not a recognised shape.
|
|
71
79
|
def for_capture_body(body)
|
|
72
80
|
return nil if body.nil? || body.empty?
|
|
@@ -100,8 +108,8 @@ module Rigor
|
|
|
100
108
|
# free-whitespace/`#`-comment flag from the `source` alone, so consumers bail on it before
|
|
101
109
|
# calling here.
|
|
102
110
|
#
|
|
103
|
-
# @param source
|
|
104
|
-
# @return
|
|
111
|
+
# @param source — the full regex source string.
|
|
112
|
+
# @return the matching imported refinement carrier, or `nil`.
|
|
105
113
|
def for_whole_pattern(source)
|
|
106
114
|
return nil if source.nil?
|
|
107
115
|
return nil unless source.start_with?('\A') && source.end_with?('\z')
|
|
@@ -93,20 +93,20 @@ module Rigor
|
|
|
93
93
|
["IO", :read, :singleton] => IO_READ_NO_LENGTH,
|
|
94
94
|
["File", :read, :singleton] => IO_READ_NO_LENGTH
|
|
95
95
|
}.freeze
|
|
96
|
+
Ractor.make_shareable(OVERRIDES)
|
|
96
97
|
private_constant :OVERRIDES
|
|
97
98
|
|
|
98
99
|
# Looks up a refined return type for the given call.
|
|
99
100
|
#
|
|
100
|
-
# @param owner_class_name
|
|
101
|
+
# @param owner_class_name — the class on which the method is defined
|
|
101
102
|
# (e.g., `"Kernel"`). Pass `nil` when the caller hasn't resolved a defining owner
|
|
102
103
|
# yet — the lookup will then fall back to matching by `(method_name, kind)` against
|
|
103
104
|
# entries whose owner is currently in the table.
|
|
104
|
-
# @param
|
|
105
|
-
# @param kind [Symbol] one of `:singleton`, `:instance`. The caller passes the shape of
|
|
105
|
+
# @param kind — one of `:singleton`, `:instance`. The caller passes the shape of
|
|
106
106
|
# the actual call site; the table stores `:both` for entries that match either.
|
|
107
|
-
# @param arg_types
|
|
107
|
+
# @param arg_types — positional argument types. Forwarded to the
|
|
108
108
|
# handler so future entries can discriminate on argument shape.
|
|
109
|
-
# @return
|
|
109
|
+
# @return the refined return type, or `nil` when no override
|
|
110
110
|
# matches.
|
|
111
111
|
def self.lookup(owner_class_name:, method_name:, kind:, arg_types: [])
|
|
112
112
|
return nil if owner_class_name.nil?
|
|
@@ -125,9 +125,10 @@ module Rigor
|
|
|
125
125
|
acc[mname] ||= []
|
|
126
126
|
acc[mname] << owner unless acc[mname].include?(owner)
|
|
127
127
|
end.freeze
|
|
128
|
+
Ractor.make_shareable(OWNERS_BY_METHOD)
|
|
128
129
|
private_constant :OWNERS_BY_METHOD
|
|
129
130
|
|
|
130
|
-
# @return
|
|
131
|
+
# @return the candidate owner class names for a bare method-name
|
|
131
132
|
# lookup. Empty when no override names this method.
|
|
132
133
|
NO_OWNERS = [].freeze
|
|
133
134
|
private_constant :NO_OWNERS
|
|
@@ -41,8 +41,7 @@ module Rigor
|
|
|
41
41
|
|
|
42
42
|
module_function
|
|
43
43
|
|
|
44
|
-
# @
|
|
45
|
-
# @return [Array, nil] `[name, start_line, start_column, end_line, end_column]`, or nil when there is
|
|
44
|
+
# @return `[name, start_line, start_column, end_line, end_column]`, or nil when there is
|
|
46
45
|
# no location to carry. Fail-soft: a location whose buffer cannot answer is dumped as nil rather
|
|
47
46
|
# than failing the whole environment's dump.
|
|
48
47
|
def dump(location)
|
|
@@ -55,8 +54,7 @@ module Rigor
|
|
|
55
54
|
nil
|
|
56
55
|
end
|
|
57
56
|
|
|
58
|
-
# @param payload
|
|
59
|
-
# @return [RBS::Location, nil]
|
|
57
|
+
# @param payload — what {dump} produced.
|
|
60
58
|
def load(payload)
|
|
61
59
|
return nil if payload.nil?
|
|
62
60
|
|