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
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rigor
|
|
4
|
+
class Environment
|
|
5
|
+
# ADR-112 WD5 / issue #1075 — the consistency rule for one member declared by two sources. It replaces
|
|
6
|
+
# ADR-32 WD13's "`sig/` wins per member": a `sig/` declaration and an inline (`@rbs` / `#:`) one of the
|
|
7
|
+
# same member are compared instead of ranked.
|
|
8
|
+
#
|
|
9
|
+
# - **Consistent** — in every type position one side's type is a subtype of the other's, decided from
|
|
10
|
+
# the two declarations alone ({Comparator#subset?}). `untyped` (and
|
|
11
|
+
# `void` / `top`, which RBS defines as the same top type) is consistent with everything and is the
|
|
12
|
+
# least precise answer, so a migrating project's `sig/ -> untyped` beside an inline `-> void` stays
|
|
13
|
+
# quiet (ADR-93's herb case). The two merge to the more precise side: when every position of the
|
|
14
|
+
# inline member is at least as precise as `sig/`'s and one is strictly more, the inline member binds
|
|
15
|
+
# and the `sig/` one stands down; otherwise `sig/` binds. Nothing is reported either way. The merge
|
|
16
|
+
# takes the narrower type in parameter positions too, which is the author's stated contract.
|
|
17
|
+
# - **Contradiction** — proven: some position every call fills whose two types are disjoint by the RBS
|
|
18
|
+
# class hierarchy ({RbsProof}), positional arity ranges that cannot meet, or a keyword one side
|
|
19
|
+
# requires and the other cannot take in any form.
|
|
20
|
+
# `sig/` still binds, so the class builds, and the run reports `rbs.contradicting-signature` as an
|
|
21
|
+
# error.
|
|
22
|
+
# - **Undecided** — everything else: a position Rigor cannot read faithfully, two types it cannot prove
|
|
23
|
+
# disjoint, shapes that differ without contradicting, overloads that do not pair one to one, or each
|
|
24
|
+
# side more precise in a different position. `sig/` binds and the dropped inline member is reported
|
|
25
|
+
# at `:info` under ADR-32 WD12, as every inline member was before.
|
|
26
|
+
#
|
|
27
|
+
# The false-positive discipline holds the DEFINITION of a contradiction (ADR-112 WD5): every doubt
|
|
28
|
+
# lands in "undecided". {Comparator} carries the type work and says what counts as a proof.
|
|
29
|
+
#
|
|
30
|
+
# The same comparison answers `rbs-extended.md`'s "an annotation whose refinement exceeds the ordinary
|
|
31
|
+
# RBS contract is a conflict": a member-level `rigor:v1:return:` / `rigor:v1:param:` payload disjoint
|
|
32
|
+
# from the member's own declared type is reported under the same identifier.
|
|
33
|
+
#
|
|
34
|
+
# The comparison works on one member PAIR and knows nothing about where either side came from, so a
|
|
35
|
+
# third source (ADR-112's `@extrbs`, #1073) plugs in as another caller of {Comparator#compare}.
|
|
36
|
+
#
|
|
37
|
+
# Pure over RBS AST members: no environment is consulted, so {RbsLoader} derives the same answer from its
|
|
38
|
+
# inputs at build time and on an environment-cache HIT.
|
|
39
|
+
module MemberConsistency
|
|
40
|
+
# One outcome per `(class, method, kind)` key two sources declare, or per member whose refinement
|
|
41
|
+
# exceeds its own declared type (`outcome: :refinement`). `signature_path` / `signature_line` locate
|
|
42
|
+
# the `.rbs` member (nil for a refinement record read off an inline member); `virtual_name` is the
|
|
43
|
+
# synthesized buffer name of the inline source (nil for a refinement record read off a `.rbs` member).
|
|
44
|
+
Record = Data.define(:class_name, :method_name, :kind, :outcome, :detail, :signature_path,
|
|
45
|
+
:signature_line, :virtual_name)
|
|
46
|
+
|
|
47
|
+
# What the environment build needs from the rule: which inline keys stand down, and which `.rbs`
|
|
48
|
+
# members stand down per file (because the inline side was the more precise one).
|
|
49
|
+
Resolution = Data.define(:records, :inline_standdowns, :signature_standdowns)
|
|
50
|
+
|
|
51
|
+
EMPTY = Ractor.make_shareable(
|
|
52
|
+
Resolution.new(records: [], inline_standdowns: Set.new, signature_standdowns: {})
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Outcomes that report, and how loud.
|
|
56
|
+
ERROR_OUTCOMES = %i[contradiction refinement].freeze
|
|
57
|
+
INFO_OUTCOMES = %i[undecided].freeze
|
|
58
|
+
|
|
59
|
+
NO_RECORDS = [].freeze
|
|
60
|
+
private_constant :NO_RECORDS
|
|
61
|
+
|
|
62
|
+
# What a disjointness proof may lean on (ADR-112 WD5, #1075): the RBS class hierarchy the analysis
|
|
63
|
+
# itself uses, restricted to classes Ruby core and the stdlib declare. Never Ruby constants loaded in
|
|
64
|
+
# the analyzer process — those depend on which libraries happen to be required, and rbs and Ruby
|
|
65
|
+
# disagree about some of them (`Tempfile < File` in rbs, `< Delegator` in Ruby). Never a class the
|
|
66
|
+
# project declares, whether in `sig/`, inline or only in Ruby: a project `sig/` routinely omits a
|
|
67
|
+
# superclass (`class Admin` for `Admin < User`), and a `Struct.new` / `Data.define` / `Class.new`
|
|
68
|
+
# constant has none in RBS at all, so the rest of Rigor never reads two of them as disjoint either.
|
|
69
|
+
#
|
|
70
|
+
# A core or stdlib class may be reopened by the project (a `sig/` monkeypatch); the proof still
|
|
71
|
+
# counts it, since a reopening can add modules but never change the superclass chain a class-versus-
|
|
72
|
+
# class answer reads. Nothing here depends on which files the run was given, so `rigor check lib` and
|
|
73
|
+
# `rigor check lib/one.rb` report the same rows.
|
|
74
|
+
#
|
|
75
|
+
# Only the reported rows are derived with a proof; the environment build is not, and needs none:
|
|
76
|
+
# a contradiction and an undecided pair both keep the `.rbs` member, so a proof changes a row's
|
|
77
|
+
# severity and never which declaration binds.
|
|
78
|
+
class RbsProof
|
|
79
|
+
# Core and stdlib classes whose RBS ancestry disagrees with Ruby's, excluded from every proof on
|
|
80
|
+
# both sides of each disagreement. rbs 4.2 declares `class Tempfile < File` where the `tempfile`
|
|
81
|
+
# library defines `Tempfile < Delegator` (so RBS reads `Tempfile` and `Delegator` as unrelated),
|
|
82
|
+
# `class Random` with no superclass where Ruby has `Random < Random::Base`, and
|
|
83
|
+
# `class Gem::MissingSpecError` with no superclass where RubyGems has it `< Gem::LoadError`. A pair
|
|
84
|
+
# naming one of these is undecided. `spec/rigor/environment/member_consistency_ancestry_guard_spec.rb` compares
|
|
85
|
+
# every candidate class's RBS chain with Ruby's and fails on a disagreement missing from this list,
|
|
86
|
+
# so an rbs or Ruby bump that introduces one fails CI instead of reporting an error on correct code.
|
|
87
|
+
UNRELIABLE_ANCESTRY = %w[Tempfile Delegator Random Random::Base Gem::MissingSpecError].to_set.freeze
|
|
88
|
+
|
|
89
|
+
# @param loader — the project's {RbsLoader}, whose built environment answers the hierarchy.
|
|
90
|
+
def initialize(loader)
|
|
91
|
+
@loader = loader
|
|
92
|
+
@ancestors = {}
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# The RBS ancestor names of `name` (itself first) when its primary RBS declaration is a class from
|
|
96
|
+
# Ruby core or the stdlib, or nil.
|
|
97
|
+
def class_ancestors(name)
|
|
98
|
+
key = name.to_s.delete_prefix("::")
|
|
99
|
+
return @ancestors[key] if @ancestors.key?(key)
|
|
100
|
+
|
|
101
|
+
@ancestors[key] = core_class_ancestors(key)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
def core_class_ancestors(key)
|
|
107
|
+
return nil if UNRELIABLE_ANCESTRY.include?(key)
|
|
108
|
+
return nil unless @loader.core_or_stdlib_class?(key) && !@loader.rbs_module?(key)
|
|
109
|
+
|
|
110
|
+
ancestors = @loader.ancestor_names_for(key)
|
|
111
|
+
ancestors.first == key ? ancestors : nil
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
class << self
|
|
116
|
+
# @param signature_members — `{[class, method, kind] => [signature_path, member, visibility]}`, the
|
|
117
|
+
# first project `.rbs` member declaring each key, with its effective visibility.
|
|
118
|
+
# @param inline_members — `[[virtual_name, class_name, member, visibility], ...]`, every member the
|
|
119
|
+
# inline sources declare.
|
|
120
|
+
# @param shadowable — the first segment of every class / module name the project's inputs declare
|
|
121
|
+
# ({Comparator#initialize}).
|
|
122
|
+
# @param proof — an {RbsProof} for the reported rows, or nil for the environment build.
|
|
123
|
+
# @return a {Resolution}. Records are sorted and deduplicated; silent outcomes are recorded too, so a
|
|
124
|
+
# caller can see what merged where.
|
|
125
|
+
def resolve(signature_members, inline_members, shadowable: Set.new, proof: nil)
|
|
126
|
+
return EMPTY if inline_members.empty?
|
|
127
|
+
|
|
128
|
+
# Loaded here rather than with the file: {RbsLoader} requires this module on every run, and only a
|
|
129
|
+
# project with inline RBS ever compares anything.
|
|
130
|
+
require_relative "member_consistency/comparator"
|
|
131
|
+
|
|
132
|
+
state = { comparator: Comparator.new(shadowable, proof: proof), records: [], inline: Set.new,
|
|
133
|
+
signature: Hash.new { |hash, file| hash[file] = Set.new }, checked: {}.compare_by_identity }
|
|
134
|
+
inline_members.each do |virtual_name, class_name, member, visibility|
|
|
135
|
+
state[:records].concat(refinement_records(state, class_name, member, nil, virtual_name))
|
|
136
|
+
resolve_member(state, signature_members, [virtual_name, class_name, member, visibility])
|
|
137
|
+
end
|
|
138
|
+
Resolution.new(
|
|
139
|
+
records: state[:records].uniq.sort_by { |r| record_sort_key(r) }.freeze,
|
|
140
|
+
inline_standdowns: state[:inline].freeze,
|
|
141
|
+
signature_standdowns: state[:signature].transform_values(&:freeze).freeze
|
|
142
|
+
)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# The `[method_name, kind]` pairs one RBS member contributes to a definition build, mirroring
|
|
146
|
+
# `RBS::DefinitionBuilder::MethodBuilder#build_instance` / `#build_singleton` — which is what decides
|
|
147
|
+
# whether two members collide. An attribute contributes its reader and / or writer name (`foo`,
|
|
148
|
+
# `foo=`), an alias its new name, and `def self?.x` both sides. An `overloading?` member (`def x: ...
|
|
149
|
+
# | ...`) contributes NOTHING: rbs files those under `overloads` rather than `originals`, so they are
|
|
150
|
+
# designed to compose with an existing declaration and are never compared against it.
|
|
151
|
+
def member_method_keys(member)
|
|
152
|
+
case member
|
|
153
|
+
when ::RBS::AST::Members::MethodDefinition then method_definition_keys(member)
|
|
154
|
+
when ::RBS::AST::Members::AttrReader then [[member.name, member.kind]]
|
|
155
|
+
when ::RBS::AST::Members::AttrWriter then [[:"#{member.name}=", member.kind]]
|
|
156
|
+
when ::RBS::AST::Members::AttrAccessor then [[member.name, member.kind], [:"#{member.name}=", member.kind]]
|
|
157
|
+
when ::RBS::AST::Members::Alias then [[member.new_name, member.kind]]
|
|
158
|
+
else []
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
private
|
|
163
|
+
|
|
164
|
+
def resolve_member(state, signature_members, inline)
|
|
165
|
+
_virtual_name, class_name, member, = inline
|
|
166
|
+
overlapping = member_method_keys(member).filter_map do |method_name, kind|
|
|
167
|
+
key = [class_name, method_name, kind]
|
|
168
|
+
owner = signature_members[key]
|
|
169
|
+
owner && [key, *owner]
|
|
170
|
+
end
|
|
171
|
+
return if overlapping.empty?
|
|
172
|
+
|
|
173
|
+
verdicts = overlapping.map do |key, path, sig_member, sig_visibility|
|
|
174
|
+
record_signature_refinements(state, class_name, sig_member, path)
|
|
175
|
+
[key, path, sig_member, state[:comparator].compare(sig_member, member, key[1]), sig_visibility]
|
|
176
|
+
end
|
|
177
|
+
binds = inline_binds?(state[:comparator], verdicts, overlapping.map(&:first), inline)
|
|
178
|
+
apply_verdicts(state, verdicts, binds, inline[0])
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Records each key's outcome and files the losing side: every `.rbs` member the inline one displaces
|
|
182
|
+
# when it binds, or every shared inline key when `sig/` does.
|
|
183
|
+
def apply_verdicts(state, verdicts, inline_binds, virtual_name)
|
|
184
|
+
verdicts.each do |key, path, sig_member, verdict, _|
|
|
185
|
+
if inline_binds
|
|
186
|
+
state[:signature][path].merge(full_keys(key[0], sig_member))
|
|
187
|
+
verdict = [:inline, nil]
|
|
188
|
+
else
|
|
189
|
+
state[:inline] << key
|
|
190
|
+
verdict = reported_verdict(verdict)
|
|
191
|
+
end
|
|
192
|
+
state[:records] << record(key, verdict, path, sig_member, virtual_name)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# The inline member binds only when every key it shares is at least as precise inline, one is
|
|
197
|
+
# strictly more, and swapping loses nothing the `.rbs` member said:
|
|
198
|
+
#
|
|
199
|
+
# - each `.rbs` member it displaces declares no key the inline member does not also declare (an
|
|
200
|
+
# `attr_accessor` in `sig/` against an inline `def foo` would otherwise take `foo=` down with it);
|
|
201
|
+
# - the two have the same effective visibility (a `private def` in `sig/` must not turn public);
|
|
202
|
+
# - every annotation on the `.rbs` member other than a `rigor:v1:return:` / `rigor:v1:param:`
|
|
203
|
+
# refinement (which the comparison has already weighed) is also on the inline member, so a
|
|
204
|
+
# predicate, an assertion or an effect envelope written in `sig/` does not vanish (ADR-32 WD12).
|
|
205
|
+
def inline_binds?(comparator, verdicts, shared_keys, inline)
|
|
206
|
+
outcomes = verdicts.map { |verdict| verdict[3].first }
|
|
207
|
+
return false unless outcomes.all? { |outcome| %i[equal inline].include?(outcome) }
|
|
208
|
+
return false unless outcomes.include?(:inline)
|
|
209
|
+
|
|
210
|
+
shared = shared_keys.to_set
|
|
211
|
+
verdicts.all? do |_, _, sig_member, _, sig_visibility|
|
|
212
|
+
full_keys(inline[1], sig_member).all? { |key| shared.include?(key) } &&
|
|
213
|
+
sig_visibility == inline[3] &&
|
|
214
|
+
annotations_kept?(comparator, sig_member, inline[2])
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def annotations_kept?(comparator, sig_member, inline_member)
|
|
219
|
+
kept = comparator.member_annotation_strings(inline_member)
|
|
220
|
+
comparator.member_annotation_strings(sig_member).all? do |string|
|
|
221
|
+
comparator.refinement_directive?(string) || kept.include?(string)
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# A key where the inline side was more precise, but the member as a whole could not bind, lost
|
|
226
|
+
# something the author wrote: that is WD12's "parsed and not honoured", so it reports as undecided.
|
|
227
|
+
def reported_verdict(verdict)
|
|
228
|
+
if verdict.first == :inline
|
|
229
|
+
return [:undecided,
|
|
230
|
+
"the inline declaration is more precise here but could not replace the `.rbs` member " \
|
|
231
|
+
"without dropping what it declares"]
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
verdict
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def full_keys(class_name, member)
|
|
238
|
+
member_method_keys(member).map { |method_name, kind| [class_name, method_name, kind] }
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# The `.rbs` line is read only for an outcome that reports it: asking an `RBS::Buffer` for a line
|
|
242
|
+
# builds that buffer's whole line table, a cost a silent merge has no use for.
|
|
243
|
+
def record(key, verdict, path, sig_member, virtual_name)
|
|
244
|
+
line = ERROR_OUTCOMES.include?(verdict[0]) ? member_line(sig_member) : nil
|
|
245
|
+
Record.new(
|
|
246
|
+
class_name: key[0], method_name: key[1], kind: key[2], outcome: verdict[0], detail: verdict[1],
|
|
247
|
+
signature_path: path, signature_line: line, virtual_name: virtual_name
|
|
248
|
+
)
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def record_signature_refinements(state, class_name, sig_member, path)
|
|
252
|
+
return if state[:checked].key?(sig_member)
|
|
253
|
+
|
|
254
|
+
state[:checked][sig_member] = true
|
|
255
|
+
state[:records].concat(refinement_records(state, class_name, sig_member, path, nil))
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# `path` is the `.rbs` file for a `sig/` member (whose line is then read) and nil for an inline one.
|
|
259
|
+
def refinement_records(state, class_name, member, path, virtual_name)
|
|
260
|
+
conflicts = state[:comparator].refinement_conflicts(member)
|
|
261
|
+
return NO_RECORDS if conflicts.empty?
|
|
262
|
+
|
|
263
|
+
method_name, kind = member_method_keys(member).first || [member_name(member), :instance]
|
|
264
|
+
line = path && member_line(member)
|
|
265
|
+
conflicts.map do |detail|
|
|
266
|
+
Record.new(class_name: class_name, method_name: method_name, kind: kind, outcome: :refinement,
|
|
267
|
+
detail: detail, signature_path: path, signature_line: line, virtual_name: virtual_name)
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def member_name(member)
|
|
272
|
+
member.respond_to?(:name) ? member.name : member.new_name
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def member_line(member)
|
|
276
|
+
location = member.respond_to?(:location) ? member.location : nil
|
|
277
|
+
location.respond_to?(:start_line) ? location.start_line : nil
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# `Symbol#name` and `nil.to_s` are frozen, so the key allocates nothing but itself.
|
|
281
|
+
def record_sort_key(record)
|
|
282
|
+
[record.class_name, record.method_name.name, record.kind.name, record.outcome.name,
|
|
283
|
+
record.virtual_name.to_s, record.signature_path.to_s, record.detail.to_s]
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def method_definition_keys(member)
|
|
287
|
+
return [] if member.respond_to?(:overloading?) && member.overloading?
|
|
288
|
+
|
|
289
|
+
case member.kind
|
|
290
|
+
when :instance then [[member.name, :instance]]
|
|
291
|
+
when :singleton then [[member.name, :singleton]]
|
|
292
|
+
else [[member.name, :instance], [member.name, :singleton]] # `def self?.x` defines both sides
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
end
|
|
@@ -37,12 +37,12 @@ module Rigor
|
|
|
37
37
|
module MissingGemConstantIndex
|
|
38
38
|
module_function
|
|
39
39
|
|
|
40
|
-
# @param gems
|
|
40
|
+
# @param gems — `[gem_name, version]` pairs (the `:missing` rows of
|
|
41
41
|
# {RbsCoverageReport}).
|
|
42
|
-
# @param bundle_path
|
|
43
|
-
# @param spec_resolver
|
|
42
|
+
# @param bundle_path — the target's resolved bundler install root, or nil.
|
|
43
|
+
# @param spec_resolver — `(name, version) -> String?` fallback dir resolver. Injectable for
|
|
44
44
|
# specs; the default is the RubyGems-metadata lookup (no code load).
|
|
45
|
-
# @return
|
|
45
|
+
# @return frozen `root constant name => gem name`. On a collision (two gems
|
|
46
46
|
# declaring the same top-level constant) the first gem wins — the CAUSE recorded downstream
|
|
47
47
|
# (external gem without RBS) is true under either owner.
|
|
48
48
|
def build(gems, bundle_path: nil, spec_resolver: method(:installed_gem_dir))
|
|
@@ -37,17 +37,17 @@ module Rigor
|
|
|
37
37
|
DEFAULT_COLLECTION_PATH = ".gem_rbs_collection"
|
|
38
38
|
private_constant :DEFAULT_COLLECTION_PATH
|
|
39
39
|
|
|
40
|
-
# @param lockfile_path
|
|
40
|
+
# @param lockfile_path — explicit path to `rbs_collection.lock.yaml`. When `nil`,
|
|
41
41
|
# falls back to `auto_detect` if `auto_detect:` is true.
|
|
42
|
-
# @param project_root
|
|
42
|
+
# @param project_root — resolution base for relative `lockfile_path:` and the auto-detect
|
|
43
43
|
# search.
|
|
44
|
-
# @param auto_detect
|
|
44
|
+
# @param auto_detect — when true and `lockfile_path:` is nil, look for
|
|
45
45
|
# `<project_root>/rbs_collection.lock.yaml`.
|
|
46
|
-
# @param skip_gem_names
|
|
46
|
+
# @param skip_gem_names — gem names rigor already loads from its bundled
|
|
47
47
|
# stdlib (the merged `DEFAULT_LIBRARIES + libraries:` set). Entries whose `name` is in this set are
|
|
48
48
|
# dropped regardless of `source.type` to avoid `RBS::DuplicatedDeclarationError` on
|
|
49
49
|
# stdlib-extracted default gems. Defaults to empty.
|
|
50
|
-
# @return
|
|
50
|
+
# @return every `<collection_path>/<gem-name>/<gem-version>/` directory listed in the
|
|
51
51
|
# lockfile whose entry has a non-skipped source type, whose `name` is not in `skip_gem_names:`, and
|
|
52
52
|
# whose directory exists on disk. Returns `[]` when no lockfile is resolvable, when the YAML is
|
|
53
53
|
# unreadable, or when the collection path doesn't exist.
|
|
@@ -35,16 +35,16 @@ module Rigor
|
|
|
35
35
|
"idn-ruby", "mysql2", "nokogiri", "pg", "prism", "racc", "redis", "rubygems"
|
|
36
36
|
].freeze
|
|
37
37
|
|
|
38
|
-
# @param locked_gems
|
|
38
|
+
# @param locked_gems — The lockfile-resolved gem set. Empty
|
|
39
39
|
# hash → no coverage analysis to do.
|
|
40
|
-
# @param default_libraries
|
|
40
|
+
# @param default_libraries — gem names rigor auto-loads through
|
|
41
41
|
# `RBS::EnvironmentLoader#add(library:)`. Pass `Rigor::Environment::DEFAULT_LIBRARIES` from callers
|
|
42
42
|
# running in a project context.
|
|
43
|
-
# @param bundle_sig_paths
|
|
43
|
+
# @param bundle_sig_paths — the discovered `<bundle>/.../gems/<name>-<ver>/sig`
|
|
44
44
|
# paths from {BundleSigDiscovery.discover}.
|
|
45
|
-
# @param rbs_collection_paths
|
|
45
|
+
# @param rbs_collection_paths — the discovered `<collection>/<name>/<version>/`
|
|
46
46
|
# paths from {RbsCollectionDiscovery.discover}.
|
|
47
|
-
# @return
|
|
47
|
+
# @return one row per locked gem; sorted by gem name for deterministic output.
|
|
48
48
|
def self.classify(locked_gems:, default_libraries:,
|
|
49
49
|
bundle_sig_paths:, rbs_collection_paths:)
|
|
50
50
|
default_set = default_libraries.to_set
|
|
@@ -63,8 +63,10 @@ module Rigor
|
|
|
63
63
|
@ancestor_names_cache[key] = loader.ancestor_names_for(key)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
# Allocates only when there is a prefix to strip (see `Environment#normalize_class_name`).
|
|
66
67
|
def normalize_name(name)
|
|
67
|
-
name.to_s
|
|
68
|
+
name = name.to_s
|
|
69
|
+
name.start_with?("::") ? name.delete_prefix("::") : name
|
|
68
70
|
end
|
|
69
71
|
end
|
|
70
72
|
end
|