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
|
@@ -16,7 +16,24 @@ module Rigor
|
|
|
16
16
|
# The audit deliberately mirrors the loader's own acceptance test (`path.directory?` + a
|
|
17
17
|
# recursive `**/*.rbs` glob) so a `:ok` verdict means the loader did load from it and a
|
|
18
18
|
# warning means it did not.
|
|
19
|
+
#
|
|
20
|
+
# {.bundled_plugin_routes} answers the mirror-image question — an entry that loads too
|
|
21
|
+
# *little of the plugin*, rather than nothing at all. See its own comment.
|
|
19
22
|
module SignaturePathAudit
|
|
23
|
+
# The `plugins/` tree of the engine running this code, anchored from THIS file
|
|
24
|
+
# (`<root>/lib/rigor/signature_path_audit.rb`) so a git checkout and an installed
|
|
25
|
+
# `rigortype` gem answer identically — the anchor {Plugin::Loader::ENGINE_ROOT} uses, for
|
|
26
|
+
# the reason it documents.
|
|
27
|
+
#
|
|
28
|
+
# Deliberately re-derived rather than read off `Plugin::Loader`: ADR-87 WD4 keeps this
|
|
29
|
+
# file, which every `rigor check` loads before the cache probe, off the plugin
|
|
30
|
+
# subsystem's require graph — and that graph is order-dependent (`plugin/registry.rb`
|
|
31
|
+
# resolves `NodeRuleWalk` at load, which only `rigor/plugin.rb` has required by then), so
|
|
32
|
+
# requiring the loader from here fails outright. `signature_path_audit_spec` pins the two
|
|
33
|
+
# anchors equal, and pins this discovery against `Loader.bundled_plugin_sig_path`, so the
|
|
34
|
+
# duplication cannot drift unnoticed.
|
|
35
|
+
BUNDLED_PLUGINS_ROOT = File.expand_path("../../plugins", __dir__).freeze
|
|
36
|
+
|
|
20
37
|
# One configured `signature_paths:` entry's resolution status.
|
|
21
38
|
#
|
|
22
39
|
# `status` is one of:
|
|
@@ -60,17 +77,11 @@ module Rigor
|
|
|
60
77
|
# `nil` — the unset default, where Rigor auto-detects `<root>/sig` — to get an empty
|
|
61
78
|
# result: an absent auto-detected `sig/` is a normal setup, not a misconfiguration, so it
|
|
62
79
|
# is never audited.
|
|
63
|
-
#
|
|
64
|
-
# @param signature_paths [Array<String, Pathname>, nil]
|
|
65
|
-
# @return [Array<Entry>]
|
|
66
80
|
def self.audit(signature_paths)
|
|
67
81
|
Array(signature_paths).map { |path| classify(path.to_s) }
|
|
68
82
|
end
|
|
69
83
|
|
|
70
84
|
# The subset of {audit} that resolved to nothing — the entries worth warning about.
|
|
71
|
-
#
|
|
72
|
-
# @param signature_paths [Array<String, Pathname>, nil]
|
|
73
|
-
# @return [Array<Entry>]
|
|
74
85
|
def self.warnings(signature_paths)
|
|
75
86
|
audit(signature_paths).select(&:warning?)
|
|
76
87
|
end
|
|
@@ -82,5 +93,141 @@ module Rigor
|
|
|
82
93
|
count = Dir.glob(File.join(path, "**", "*.rbs")).size
|
|
83
94
|
Entry.new(path: path, status: count.zero? ? :empty : :ok, rbs_file_count: count)
|
|
84
95
|
end
|
|
96
|
+
|
|
97
|
+
# One configured entry that reaches the `sig/` of a plugin THIS engine bundles, while
|
|
98
|
+
# `plugins:` never names that plugin (issue #697).
|
|
99
|
+
BundledPluginRoute = Data.define(:path, :gem) do
|
|
100
|
+
# Names the plugin and the one edit that fixes it. The consequence is spelled out
|
|
101
|
+
# because the symptom the user actually sees is `call.undefined-method` on code that
|
|
102
|
+
# runs — nothing in that row points back at the `signature_paths:` line.
|
|
103
|
+
def message
|
|
104
|
+
"signature_paths: #{path.inspect} loads the signatures of the bundled plugin #{gem.inspect}, " \
|
|
105
|
+
"which `plugins:` does not name — so the plugin's manifest never loads, and the classes it " \
|
|
106
|
+
"declares only partially on purpose (ADR-26 `open_receivers:`) are read as complete, which " \
|
|
107
|
+
"reports methods your code really defines as undefined. " \
|
|
108
|
+
"Add #{gem.inspect} to `plugins:` instead of naming its `sig/` in `signature_paths:`."
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def to_h
|
|
112
|
+
{ "path" => path, "gem" => gem, "message" => message }
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# The mirror image of {.warnings}: an entry the loader reads perfectly well, which
|
|
117
|
+
# nevertheless leaves the user worse off than not configuring it.
|
|
118
|
+
#
|
|
119
|
+
# A bundled plugin ships two halves that only work together — the RBS under its `sig/`,
|
|
120
|
+
# and the manifest that says which of those declarations are deliberately partial
|
|
121
|
+
# (ADR-26 `open_receivers:`). `plugins:` loads both; `signature_paths:` loads only the
|
|
122
|
+
# first, and the partial declarations then read as complete, so a scope the application
|
|
123
|
+
# really defines draws `call.undefined-method`. This is a configuration mistake with no
|
|
124
|
+
# visible cause, so it is reported here rather than fixed by teaching the check rules yet
|
|
125
|
+
# another route to the same protection — which is [#660](https://github.com/rigortype/rigor/issues/660)'s
|
|
126
|
+
# question to settle, not this warning's.
|
|
127
|
+
#
|
|
128
|
+
# **What it asks is what the entry LOADS, not what it looks like**, exactly as
|
|
129
|
+
# `Environment::RbsLoader.bundled_overlay_twin_signatures_loaded?` does for the overlay
|
|
130
|
+
# stand-down: both sides are `File.realpath`'d and matched against the plugin's actual
|
|
131
|
+
# `.rbs` files, so a symlink or a case-variant spelling answers the same as the directory
|
|
132
|
+
# itself, and an entry naming a file (or a directory that does not exist) — which the
|
|
133
|
+
# loader reads nothing from — matches nothing. The two are not single-homed because the
|
|
134
|
+
# overlay-side predicate lives on the RBS loader, and ADR-87 WD4 keeps this file, which
|
|
135
|
+
# every `rigor check` loads before the cache probe, off the engine's require graph.
|
|
136
|
+
#
|
|
137
|
+
# @param signature_paths — {Configuration#signature_paths}; `nil` (the unset default,
|
|
138
|
+
# where Rigor auto-detects `<root>/sig`) is never audited.
|
|
139
|
+
# @param plugins — the raw {Configuration#plugins} list.
|
|
140
|
+
def self.bundled_plugin_routes(signature_paths, plugins = [])
|
|
141
|
+
entries = resolved_entries(signature_paths)
|
|
142
|
+
return [] if entries.empty?
|
|
143
|
+
|
|
144
|
+
root = canonical_path(BUNDLED_PLUGINS_ROOT)
|
|
145
|
+
return [] if root.nil? || entries.none? { |(_, dir)| overlapping?(dir, root) }
|
|
146
|
+
|
|
147
|
+
listed = listed_plugin_names(plugins)
|
|
148
|
+
bundled_plugin_sig_dirs.reject { |gem, _| listed?(gem, listed) }.flat_map do |gem, sig_dir|
|
|
149
|
+
files = canonical_rbs_files(sig_dir)
|
|
150
|
+
next [] if files.empty?
|
|
151
|
+
|
|
152
|
+
entries.filter_map do |(entry, dir)|
|
|
153
|
+
BundledPluginRoute.new(path: entry, gem: gem) if files.any? { |file| under?(file, dir) }
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# `[entry as configured, canonical directory]` for every entry the loader would read from.
|
|
159
|
+
def self.resolved_entries(signature_paths)
|
|
160
|
+
Array(signature_paths).filter_map do |entry|
|
|
161
|
+
dir = canonical_path(entry.to_s)
|
|
162
|
+
[entry.to_s, dir] if dir && File.directory?(dir)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
private_class_method :resolved_entries
|
|
166
|
+
|
|
167
|
+
# Gem name of every plugin the engine bundles that ships signatures, to its `sig/`.
|
|
168
|
+
# Derived from the `plugins/` tree rather than listed, for {Plugin::FirstParty}'s reason:
|
|
169
|
+
# a list would be a second source of truth, and its first drift would silently stop
|
|
170
|
+
# warning about the plugin that drifted.
|
|
171
|
+
def self.bundled_plugin_sig_dirs
|
|
172
|
+
return {} unless File.directory?(BUNDLED_PLUGINS_ROOT)
|
|
173
|
+
|
|
174
|
+
Dir.children(BUNDLED_PLUGINS_ROOT).sort.filter_map do |gem|
|
|
175
|
+
sig = File.join(BUNDLED_PLUGINS_ROOT, gem, "sig")
|
|
176
|
+
[gem, sig] if File.directory?(sig)
|
|
177
|
+
end.to_h
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Every name a `plugins:` entry puts on the record, in both the bare-string and the
|
|
181
|
+
# `gem:` / `id:` hash forms. An `enabled: false` entry counts as named even though it
|
|
182
|
+
# loads nothing: the user has demonstrably found the plugin, and telling them to add what
|
|
183
|
+
# is already there would be worse than staying quiet. Under-warning is this module's
|
|
184
|
+
# standing FP-safe direction.
|
|
185
|
+
def self.listed_plugin_names(plugins)
|
|
186
|
+
Array(plugins).flat_map do |raw|
|
|
187
|
+
case raw
|
|
188
|
+
when String then [raw]
|
|
189
|
+
when Hash
|
|
190
|
+
keyed = raw.to_h { |key, value| [key.to_s, value] }
|
|
191
|
+
[keyed["gem"], keyed["id"]].compact.map(&:to_s)
|
|
192
|
+
else []
|
|
193
|
+
end
|
|
194
|
+
end.to_set
|
|
195
|
+
end
|
|
196
|
+
private_class_method :listed_plugin_names
|
|
197
|
+
|
|
198
|
+
# A bundled plugin's manifest id is its gem name minus the `rigor-` prefix, and `plugins:`
|
|
199
|
+
# accepts either spelling as `id:`, so both count as naming it.
|
|
200
|
+
def self.listed?(gem, listed)
|
|
201
|
+
require_relative "plugin/first_party"
|
|
202
|
+
listed.include?(gem) || listed.include?(gem.delete_prefix(Plugin::FirstParty::GEM_PREFIX))
|
|
203
|
+
end
|
|
204
|
+
private_class_method :listed?
|
|
205
|
+
|
|
206
|
+
def self.canonical_rbs_files(dir)
|
|
207
|
+
Dir.glob(File.join(dir, "**", "*.rbs")).filter_map { |file| canonical_path(file) }
|
|
208
|
+
end
|
|
209
|
+
private_class_method :canonical_rbs_files
|
|
210
|
+
|
|
211
|
+
# `File.realpath`, not `File.expand_path`: it resolves symlinks and, on a case-folding
|
|
212
|
+
# filesystem, the on-disk spelling. It raises for a path that does not exist, which is
|
|
213
|
+
# the answer wanted here — a path the loader cannot read is not a route to anything.
|
|
214
|
+
def self.canonical_path(path)
|
|
215
|
+
File.realpath(path.to_s)
|
|
216
|
+
rescue SystemCallError
|
|
217
|
+
nil
|
|
218
|
+
end
|
|
219
|
+
private_class_method :canonical_path
|
|
220
|
+
|
|
221
|
+
def self.under?(path, dir)
|
|
222
|
+
path.start_with?("#{dir}#{File::SEPARATOR}")
|
|
223
|
+
end
|
|
224
|
+
private_class_method :under?
|
|
225
|
+
|
|
226
|
+
# Whether the two directories could possibly share a file. The cheap prune that keeps the
|
|
227
|
+
# per-plugin globs off every run whose `signature_paths:` point at the project's own tree.
|
|
228
|
+
def self.overlapping?(one, other)
|
|
229
|
+
one == other || under?(one, other) || under?(other, one)
|
|
230
|
+
end
|
|
231
|
+
private_class_method :overlapping?
|
|
85
232
|
end
|
|
86
233
|
end
|
|
@@ -31,9 +31,6 @@ module Rigor
|
|
|
31
31
|
|
|
32
32
|
# The Symbol a literal `Prism::SymbolNode` / `Prism::StringNode` names, or `nil` for any other node
|
|
33
33
|
# (including `nil`).
|
|
34
|
-
#
|
|
35
|
-
# @param node [Prism::Node, nil]
|
|
36
|
-
# @return [Symbol, nil]
|
|
37
34
|
def symbol_or_string(node)
|
|
38
35
|
return nil unless node.is_a?(Prism::SymbolNode) || node.is_a?(Prism::StringNode)
|
|
39
36
|
|
|
@@ -44,9 +41,6 @@ module Rigor
|
|
|
44
41
|
# (including `nil`). The String-returning sibling of {.symbol_or_string} — for callers that key on the
|
|
45
42
|
# raw name rather than the interned Symbol (route helpers, factory names, filter targets).
|
|
46
43
|
# `#unescaped` round-trips an interpolation-free `:foo` / `"foo"` to `"foo"` for both kinds.
|
|
47
|
-
#
|
|
48
|
-
# @param node [Prism::Node, nil]
|
|
49
|
-
# @return [String, nil]
|
|
50
44
|
def symbol_or_string_name(node)
|
|
51
45
|
return nil unless node.is_a?(Prism::SymbolNode) || node.is_a?(Prism::StringNode)
|
|
52
46
|
|
|
@@ -56,9 +50,6 @@ module Rigor
|
|
|
56
50
|
# The Symbol a literal `Prism::SymbolNode` names, or `nil` for any other node (including a
|
|
57
51
|
# `Prism::StringNode` and `nil`). Stricter than {.symbol_or_string}: a DSL that accepts only `:draft`
|
|
58
52
|
# and not `"draft"` keeps that distinction by reaching for this rather than the Symbol-or-String form.
|
|
59
|
-
#
|
|
60
|
-
# @param node [Prism::Node, nil]
|
|
61
|
-
# @return [Symbol, nil]
|
|
62
53
|
def symbol(node)
|
|
63
54
|
return nil unless node.is_a?(Prism::SymbolNode)
|
|
64
55
|
|
|
@@ -68,9 +59,6 @@ module Rigor
|
|
|
68
59
|
# The String a literal `Prism::SymbolNode` names, or `nil` for any other node (including a
|
|
69
60
|
# `Prism::StringNode` and `nil`). The String-returning sibling of {.symbol} — SymbolNode-only, but the
|
|
70
61
|
# caller wants the raw name rather than the interned Symbol.
|
|
71
|
-
#
|
|
72
|
-
# @param node [Prism::Node, nil]
|
|
73
|
-
# @return [String, nil]
|
|
74
62
|
def symbol_name(node)
|
|
75
63
|
return nil unless node.is_a?(Prism::SymbolNode)
|
|
76
64
|
|
|
@@ -79,9 +67,6 @@ module Rigor
|
|
|
79
67
|
|
|
80
68
|
# Every literal Symbol/String positional argument of a call, in source order. Non-literal arguments
|
|
81
69
|
# are dropped. Returns `[]` when the call has no argument list.
|
|
82
|
-
#
|
|
83
|
-
# @param call_node [Prism::CallNode, nil]
|
|
84
|
-
# @return [Array<Symbol>]
|
|
85
70
|
def symbol_arguments(call_node)
|
|
86
71
|
args = call_node&.arguments&.arguments
|
|
87
72
|
return [] if args.nil?
|
|
@@ -93,20 +78,12 @@ module Rigor
|
|
|
93
78
|
# {.symbol_name} — for callers that need a predicate rather than an extraction (hash-key matching in
|
|
94
79
|
# keyword or assoc argument positions, e.g. `el.is_a?(AssocNode) && symbol_named?(el.key, "required")`).
|
|
95
80
|
# Uses `#unescaped` (not `#value`) for round-trip consistency.
|
|
96
|
-
#
|
|
97
|
-
# @param node [Prism::Node, nil]
|
|
98
|
-
# @param name [String]
|
|
99
|
-
# @return [Boolean]
|
|
100
81
|
def symbol_named?(node, name)
|
|
101
82
|
node.is_a?(Prism::SymbolNode) && node.unescaped == name
|
|
102
83
|
end
|
|
103
84
|
|
|
104
85
|
# The literal Symbol/String at positional `index`, or `nil` when the call has no argument list, the
|
|
105
86
|
# index is out of range, or the argument there is not a literal Symbol/String.
|
|
106
|
-
#
|
|
107
|
-
# @param call_node [Prism::CallNode, nil]
|
|
108
|
-
# @param index [Integer]
|
|
109
|
-
# @return [Symbol, nil]
|
|
110
87
|
def symbol_arg(call_node, index)
|
|
111
88
|
args = call_node&.arguments&.arguments
|
|
112
89
|
return nil if args.nil?
|
|
@@ -106,8 +106,6 @@ module Rigor
|
|
|
106
106
|
# e.g. `node.body`). Pure and re-entrant; `break` / `next` / `return` in the block behave exactly as they
|
|
107
107
|
# would with `compact_child_nodes.each`. Walkers holding a known `Prism::Node` call `#rigor_each_child`
|
|
108
108
|
# directly; this wrapper is the nil-tolerant entry.
|
|
109
|
-
#
|
|
110
|
-
# @yieldparam child [Prism::Node]
|
|
111
109
|
def each_child(node, &)
|
|
112
110
|
node.rigor_each_child(&) if node.is_a?(Prism::Node)
|
|
113
111
|
end
|
|
@@ -22,25 +22,19 @@ module Rigor
|
|
|
22
22
|
class OutOfRangeError < StandardError; end
|
|
23
23
|
|
|
24
24
|
class << self
|
|
25
|
-
# @param
|
|
26
|
-
# @param
|
|
27
|
-
# @param line [Integer] 1-indexed line number
|
|
28
|
-
# @param column [Integer] 1-indexed column number (byte index within the line)
|
|
29
|
-
# @return [Prism::Node, nil]
|
|
25
|
+
# @param line — 1-indexed line number
|
|
26
|
+
# @param column — 1-indexed column number (byte index within the line)
|
|
30
27
|
def at_position(source:, root:, line:, column:)
|
|
31
28
|
new(source: source, root: root).at_position(line: line, column: column)
|
|
32
29
|
end
|
|
33
30
|
|
|
34
|
-
# @param
|
|
35
|
-
# @param offset [Integer] 0-indexed byte offset
|
|
36
|
-
# @return [Prism::Node, nil]
|
|
31
|
+
# @param offset — 0-indexed byte offset
|
|
37
32
|
def at_offset(root:, offset:)
|
|
38
33
|
new(source: nil, root: root).at_offset(offset)
|
|
39
34
|
end
|
|
40
35
|
end
|
|
41
36
|
|
|
42
|
-
# @param source
|
|
43
|
-
# @param root [Prism::Node]
|
|
37
|
+
# @param source — used by `#at_position`; may be omitted when only `#at_offset` is needed.
|
|
44
38
|
def initialize(source:, root:)
|
|
45
39
|
@source = source
|
|
46
40
|
@root = root
|
|
@@ -48,7 +42,7 @@ module Rigor
|
|
|
48
42
|
|
|
49
43
|
# Resolve a `(line, column)` pair (1-indexed) to the deepest enclosing node.
|
|
50
44
|
#
|
|
51
|
-
# @raise
|
|
45
|
+
# @raise OutOfRangeError — if the line or column falls outside the source buffer.
|
|
52
46
|
def at_position(line:, column:)
|
|
53
47
|
offset = position_to_offset(line, column)
|
|
54
48
|
at_offset(offset)
|
|
@@ -25,8 +25,6 @@ module Rigor
|
|
|
25
25
|
module NodeWalker
|
|
26
26
|
module_function
|
|
27
27
|
|
|
28
|
-
# @yieldparam node [Prism::Node]
|
|
29
|
-
# @return [Enumerator] when no block is given.
|
|
30
28
|
def each(root, &)
|
|
31
29
|
return to_enum(__method__, root) unless block_given?
|
|
32
30
|
|
|
@@ -47,10 +45,6 @@ module Rigor
|
|
|
47
45
|
# itself). The yielded `ancestors` array is the live descent stack — callers that retain it past the
|
|
48
46
|
# block invocation MUST copy it (`Plugin::NodeContext` does). Used by the plugin engine to give
|
|
49
47
|
# `node_rule` blocks their enclosing class / method / block context (ADR-37 slice 1d).
|
|
50
|
-
#
|
|
51
|
-
# @yieldparam node [Prism::Node]
|
|
52
|
-
# @yieldparam ancestors [Array<Prism::Node>]
|
|
53
|
-
# @return [Enumerator] when no block is given.
|
|
54
48
|
def each_with_ancestors(root, &)
|
|
55
49
|
return to_enum(__method__, root) unless block_given?
|
|
56
50
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "prism"
|
|
4
|
+
|
|
5
|
+
module Rigor
|
|
6
|
+
module Source
|
|
7
|
+
# Issue #992 — the positional-argument envelope of a `Prism::DefNode`, and the ONE place a `def` nobody
|
|
8
|
+
# declared is turned into something `call.wrong-arity` can check a call against.
|
|
9
|
+
#
|
|
10
|
+
# Both undeclared lanes read it. A method known only to the discovery walk has no other shape, and a
|
|
11
|
+
# method `rigor-rbs-inline` synthesized a fully defaulted skeleton for (`%a{rigor:v1:inferred-signature}`)
|
|
12
|
+
# is sent here too rather than having its synthesized member's arity read, so a `def` can never be
|
|
13
|
+
# judged by two parsers of its parameter list that disagree.
|
|
14
|
+
#
|
|
15
|
+
# An envelope is plain frozen data, `[min, max, required_keywords]`, because it rides the ADR-85 seed
|
|
16
|
+
# bundle through `Marshal`: `max` is nil when a rest or `...` parameter leaves it unbounded, and
|
|
17
|
+
# `required_keywords` is true when the def takes a required keyword — a call that passes positionals
|
|
18
|
+
# only then fails on the missing keyword whatever its count, which is a different diagnostic than the
|
|
19
|
+
# one this envelope backs, so the rule declines on it the way `compute_arity_envelope` declines an RBS
|
|
20
|
+
# function with required keywords.
|
|
21
|
+
#
|
|
22
|
+
# {OPAQUE} is the value every other contribution to a name records — `define_method`, `attr_*`, an alias,
|
|
23
|
+
# a macro that names the method, a second `def` whose envelope differs — and it absorbs under {.merge}.
|
|
24
|
+
# That makes the per-name fold a join: order-independent, idempotent, and unable to keep one of several
|
|
25
|
+
# shapes silently.
|
|
26
|
+
module ParameterEnvelope
|
|
27
|
+
module_function
|
|
28
|
+
|
|
29
|
+
OPAQUE = :opaque
|
|
30
|
+
|
|
31
|
+
# The envelope of `def_node`'s own parameter list. Block, keyword-optional and keyword-rest parameters
|
|
32
|
+
# never change how many positionals the method accepts; `super`, `yield` and `&block` in the body do
|
|
33
|
+
# not either, so the body is not read at all.
|
|
34
|
+
def of(def_node)
|
|
35
|
+
params = def_node.parameters
|
|
36
|
+
return [0, 0, false].freeze if params.nil?
|
|
37
|
+
|
|
38
|
+
required = params.requireds.size + params.posts.size
|
|
39
|
+
[required, maximum(params, required), required_keywords?(params)].freeze
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def maximum(params, required)
|
|
43
|
+
return nil if params.rest || params.keyword_rest.is_a?(Prism::ForwardingParameterNode)
|
|
44
|
+
|
|
45
|
+
required + params.optionals.size
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def required_keywords?(params)
|
|
49
|
+
params.keywords.any?(Prism::RequiredKeywordParameterNode)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# The join of two contributions to one name: equal envelopes stay, anything else is {OPAQUE}.
|
|
53
|
+
def merge(left, right)
|
|
54
|
+
return right if left.nil?
|
|
55
|
+
return left if right.nil?
|
|
56
|
+
|
|
57
|
+
left == right ? left : OPAQUE
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def opaque?(envelope) = envelope == OPAQUE
|
|
61
|
+
|
|
62
|
+
# Folds `overlay`'s per-class entries into `base` with {.merge}, returning a new table. Both are
|
|
63
|
+
# `{class name => {key => envelope}}`.
|
|
64
|
+
def merge_tables(base, overlay)
|
|
65
|
+
return overlay if base.nil? || base.empty?
|
|
66
|
+
return base if overlay.nil? || overlay.empty?
|
|
67
|
+
|
|
68
|
+
base.merge(overlay) { |_class, left, right| left.merge(right) { |_key, a, b| merge(a, b) } }
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
data/lib/rigor/source.rb
CHANGED
|
@@ -91,9 +91,7 @@ module Rigor
|
|
|
91
91
|
INFO_GUARDED = %i[h5_systemic_cluster h6_genuine_bugs].freeze
|
|
92
92
|
private_constant :INFO_GUARDED
|
|
93
93
|
|
|
94
|
-
# @param diagnostics
|
|
95
|
-
# @param include_info [Boolean] let H5/H6 see `:info` diagnostics
|
|
96
|
-
# @return [Array<Hint>]
|
|
94
|
+
# @param include_info — let H5/H6 see `:info` diagnostics
|
|
97
95
|
def recognise(diagnostics, include_info: false)
|
|
98
96
|
claimed = {}.compare_by_identity
|
|
99
97
|
recognisers.filter_map do |recogniser|
|
data/lib/rigor/triage.rb
CHANGED
|
@@ -34,11 +34,9 @@ module Rigor
|
|
|
34
34
|
# `rbs.coverage.missing-gem`) survives; the count-based H5/H6 recognisers guard against info themselves so
|
|
35
35
|
# recognition trace never reads as a bug.
|
|
36
36
|
#
|
|
37
|
-
# @param
|
|
38
|
-
# @param
|
|
39
|
-
# @param
|
|
40
|
-
# @param include_info [Boolean] route info into the volume views
|
|
41
|
-
# @return [Report]
|
|
37
|
+
# @param top — hotspot-file cap
|
|
38
|
+
# @param hints — run the heuristic catalogue
|
|
39
|
+
# @param include_info — route info into the volume views
|
|
42
40
|
def analyze(diagnostics, top: 10, hints: true, include_info: false)
|
|
43
41
|
routed = include_info ? diagnostics : diagnostics.reject { |d| d.severity == :info }
|
|
44
42
|
Report.new(
|
|
@@ -26,9 +26,8 @@ module Rigor
|
|
|
26
26
|
|
|
27
27
|
attr_reader :trinary, :mode, :reasons
|
|
28
28
|
|
|
29
|
-
# @param
|
|
30
|
-
# @param
|
|
31
|
-
# @param reasons [Array<String>, String, nil] textual reasons; a
|
|
29
|
+
# @param mode — currently `:gradual` (default) or `:strict`.
|
|
30
|
+
# @param reasons — textual reasons; a
|
|
32
31
|
# single string is wrapped, `nil` becomes an empty array.
|
|
33
32
|
def initialize(trinary, mode: :gradual, reasons: nil)
|
|
34
33
|
raise ArgumentError, "trinary must be Rigor::Trinary, got #{trinary.class}" unless trinary.is_a?(Trinary)
|
|
@@ -42,18 +41,37 @@ module Rigor
|
|
|
42
41
|
|
|
43
42
|
class << self
|
|
44
43
|
def yes(mode: :gradual, reasons: nil)
|
|
45
|
-
|
|
44
|
+
literal_result(Trinary.yes, mode, reasons)
|
|
46
45
|
end
|
|
47
46
|
|
|
48
47
|
def no(mode: :gradual, reasons: nil)
|
|
49
|
-
|
|
48
|
+
literal_result(Trinary.no, mode, reasons)
|
|
50
49
|
end
|
|
51
50
|
|
|
52
51
|
def maybe(mode: :gradual, reasons: nil)
|
|
53
|
-
|
|
52
|
+
literal_result(Trinary.maybe, mode, reasons)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
# #775 — a result is an immutable value, so one instance serves every site that asks for the same
|
|
58
|
+
# verdict with the same literal reason (`"structural equality"`, `"exact name match"`, ...): the
|
|
59
|
+
# acceptance rules answer ~360k times on the lib self-check, most of them through a handful of
|
|
60
|
+
# such literals, and each answer cost the result plus its reasons array. A reason built at the
|
|
61
|
+
# site (an unfrozen interpolated String) or a reason list still builds a fresh result.
|
|
62
|
+
def literal_result(trinary, mode, reasons)
|
|
63
|
+
literal = reasons.nil? || (reasons.is_a?(String) && reasons.frozen?)
|
|
64
|
+
return new(trinary, mode: mode, reasons: reasons) unless literal
|
|
65
|
+
|
|
66
|
+
by_mode = (@literal_results[trinary] ||= {})
|
|
67
|
+
by_reason = (by_mode[mode] ||= {})
|
|
68
|
+
by_reason[reasons] ||= new(trinary, mode: mode, reasons: reasons)
|
|
54
69
|
end
|
|
55
70
|
end
|
|
56
71
|
|
|
72
|
+
# `Trinary` verdict => mode => literal reason (or nil) => the shared result.
|
|
73
|
+
@literal_results = {}
|
|
74
|
+
|
|
57
75
|
def yes?
|
|
58
76
|
trinary.yes?
|
|
59
77
|
end
|