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,189 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "prism"
|
|
4
|
+
|
|
5
|
+
require_relative "../../inference/scope_indexer"
|
|
6
|
+
require_relative "../../source/constant_path"
|
|
7
|
+
require_relative "../../source/node_children"
|
|
8
|
+
|
|
9
|
+
module Rigor
|
|
10
|
+
module Analysis
|
|
11
|
+
module CheckRules
|
|
12
|
+
# Issue #1120 — the two ways one file makes a method callable at some sites and not at others, which
|
|
13
|
+
# `call.undefined-method` has to ask the file's syntax about because no project-wide table can answer:
|
|
14
|
+
#
|
|
15
|
+
# - **Refinements.** `using M` activates M's refinements from the end of the call to the end of the body
|
|
16
|
+
# that holds it — the file's top level or a `class` / `module` body, including everything nested in it —
|
|
17
|
+
# and nowhere else, not even in another file. A `refine X do … end` block is active inside itself. What
|
|
18
|
+
# each module refines is the project-wide `Scope#discovered_refinements`; this answers whether any of
|
|
19
|
+
# those modules is in effect at a call site. A `using` whose argument is not a constant
|
|
20
|
+
# (`using Module.new { refine … }`) names no module, so every refinement counts as in effect throughout
|
|
21
|
+
# its file. A `using` inside a `def` raises in Ruby and activates nothing.
|
|
22
|
+
# - **Singleton defs on locals.** `def o.m` defines `m` on the one object `o` holds. The local's type
|
|
23
|
+
# is not changed; `o.m` is simply not reported within the scope the `def` is written in (the
|
|
24
|
+
# enclosing `def`, `class` / `module` body, or file — a block shares its enclosing scope's locals).
|
|
25
|
+
#
|
|
26
|
+
# Built lazily: the walk runs the first time a would-fire call asks, so a file with no such call pays
|
|
27
|
+
# one small object and nothing else.
|
|
28
|
+
class LexicalMethodSites
|
|
29
|
+
def initialize(root)
|
|
30
|
+
@root = root
|
|
31
|
+
@built = false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Is a refinement from one of `modules` (refining-module names) in effect at `call_node`?
|
|
35
|
+
def refinement_active?(call_node, modules)
|
|
36
|
+
build
|
|
37
|
+
return true if @unresolved_using
|
|
38
|
+
|
|
39
|
+
offset = call_node.location.start_offset
|
|
40
|
+
return true if @refine_blocks.any? { |start, stop| offset >= start && offset < stop }
|
|
41
|
+
|
|
42
|
+
@usings.any? do |start, stop, candidates|
|
|
43
|
+
offset >= start && offset < stop && candidates.any? { |name| modules.include?(name) }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Issue #1367 — is any refinement in effect at `node`: a `using` of any module, a `using` of a non-constant, or
|
|
48
|
+
# the inside of a `refine` block? The `global.*` stream check asks it where it cannot name the refining
|
|
49
|
+
# module (a `define_method` or `alias_method` inside `refine` records none).
|
|
50
|
+
def using_in_effect?(node)
|
|
51
|
+
build
|
|
52
|
+
return true if @unresolved_using
|
|
53
|
+
|
|
54
|
+
offset = node.location.start_offset
|
|
55
|
+
@refine_blocks.any? { |start, stop| offset >= start && offset < stop } ||
|
|
56
|
+
@usings.any? { |start, stop, _candidates| offset >= start && offset < stop }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Is `def_node` one of the defs a `refine X do … end` body defines on X? Such a def redefines X's method by
|
|
60
|
+
# design, so X's declared signature for the name is not its contract (issue #1120, maintainer ruling a′).
|
|
61
|
+
def refinement_def?(def_node)
|
|
62
|
+
build
|
|
63
|
+
@refinement_defs.include?(def_node.location.start_offset)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Does a `def <local>.<name>` for this call's local receiver and method name sit in the scope the call
|
|
67
|
+
# is in?
|
|
68
|
+
def singleton_local_def?(call_node)
|
|
69
|
+
receiver = call_node.receiver
|
|
70
|
+
return false unless receiver.is_a?(Prism::LocalVariableReadNode)
|
|
71
|
+
|
|
72
|
+
build
|
|
73
|
+
offset = call_node.location.start_offset
|
|
74
|
+
@singleton_defs.any? do |local, method_name, start, stop|
|
|
75
|
+
local == receiver.name && method_name == call_node.name && offset >= start && offset < stop &&
|
|
76
|
+
!nested_scope_holds?(offset, start, stop)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
# Is `offset` inside a local scope nested in the one `[start, stop)` spans? A `def` in the file's top level
|
|
83
|
+
# does not see the top level's `o`.
|
|
84
|
+
def nested_scope_holds?(offset, start, stop)
|
|
85
|
+
@scopes.any? do |inner_start, inner_stop|
|
|
86
|
+
(inner_start > start || inner_stop < stop) && inner_start >= start && inner_stop <= stop &&
|
|
87
|
+
offset >= inner_start && offset < inner_stop
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def build
|
|
92
|
+
return if @built
|
|
93
|
+
|
|
94
|
+
@built = true
|
|
95
|
+
@usings = []
|
|
96
|
+
@refine_blocks = []
|
|
97
|
+
@singleton_defs = []
|
|
98
|
+
@scopes = []
|
|
99
|
+
@refinement_defs = Set.new
|
|
100
|
+
@unresolved_using = false
|
|
101
|
+
return if @root.nil?
|
|
102
|
+
|
|
103
|
+
location = @root.location
|
|
104
|
+
span = [location.start_offset, location.end_offset]
|
|
105
|
+
walk(@root, [], span, span, false)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# `body` is the `[start, end]` of the body a `using` here stays in effect to the end of; `locals` is the
|
|
109
|
+
# span of the scope a local written here belongs to.
|
|
110
|
+
def walk(node, prefix, body, locals, in_def)
|
|
111
|
+
case node
|
|
112
|
+
when Prism::ClassNode, Prism::ModuleNode
|
|
113
|
+
span = scope_span(node)
|
|
114
|
+
inner = Source::ConstantPath.declaration_prefix(prefix, node.constant_path) || prefix
|
|
115
|
+
return walk_children(node.body, inner, span, span, false)
|
|
116
|
+
when Prism::SingletonClassNode
|
|
117
|
+
walk(node.expression, prefix, body, locals, in_def)
|
|
118
|
+
span = scope_span(node)
|
|
119
|
+
return walk_children(node.body, prefix, span, span, false)
|
|
120
|
+
when Prism::DefNode
|
|
121
|
+
record_singleton_def(node, locals)
|
|
122
|
+
return walk_children(node.body, prefix, body, scope_span(node), true)
|
|
123
|
+
when Prism::CallNode
|
|
124
|
+
record_call(node, prefix, body, in_def)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
walk_children(node, prefix, body, locals, in_def)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def walk_children(node, prefix, body, locals, in_def)
|
|
131
|
+
return if node.nil?
|
|
132
|
+
|
|
133
|
+
node.rigor_each_child { |child| walk(child, prefix, body, locals, in_def) }
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def record_singleton_def(node, locals)
|
|
137
|
+
receiver = node.receiver
|
|
138
|
+
return unless receiver.is_a?(Prism::LocalVariableReadNode)
|
|
139
|
+
|
|
140
|
+
@singleton_defs << [receiver.name, node.name, *locals]
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def record_call(node, prefix, body, in_def)
|
|
144
|
+
if Inference::ScopeIndexer.refine_target(node)
|
|
145
|
+
@refine_blocks << span_of(node.block)
|
|
146
|
+
record_refinement_defs(node.block.body)
|
|
147
|
+
elsif using_call?(node) && !in_def
|
|
148
|
+
record_using(node, prefix, body)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def record_refinement_defs(body)
|
|
153
|
+
return if body.nil?
|
|
154
|
+
|
|
155
|
+
Inference::ScopeIndexer.each_refinement_def(body) do |def_node|
|
|
156
|
+
@refinement_defs << def_node.location.start_offset
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def using_call?(node)
|
|
161
|
+
node.name == :using && (node.receiver.nil? || node.receiver.is_a?(Prism::SelfNode)) &&
|
|
162
|
+
node.arguments&.arguments&.size == 1
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def record_using(node, prefix, body)
|
|
166
|
+
argument = node.arguments.arguments.first
|
|
167
|
+
if argument.is_a?(Prism::ConstantReadNode) || argument.is_a?(Prism::ConstantPathNode)
|
|
168
|
+
candidates = Inference::ScopeIndexer.constant_receiver_candidates(argument, prefix)
|
|
169
|
+
@usings << [node.location.end_offset, body.last, candidates]
|
|
170
|
+
else
|
|
171
|
+
@unresolved_using = true
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# The span of a node that opens a local scope, recorded for {#nested_scope_holds?}.
|
|
176
|
+
def scope_span(node)
|
|
177
|
+
span = span_of(node)
|
|
178
|
+
@scopes << span
|
|
179
|
+
span
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def span_of(node)
|
|
183
|
+
location = node.location
|
|
184
|
+
[location.start_offset, location.end_offset]
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
@@ -19,13 +19,15 @@ module Rigor
|
|
|
19
19
|
# accumulated {Diagnostic}s, in the same emission order the inline `NodeWalker.each` produced them (the
|
|
20
20
|
# shared walk is the same visit-before-descend DFS over `compact_child_nodes`).
|
|
21
21
|
class MainPassCollector
|
|
22
|
-
# The node classes the
|
|
23
|
-
#
|
|
22
|
+
# The node classes the main pass branches on. A plain `Prism::IfNode` covers ternaries and postfix `if`
|
|
23
|
+
# too (the legacy `when Prism::IfNode, Prism::UnlessNode` arm did the same). The three global-write
|
|
24
|
+
# classes carry issue #1367's `global.*` rules.
|
|
24
25
|
NODE_CLASSES = [
|
|
25
|
-
Prism::CallNode, Prism::DefNode, Prism::IfNode, Prism::UnlessNode
|
|
26
|
+
Prism::CallNode, Prism::DefNode, Prism::IfNode, Prism::UnlessNode,
|
|
27
|
+
Prism::GlobalVariableWriteNode, Prism::GlobalVariableOperatorWriteNode, Prism::MultiWriteNode
|
|
26
28
|
].freeze
|
|
27
29
|
|
|
28
|
-
# @param node_diagnostics
|
|
30
|
+
# @param node_diagnostics — maps a `Prism::Node` to the array of diagnostics the main pass emits
|
|
29
31
|
# for it.
|
|
30
32
|
def initialize(node_diagnostics)
|
|
31
33
|
@node_diagnostics = node_diagnostics
|
|
@@ -50,11 +50,18 @@ module Rigor
|
|
|
50
50
|
# passage is the precedent for stopping at one hop rather than building a provenance channel through
|
|
51
51
|
# the return memo.
|
|
52
52
|
#
|
|
53
|
-
#
|
|
54
|
-
# into an ivar (`@mode = MODE` in `initialize`), or
|
|
55
|
-
# (`MODE2 = AppConfig::MODE`).
|
|
56
|
-
#
|
|
57
|
-
#
|
|
53
|
+
# - a value COPIED out of such a constant before the predicate reads it (issue #667) — into a local
|
|
54
|
+
# (`m = AppConfig::MODE; m == :x`), into an ivar (`@mode = AppConfig::MODE` in `initialize`), or
|
|
55
|
+
# through a same-file alias (`MODE2 = AppConfig::MODE`). A copy has no spelling for the root walk to
|
|
56
|
+
# recognise, so the provenance is stamped on the value where the copy happens and travels with it:
|
|
57
|
+
# the first two on the `Scope` flow carrier `published_constant_sourced` (dropped by any rebinding,
|
|
58
|
+
# unioned at a join), the alias on the per-file `published_constant_alias_names` census table, which
|
|
59
|
+
# needs no flow machinery at all because a constant write is not flow. This walk only READS those
|
|
60
|
+
# marks — the widening ADR-58's *Non-transitivity* passage forbids is inferring one AT a consumer,
|
|
61
|
+
# and the establishing transitions are named in
|
|
62
|
+
# `docs/internal-spec/inference-engine.md` § "The truthiness withholding".
|
|
63
|
+
#
|
|
64
|
+
# Deliberately NOT covered: two interprocedural hops (`live? -> prod? -> MODE`).
|
|
58
65
|
module PublishedConstantGuard
|
|
59
66
|
# A defensive depth cap against a pathological chain (the walk is otherwise linear in chain length).
|
|
60
67
|
MAX_DEPTH = 64
|
|
@@ -66,13 +73,15 @@ module Rigor
|
|
|
66
73
|
|
|
67
74
|
module_function
|
|
68
75
|
|
|
69
|
-
# @return
|
|
76
|
+
# @return true when the rule MUST withhold its firing.
|
|
70
77
|
def rooted?(node, scope, depth = 0)
|
|
71
78
|
return false if node.nil? || depth > MAX_DEPTH || scope.nil?
|
|
72
79
|
|
|
73
80
|
case node
|
|
74
81
|
when Prism::ConstantReadNode then scope.published_constant?(node.name.to_s)
|
|
75
82
|
when Prism::ConstantPathNode then published_path?(node, scope)
|
|
83
|
+
when Prism::LocalVariableReadNode then scope.published_constant_sourced?(:local, node.name)
|
|
84
|
+
when Prism::InstanceVariableReadNode then scope.published_constant_sourced?(:ivar, node.name)
|
|
76
85
|
when Prism::CallNode then rooted_call?(node, scope, depth)
|
|
77
86
|
else rooted_through_composition?(node, scope, depth)
|
|
78
87
|
end
|
|
@@ -6,9 +6,9 @@ module Rigor
|
|
|
6
6
|
# Canonical identifiers for each rule. Per ADR-8 § "Diagnostic ID family hierarchy", rule names are
|
|
7
7
|
# `family.rule-name` two-segment strings; the families group diagnostics by where they originate
|
|
8
8
|
# (`call.*` for call-site rules, `flow.*` for flow-analysis proofs, `assert.*` for runtime-assertion
|
|
9
|
-
# rules, `dump.*` for debug helpers, `def.*` for method-definition rules
|
|
10
|
-
# `disable:` list and the in-source `# rigor:disable <rule>`
|
|
11
|
-
# register here so user configuration can refer to them.
|
|
9
|
+
# rules, `dump.*` for debug helpers, `def.*` for method-definition rules, `global.*` for writes to special
|
|
10
|
+
# globals). Used by the configuration `disable:` list and the in-source `# rigor:disable <rule>`
|
|
11
|
+
# suppression comment system; new rules MUST register here so user configuration can refer to them.
|
|
12
12
|
#
|
|
13
13
|
# ADR-87 WD4 — this pure-data constant table is split out of the (engine-heavy) `check_rules.rb` so
|
|
14
14
|
# {Analysis::RuleCatalog} — which the CLI's JSON `evidence_tier` / `documentation_url` enrichment reads
|
|
@@ -66,6 +66,18 @@ module Rigor
|
|
|
66
66
|
# annotation must never turn collection on by itself (that would be a project-wide cost cliff
|
|
67
67
|
# nobody asked for), and it must equally never be silently inert.
|
|
68
68
|
RULE_EFFECT_ANNOTATIONS_UNCHECKED = "effect.annotations-unchecked"
|
|
69
|
+
# ADR-112 WD5 / #1075 — two statements of one member's contract that contradict: a `sig/` declaration
|
|
70
|
+
# against an inline `@rbs` / `#:` one (and, once #1073 reads it, `@rbs` / `#:` against `@extrbs`), or a
|
|
71
|
+
# `rigor:v1:` refinement outside the member's own declared type. `rbs.` because the finding is about
|
|
72
|
+
# the RBS the environment is built from, whichever file spelled it; not `rbs_extended.`, whose rows
|
|
73
|
+
# are payload validity, since most contradictions involve no `RBS::Extended` annotation at all.
|
|
74
|
+
RULE_CONTRADICTING_SIGNATURE = "rbs.contradicting-signature"
|
|
75
|
+
# Issue #1367 (ADR-117 WD2) — the `global.*` family: a write to a special global that its setter rejects, so
|
|
76
|
+
# the write raises on every run. Two ids so a project can tune the type check without hiding read-only
|
|
77
|
+
# writes; the `write` wording follows `def.ivar-write-mismatch`. The envelope is the interpreter's setter
|
|
78
|
+
# (`SpecialGlobalSetters`), not the global's RBS declaration.
|
|
79
|
+
RULE_GLOBAL_WRITE_TYPE_MISMATCH = "global.write-type-mismatch"
|
|
80
|
+
RULE_GLOBAL_READONLY_WRITE = "global.readonly-write"
|
|
69
81
|
|
|
70
82
|
ALL_RULES = [
|
|
71
83
|
RULE_UNDEFINED_METHOD,
|
|
@@ -91,6 +103,8 @@ module Rigor
|
|
|
91
103
|
RULE_OVERRIDE_RETURN_WIDENED,
|
|
92
104
|
RULE_OVERRIDE_PARAM_NARROWED,
|
|
93
105
|
RULE_IVAR_WRITE_MISMATCH,
|
|
106
|
+
RULE_GLOBAL_WRITE_TYPE_MISMATCH,
|
|
107
|
+
RULE_GLOBAL_READONLY_WRITE,
|
|
94
108
|
RULE_SUPPRESSION_UNKNOWN_RULE,
|
|
95
109
|
RULE_SUPPRESSION_EMPTY,
|
|
96
110
|
RULE_SUPPRESSION_UNKNOWN_MARKER,
|
|
@@ -98,7 +112,8 @@ module Rigor
|
|
|
98
112
|
RULE_EFFECT_ENVELOPE_EXCEEDED,
|
|
99
113
|
RULE_EFFECT_LISKOV_WIDENED,
|
|
100
114
|
RULE_EFFECT_UNKNOWN_LABEL,
|
|
101
|
-
RULE_EFFECT_ANNOTATIONS_UNCHECKED
|
|
115
|
+
RULE_EFFECT_ANNOTATIONS_UNCHECKED,
|
|
116
|
+
RULE_CONTRADICTING_SIGNATURE
|
|
102
117
|
].freeze
|
|
103
118
|
|
|
104
119
|
# Backward-compat alias table (ADR-8 § "Backward compatibility"). Existing user code with
|
|
@@ -128,7 +143,7 @@ module Rigor
|
|
|
128
143
|
|
|
129
144
|
# Family wildcard — a `<family>` token in a suppression comment or `disable:` list disables every rule
|
|
130
145
|
# whose canonical id starts with `<family>.`. Per ADR-8 § "1".
|
|
131
|
-
RULE_FAMILIES = %w[call flow assert dump def suppression static effect].freeze
|
|
146
|
+
RULE_FAMILIES = %w[call flow assert dump def global suppression static effect].freeze
|
|
132
147
|
|
|
133
148
|
# Families of diagnostics the engine emits OUTSIDE the CheckRules catalogue (aggregator-level and
|
|
134
149
|
# reporter-level diagnostics such as `rbs_extended.unsatisfied-conformance`,
|
|
@@ -137,7 +152,7 @@ module Rigor
|
|
|
137
152
|
# first segment appears here as KNOWN and stays silent: these ids are legitimate suppression /
|
|
138
153
|
# `severity_overrides:` vocabulary the light rule-id table cannot enumerate (plugins load dynamically;
|
|
139
154
|
# aggregator ids live in the engine-heavy runner), so under-warning is the FP-safe direction.
|
|
140
|
-
NON_CHECK_DIAGNOSTIC_FAMILIES = %w[rbs_extended dynamic rbs pre-eval plugin].freeze
|
|
155
|
+
NON_CHECK_DIAGNOSTIC_FAMILIES = %w[rbs_extended dynamic rbs pre-eval plugin plugin_trust].freeze
|
|
141
156
|
|
|
142
157
|
# Bare (dot-less) diagnostic ids the engine emits outside the catalogue (see the `rule:` literals in
|
|
143
158
|
# `Analysis::Runner` / `Runner::DiagnosticAggregator`). A token equal to one of these is treated as
|
|
@@ -40,11 +40,27 @@ module Rigor
|
|
|
40
40
|
|
|
41
41
|
CLASS_OR_MODULE_NODE_CLASSES = [Prism::ClassNode, Prism::ModuleNode].freeze
|
|
42
42
|
|
|
43
|
+
# Issue #909 — the receivers whose block form opens a class body that is NOT the lexically enclosing
|
|
44
|
+
# class: `Class.new do … end`, `Module.new`, `Struct.new`, `Data.define`. A `def` in such a block
|
|
45
|
+
# belongs to the anonymous class the call returns, so its ivar writes are a different store from the
|
|
46
|
+
# enclosing class's.
|
|
47
|
+
DETACHED_CLASS_FACTORIES = {
|
|
48
|
+
Class: %i[new],
|
|
49
|
+
Module: %i[new],
|
|
50
|
+
Struct: %i[new],
|
|
51
|
+
Data: %i[define]
|
|
52
|
+
}.freeze
|
|
53
|
+
Ractor.make_shareable(DETACHED_CLASS_FACTORIES)
|
|
54
|
+
private_constant :DETACHED_CLASS_FACTORIES
|
|
55
|
+
|
|
56
|
+
EMPTY_METHODS = [].freeze
|
|
57
|
+
private_constant :EMPTY_METHODS
|
|
58
|
+
|
|
43
59
|
# The immutable per-node descent context. Recomputed for each child from its parent's context as the
|
|
44
60
|
# walk descends; collectors read only the fields they declared a need for.
|
|
45
|
-
Context = Data.define(:in_loop_or_block, :qualified_prefix, :inside_def) do
|
|
61
|
+
Context = Data.define(:in_loop_or_block, :qualified_prefix, :inside_def, :detached_ivar_facet) do
|
|
46
62
|
def self.root
|
|
47
|
-
new(in_loop_or_block: false, qualified_prefix: [], inside_def: false)
|
|
63
|
+
new(in_loop_or_block: false, qualified_prefix: [], inside_def: false, detached_ivar_facet: false)
|
|
48
64
|
end
|
|
49
65
|
end
|
|
50
66
|
|
|
@@ -58,9 +74,13 @@ module Rigor
|
|
|
58
74
|
# - `:inside_def` (`inside_def`) — lexically inside a `DefNode`; IvarWrite collects only at a `def`
|
|
59
75
|
# that sits directly in a class / module body (its legacy walk `return`s at the first `def` it
|
|
60
76
|
# meets, so a nested def is never reached).
|
|
77
|
+
# - `:detached_ivar_facet` (`detached_ivar_facet`) — under a `class << self` body or an
|
|
78
|
+
# anonymous-class factory block, where the enclosing class name does not name the ivar store the
|
|
79
|
+
# body writes to.
|
|
61
80
|
GATE_CONTEXT_PREDICATES = {
|
|
62
81
|
loop_or_block: :in_loop_or_block,
|
|
63
|
-
inside_def: :inside_def
|
|
82
|
+
inside_def: :inside_def,
|
|
83
|
+
detached_ivar_facet: :detached_ivar_facet
|
|
64
84
|
}.freeze
|
|
65
85
|
|
|
66
86
|
# A per-node driver over a fixed collector set: holds the compiled `node_class => [[collector,
|
|
@@ -89,7 +109,7 @@ module Rigor
|
|
|
89
109
|
end
|
|
90
110
|
end
|
|
91
111
|
|
|
92
|
-
#
|
|
112
|
+
# Mirrors {RuleWalk.descend}.
|
|
93
113
|
def descend(node, context)
|
|
94
114
|
RuleWalk.descend(node, context)
|
|
95
115
|
end
|
|
@@ -124,14 +144,30 @@ module Rigor
|
|
|
124
144
|
LOOP_OR_BLOCK_NODE_CLASSES.any? { |klass| node.is_a?(klass) }
|
|
125
145
|
inside_def = context.inside_def || node.is_a?(Prism::DefNode)
|
|
126
146
|
qualified_prefix = extend_prefix(node, context.qualified_prefix)
|
|
147
|
+
detached_ivar_facet = context.detached_ivar_facet || detached_ivar_facet?(node)
|
|
127
148
|
|
|
128
149
|
Context.new(
|
|
129
150
|
in_loop_or_block: in_loop_or_block,
|
|
130
151
|
qualified_prefix: qualified_prefix,
|
|
131
|
-
inside_def: inside_def
|
|
152
|
+
inside_def: inside_def,
|
|
153
|
+
detached_ivar_facet: detached_ivar_facet
|
|
132
154
|
)
|
|
133
155
|
end
|
|
134
156
|
|
|
157
|
+
# True for a node whose descendants write ivars to a store the enclosing class name does not name:
|
|
158
|
+
# a `class << self` body (the class object's own ivars) or a call that builds an anonymous class
|
|
159
|
+
# from a block. Every singleton-class body counts, `class << Konstant` included: whichever object's
|
|
160
|
+
# singleton it opens, it is not the instance facet the enclosing prefix names.
|
|
161
|
+
def detached_ivar_facet?(node)
|
|
162
|
+
return true if node.is_a?(Prism::SingletonClassNode)
|
|
163
|
+
return false unless node.is_a?(Prism::CallNode) && node.block.is_a?(Prism::BlockNode)
|
|
164
|
+
|
|
165
|
+
receiver = node.receiver
|
|
166
|
+
return false unless receiver.is_a?(Prism::ConstantReadNode)
|
|
167
|
+
|
|
168
|
+
DETACHED_CLASS_FACTORIES.fetch(receiver.name, EMPTY_METHODS).include?(node.name)
|
|
169
|
+
end
|
|
170
|
+
|
|
135
171
|
private
|
|
136
172
|
|
|
137
173
|
def collector_gates(collector)
|
|
@@ -58,7 +58,7 @@ module Rigor
|
|
|
58
58
|
# Legacy single-collector walk — the oracle the shadow harness (`RIGOR_SHADOW_RULE_WALK=1`) compares
|
|
59
59
|
# the shared {RuleWalk} traversal against. Tracks the lexical class / module prefix itself, exactly
|
|
60
60
|
# as {RuleWalk} threads `qualified_prefix`.
|
|
61
|
-
# @return
|
|
61
|
+
# @return one entry per provably-shadowed rescue clause.
|
|
62
62
|
def collect(root)
|
|
63
63
|
walk(root, [])
|
|
64
64
|
@results.freeze
|