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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../check_rules/rule_ids"
|
|
3
4
|
require_relative "../crash_signature"
|
|
4
5
|
require_relative "../diagnostic"
|
|
5
6
|
require_relative "../severity_stamp"
|
|
@@ -22,36 +23,39 @@ module Rigor
|
|
|
22
23
|
# end-of-pass snapshots) is read through injected reader procs so this collaborator never calls back
|
|
23
24
|
# into the {Runner} and the read happens at the exact point in the run the original inline read did.
|
|
24
25
|
class DiagnosticAggregator # rubocop:disable Metrics/ClassLength
|
|
25
|
-
# @param
|
|
26
|
-
# @param
|
|
27
|
-
# @param boundary_cross_reporter [DependencySourceInference::BoundaryCrossReporter]
|
|
28
|
-
# @param source_rbs_synthesis_reporter [Plugin::SourceRbsSynthesisReporter]
|
|
29
|
-
# @param plugin_registry [#call] reader returning the current {Plugin::Registry} (varies per run).
|
|
30
|
-
# @param dependency_source_index [#call] reader returning the current
|
|
26
|
+
# @param plugin_registry — reader returning the current {Plugin::Registry} (varies per run).
|
|
27
|
+
# @param dependency_source_index — reader returning the current
|
|
31
28
|
# {DependencySourceInference::Index}.
|
|
32
|
-
# @param pool_mode
|
|
33
|
-
# @param cached_plugin_prepare_diagnostics
|
|
34
|
-
# @param pre_eval_diagnostics_from_scanner
|
|
35
|
-
# @param synthesized_namespaces_snapshot
|
|
36
|
-
# @param quarantined_signatures_snapshot
|
|
29
|
+
# @param pool_mode — reader returning the pool-mode flag.
|
|
30
|
+
# @param cached_plugin_prepare_diagnostics — reader returning the prepare-diagnostic snapshot.
|
|
31
|
+
# @param pre_eval_diagnostics_from_scanner — reader returning the pre-eval scanner diagnostics.
|
|
32
|
+
# @param synthesized_namespaces_snapshot — reader.
|
|
33
|
+
# @param quarantined_signatures_snapshot — reader returning the `signature_paths:` files skipped
|
|
37
34
|
# because they do not parse (`[path, first_error_line]` pairs).
|
|
38
|
-
# @param
|
|
35
|
+
# @param signature_standdowns_snapshot — reader returning the plugin-contributed signature files
|
|
36
|
+
# that stood down against a colliding generic arity (#610), as
|
|
37
|
+
# `[path, class_name, existing_arity, incoming_arity, existing_file]` tuples. Defaults to none so
|
|
38
|
+
# a caller that snapshots nothing of the kind need not say so.
|
|
39
|
+
# @param env_build_failure_snapshot — reader returning the total RBS env-build failure tuple
|
|
39
40
|
# (`[error_class, first_error_line, conflicting_buffer_names]`) or nil when the env built.
|
|
40
|
-
# @param definition_build_failures_snapshot
|
|
41
|
+
# @param definition_build_failures_snapshot — issue #696 — reader returning the per-class
|
|
41
42
|
# `RBS::DefinitionBuilder` failures the run observed, as `[class_name, error_class, member,
|
|
42
|
-
# conflicting_buffer_names]` tuples
|
|
43
|
-
#
|
|
43
|
+
# conflicting_buffer_names, unresolved_type_name_detail]` tuples (issue #997 added the fifth
|
|
44
|
+
# element — `[token, location, refinement_hint]`, `nil` unless `error_class` is
|
|
45
|
+
# `RBS::NoTypeFoundError`). Empty for a healthy sig set.
|
|
46
|
+
# @param hkt_scan_failure_snapshot — issue #784 — reader returning the `[error_class_name,
|
|
44
47
|
# first_message_line, raw_frame_or_nil, stage]` tuple whichever stage of the HKT-registry build
|
|
45
48
|
# raised, or nil when both built (or were never demanded). `stage` is `:scan` (the RBS `type`-alias
|
|
46
49
|
# scan) or `:overlay` (the plugin-manifest aggregation, #791), and picks the row's wording.
|
|
47
|
-
# @param conformance_results_snapshot
|
|
50
|
+
# @param conformance_results_snapshot — reader.
|
|
48
51
|
def initialize(configuration:, rbs_extended_reporter:, boundary_cross_reporter:, # rubocop:disable Metrics/ParameterLists
|
|
49
52
|
source_rbs_synthesis_reporter:, plugin_registry:, dependency_source_index:,
|
|
50
53
|
pool_mode:, cached_plugin_prepare_diagnostics:,
|
|
51
54
|
pre_eval_diagnostics_from_scanner:, synthesized_namespaces_snapshot:,
|
|
52
55
|
quarantined_signatures_snapshot:, env_build_failure_snapshot:,
|
|
53
56
|
definition_build_failures_snapshot:, hkt_scan_failure_snapshot:,
|
|
54
|
-
conformance_results_snapshot:
|
|
57
|
+
conformance_results_snapshot:, signature_standdowns_snapshot: -> { [] },
|
|
58
|
+
pooled_run_disclosures: -> { [] })
|
|
55
59
|
@configuration = configuration
|
|
56
60
|
@rbs_extended_reporter = rbs_extended_reporter
|
|
57
61
|
@boundary_cross_reporter = boundary_cross_reporter
|
|
@@ -63,10 +67,14 @@ module Rigor
|
|
|
63
67
|
@pre_eval_diagnostics_from_scanner_reader = pre_eval_diagnostics_from_scanner
|
|
64
68
|
@synthesized_namespaces_snapshot_reader = synthesized_namespaces_snapshot
|
|
65
69
|
@quarantined_signatures_snapshot_reader = quarantined_signatures_snapshot
|
|
70
|
+
@signature_standdowns_snapshot_reader = signature_standdowns_snapshot
|
|
66
71
|
@env_build_failure_snapshot_reader = env_build_failure_snapshot
|
|
67
72
|
@definition_build_failures_snapshot_reader = definition_build_failures_snapshot
|
|
68
73
|
@hkt_scan_failure_snapshot_reader = hkt_scan_failure_snapshot
|
|
69
74
|
@conformance_results_snapshot_reader = conformance_results_snapshot
|
|
75
|
+
# Issue #1051 — reader for the pool coordinator's de-duplicated run-scoped disclosure table.
|
|
76
|
+
# Empty on a sequential run, where `plugin_registry`'s own instances are the ones that registered.
|
|
77
|
+
@pooled_run_disclosures_reader = pooled_run_disclosures
|
|
70
78
|
end
|
|
71
79
|
|
|
72
80
|
# Pre-file diagnostic streams that fire once per run rather than per analyzed file: plugin load /
|
|
@@ -416,12 +424,33 @@ module Rigor
|
|
|
416
424
|
[build_rbs_synthesized_namespace_diagnostic(synthesized)]
|
|
417
425
|
end
|
|
418
426
|
|
|
427
|
+
# Issue #610 — the outcome that AVOIDED `rbs.coverage.definition-build-failed`'s rung: a signature
|
|
428
|
+
# file a loaded plugin contributes re-declared a class another loaded source (typically an `rbs
|
|
429
|
+
# collection install`) already declares at a DIFFERENT generic arity, so the plugin's file stood
|
|
430
|
+
# down rather than fail the class's definition build. One `:info` per file: the user is told what
|
|
431
|
+
# typing they are not getting and why, and — unlike the quarantine row this file used to be
|
|
432
|
+
# misreported as — is not sent to remove a declaration the plugin owns.
|
|
433
|
+
def rbs_plugin_signature_stood_down_diagnostics
|
|
434
|
+
standdowns = signature_standdowns_snapshot
|
|
435
|
+
return [] if standdowns.nil? || standdowns.empty?
|
|
436
|
+
|
|
437
|
+
standdowns.map { |entry| build_rbs_plugin_signature_stood_down_diagnostic(entry) }
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
# The two `:info` notices that close the `rbs.coverage.*` ladder, in this order: the namespace
|
|
441
|
+
# synthesis first, then the stand-down (#610) — the outcome that AVOIDED a definition-build failure
|
|
442
|
+
# and so the quietest row on it. One method so the runner's assembly reads them as one slot.
|
|
443
|
+
def rbs_coverage_notice_diagnostics
|
|
444
|
+
rbs_synthesized_namespace_diagnostics + rbs_plugin_signature_stood_down_diagnostics
|
|
445
|
+
end
|
|
446
|
+
|
|
419
447
|
# Maps the per-run `rigor:v1:conforms-to` scan results into diagnostics (spec: `rbs-extended.md` §
|
|
420
448
|
# "Explicit conformance directive"). A class that declares `conforms-to _Interface` but is missing
|
|
421
449
|
# a required interface method surfaces as `rbs_extended.unsatisfied-conformance`; an unresolvable
|
|
422
450
|
# interface name surfaces as `dynamic.rbs-extended.unresolved` `:info` (the same fail-soft channel
|
|
423
|
-
# the other directive parsers use). Empty for a project with no directive
|
|
424
|
-
# conformance, or
|
|
451
|
+
# the other directive parsers use). Empty for a project with no directive or a well-formed
|
|
452
|
+
# conformance; every analysis path, pooled or degraded, takes the snapshot `synthesized_namespaces`
|
|
453
|
+
# comes from.
|
|
425
454
|
def conforms_to_diagnostics
|
|
426
455
|
results = conformance_results_snapshot
|
|
427
456
|
return [] if results.nil? || results.empty?
|
|
@@ -436,16 +465,28 @@ module Rigor
|
|
|
436
465
|
when RbsExtended::ConformanceChecker::IncompatibleSignature
|
|
437
466
|
build_incompatible_signature_diagnostic(record)
|
|
438
467
|
else # UnresolvedInterface
|
|
439
|
-
|
|
440
|
-
record.location,
|
|
441
|
-
rule: "dynamic.rbs-extended.unresolved",
|
|
442
|
-
message: "`#{record.class_name}` declares `conforms-to #{record.interface_name}` but " \
|
|
443
|
-
"interface `#{record.interface_name}` is not loaded. Check for a typo or add " \
|
|
444
|
-
"the `sig`/library that declares it to the RBS load path."
|
|
445
|
-
)
|
|
468
|
+
build_unresolved_conformance_diagnostic(record)
|
|
446
469
|
end
|
|
447
470
|
end
|
|
448
471
|
|
|
472
|
+
# Issue #928 — `:warning`, not the `:info` the other `dynamic.rbs-extended.unresolved` producers
|
|
473
|
+
# stamp. Those report that an inference fell back; this one reports that an assertion the author
|
|
474
|
+
# deliberately wrote is checking NOTHING, and the whole point of `conforms-to` is to be checked. It
|
|
475
|
+
# is not unsolicited either: only a project that wrote the directive can see it. Now that the
|
|
476
|
+
# capability-role catalog ships, the remaining way to reach this row is a name that does not exist.
|
|
477
|
+
def build_unresolved_conformance_diagnostic(record)
|
|
478
|
+
path, line, column = location_fields(record.location)
|
|
479
|
+
Diagnostic.new(
|
|
480
|
+
path: path, line: line, column: column,
|
|
481
|
+
message: "`#{record.class_name}` declares `conforms-to #{record.interface_name}` but " \
|
|
482
|
+
"interface `#{record.interface_name}` is not loaded. Check for a typo or add " \
|
|
483
|
+
"the `sig`/library that declares it to the RBS load path.",
|
|
484
|
+
severity: :warning,
|
|
485
|
+
rule: "dynamic.rbs-extended.unresolved",
|
|
486
|
+
source_family: :builtin
|
|
487
|
+
)
|
|
488
|
+
end
|
|
489
|
+
|
|
449
490
|
def build_unsatisfied_conformance_diagnostic(record)
|
|
450
491
|
path, line, column = location_fields(record.location)
|
|
451
492
|
Diagnostic.new(
|
|
@@ -544,17 +585,58 @@ module Rigor
|
|
|
544
585
|
"#{first_failure_clause(failures.first)}#{conflicting_files_clause(files, sample_size)} " \
|
|
545
586
|
"Rigor still treats each class as KNOWN, so calls into it — real methods and typos " \
|
|
546
587
|
"alike — silently read `Dynamic[top]` instead of resolving, and this run is quieter " \
|
|
547
|
-
"than it should be rather than cleaner.
|
|
548
|
-
"member; remove the duplicate declaration (`rbs validate`) to restore type coverage.",
|
|
588
|
+
"than it should be rather than cleaner. #{definition_build_advice(failures.first)}",
|
|
549
589
|
severity: :warning,
|
|
550
590
|
rule: "rbs.coverage.definition-build-failed",
|
|
551
591
|
source_family: :builtin
|
|
552
592
|
)
|
|
553
593
|
end
|
|
554
594
|
|
|
555
|
-
#
|
|
556
|
-
#
|
|
557
|
-
#
|
|
595
|
+
# The closing advice follows the FIRST failure's error class: `GenericParameterMismatchError` is two
|
|
596
|
+
# declarations of one CLASS at different generic arity (#610); `NoTypeFoundError` (issue #997) is
|
|
597
|
+
# ONE declaration naming a type that does not exist, which "remove the duplicate declaration" sends
|
|
598
|
+
# its reader after a duplicate that is not there — the fifth tuple element
|
|
599
|
+
# ({RbsLoader#unresolved_type_name_detail}) is non-nil for exactly that case. Every other error class
|
|
600
|
+
# (the two duplicated-definition errors, `RecursiveAncestorError`, …) keeps the duplicate-declaration
|
|
601
|
+
# wording, which is accurate for them.
|
|
602
|
+
def definition_build_advice(failure)
|
|
603
|
+
_, error_class, _member, _buffers, unresolved = failure
|
|
604
|
+
if error_class.to_s.end_with?("GenericParameterMismatchError")
|
|
605
|
+
"Two signature sources declare the class with a different number of type parameters; make " \
|
|
606
|
+
"the declarations agree (`rbs validate`) to restore type coverage."
|
|
607
|
+
elsif unresolved
|
|
608
|
+
unresolved_type_name_advice(unresolved)
|
|
609
|
+
else
|
|
610
|
+
"Two signature sources declare the same member; remove the duplicate declaration " \
|
|
611
|
+
"(`rbs validate`) to restore type coverage."
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
# Issue #997 — `unresolved` is {RbsLoader#unresolved_type_name_detail}'s `[token, location,
|
|
616
|
+
# refinement_hint]`. `refinement_hint` turns the message into a fix: the token is not a typo to
|
|
617
|
+
# chase down but the start of a Rigor refinement name that is not valid in an RBS type position, and
|
|
618
|
+
# the reader is told the spelling that IS valid today. Without a hint, the token is named with its
|
|
619
|
+
# position and the reader is left with the same "not a duplicate" correction plus a typo/missing-load
|
|
620
|
+
# check — still narrower than the duplicate-declaration wording it replaces.
|
|
621
|
+
def unresolved_type_name_advice(unresolved)
|
|
622
|
+
token, location, refinement_hint = unresolved
|
|
623
|
+
position = location ? " at `#{location}`" : ""
|
|
624
|
+
if refinement_hint
|
|
625
|
+
"`#{token}`#{position} does not name a type RBS can resolve; it is the start of the Rigor " \
|
|
626
|
+
"refinement `#{refinement_hint}`, which is not valid in an RBS type position. Write it as " \
|
|
627
|
+
"an `%a{rigor:v1:param: name is #{refinement_hint}}` (or `return:` / `assert`) annotation " \
|
|
628
|
+
"alongside the plain RBS type instead — see docs/manual/16-rbs-extended-annotations.md — " \
|
|
629
|
+
"to restore type coverage."
|
|
630
|
+
else
|
|
631
|
+
"One signature source names `#{token}`#{position}, which is not a type RBS can resolve; fix " \
|
|
632
|
+
"the typo, or if it names a class, confirm it is loaded (`rbs validate`) to restore type " \
|
|
633
|
+
"coverage."
|
|
634
|
+
end
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
# `[class_name, error_class, member, buffers, unresolved_type_name_detail]`. The member is nil for
|
|
638
|
+
# the error classes that carry no name at all (`RecursiveAncestorError`), and the clause then names
|
|
639
|
+
# the error class alone rather than inventing a member.
|
|
558
640
|
def first_failure_clause(failure)
|
|
559
641
|
_, error_class, member, = failure
|
|
560
642
|
return " First failure: #{error_class}." if member.nil? || member.empty?
|
|
@@ -665,6 +747,42 @@ module Rigor
|
|
|
665
747
|
)
|
|
666
748
|
end
|
|
667
749
|
|
|
750
|
+
def build_rbs_plugin_signature_stood_down_diagnostic(entry)
|
|
751
|
+
path, class_name, existing_arity, incoming_arity, existing_file = entry
|
|
752
|
+
displaced_by = displacing_source_phrase(existing_file)
|
|
753
|
+
Diagnostic.new(
|
|
754
|
+
path: ".rigor.yml",
|
|
755
|
+
line: 1,
|
|
756
|
+
column: 1,
|
|
757
|
+
message: "`#{relative_signature_path(path.to_s)}` (a signature file a plugin contributes) declares " \
|
|
758
|
+
"`#{class_name.to_s.delete_prefix('::')}` with #{type_parameter_phrase(incoming_arity)}, " \
|
|
759
|
+
"but #{displaced_by} already declares it with #{type_parameter_phrase(existing_arity)}. " \
|
|
760
|
+
"Two declarations of one class at different generic arity fail its definition build, so " \
|
|
761
|
+
"the plugin's file stood down: calls into the class resolve against the other " \
|
|
762
|
+
"declaration, and the plugin's element typing for it is unavailable while both are " \
|
|
763
|
+
"loaded. Expected when a bundled plugin and an `rbs collection install` both declare " \
|
|
764
|
+
"the class; nothing to fix unless you want the plugin's typing back, which needs the " \
|
|
765
|
+
"other source to stop declaring the class.",
|
|
766
|
+
severity: :info,
|
|
767
|
+
rule: "rbs.coverage.plugin-signature-stood-down",
|
|
768
|
+
source_family: :builtin
|
|
769
|
+
)
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
def displacing_source_phrase(existing_file)
|
|
773
|
+
return "another loaded signature source" if existing_file.nil?
|
|
774
|
+
|
|
775
|
+
"`#{relative_signature_path(existing_file.to_s)}`"
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
def type_parameter_phrase(arity)
|
|
779
|
+
case arity
|
|
780
|
+
when nil, 0 then "no type parameters"
|
|
781
|
+
when 1 then "1 type parameter"
|
|
782
|
+
else "#{arity} type parameters"
|
|
783
|
+
end
|
|
784
|
+
end
|
|
785
|
+
|
|
668
786
|
def build_rbs_coverage_missing_diagnostic(missing)
|
|
669
787
|
sample_size = 5
|
|
670
788
|
sample = missing.first(sample_size).map(&:gem_name)
|
|
@@ -722,7 +840,22 @@ module Rigor
|
|
|
722
840
|
)
|
|
723
841
|
end
|
|
724
842
|
|
|
725
|
-
unresolved + lossy + hkt_directive_diagnostics
|
|
843
|
+
unresolved + lossy + hkt_directive_diagnostics + deprecated_form_diagnostics
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
# ADR-109 WD3 — one row per annotation still written in a spelling the grammar accepts but no
|
|
847
|
+
# longer displays. The row names the replacement because the deprecation window exists for exactly
|
|
848
|
+
# this edit, and it stays `:info`: the annotation resolved, the run is as green as it was.
|
|
849
|
+
def deprecated_form_diagnostics
|
|
850
|
+
@rbs_extended_reporter.deprecated_forms.map do |entry|
|
|
851
|
+
build_positioned_reporter_diagnostic(
|
|
852
|
+
entry,
|
|
853
|
+
rule: "dynamic.rbs-extended.deprecated-form",
|
|
854
|
+
message: "`#{entry.payload}` is a deprecated spelling; write `#{entry.replacement}`. The " \
|
|
855
|
+
"angle-bracket integer range is accepted for one deprecation window and removed " \
|
|
856
|
+
"at the next compatibility break (ADR-109)."
|
|
857
|
+
)
|
|
858
|
+
end
|
|
726
859
|
end
|
|
727
860
|
|
|
728
861
|
# Issue #785 — one row per declined HKT directive. The consequence sentence is the point: the parser
|
|
@@ -752,10 +885,29 @@ module Rigor
|
|
|
752
885
|
return [] if @source_rbs_synthesis_reporter.empty?
|
|
753
886
|
|
|
754
887
|
@source_rbs_synthesis_reporter.entries.map do |entry|
|
|
755
|
-
entry.kind
|
|
888
|
+
case entry.kind
|
|
889
|
+
when :not_honoured then not_honoured_diagnostic(entry)
|
|
890
|
+
when :contradiction then contradicting_signature_diagnostic(entry)
|
|
891
|
+
else synthesis_failed_diagnostic(entry)
|
|
892
|
+
end
|
|
756
893
|
end
|
|
757
894
|
end
|
|
758
895
|
|
|
896
|
+
# ADR-112 WD5 / issue #1075 — a member whose two declarations contradict, or whose refinement is
|
|
897
|
+
# outside its own declared type. An error in every profile: the false-positive discipline is carried
|
|
898
|
+
# by the rule's narrow definition of a contradiction, never by the severity (ADR-112 WD5). The message
|
|
899
|
+
# is composed where the record is read ({Environment.record_member_consistency}), since only there
|
|
900
|
+
# are both sources' paths at hand.
|
|
901
|
+
def contradicting_signature_diagnostic(entry)
|
|
902
|
+
Diagnostic.new(
|
|
903
|
+
path: entry.path, line: entry.line || 1, column: 1,
|
|
904
|
+
message: entry.message,
|
|
905
|
+
severity: :error,
|
|
906
|
+
rule: CheckRules::RULE_CONTRADICTING_SIGNATURE,
|
|
907
|
+
source_family: :builtin
|
|
908
|
+
)
|
|
909
|
+
end
|
|
910
|
+
|
|
759
911
|
def synthesis_failed_diagnostic(entry)
|
|
760
912
|
Diagnostic.new(
|
|
761
913
|
path: entry.path, line: 1, column: 1,
|
|
@@ -811,6 +963,153 @@ module Rigor
|
|
|
811
963
|
end
|
|
812
964
|
end
|
|
813
965
|
|
|
966
|
+
# Issue #959 — surfaces the {Plugin::IoBoundary} refusal history each loaded plugin accumulated over
|
|
967
|
+
# the whole run (prepare AND every per-file call: `#io_boundary` is memoised per plugin instance, so
|
|
968
|
+
# one boundary sees both). `TrustPolicy#allow_read?` stays `File.expand_path`-only per ADR-2 — a
|
|
969
|
+
# project rooted under a symlink (macOS' `/tmp` → `/private/tmp` is the common case) can have every
|
|
970
|
+
# plugin read fall outside its own read roots with nothing said about it. One `:info` row per plugin
|
|
971
|
+
# that hit this, never one per path, naming the count and the first path so the row stays legible on
|
|
972
|
+
# a plugin that walked a whole out-of-scope subtree.
|
|
973
|
+
#
|
|
974
|
+
# Positioned here, in `#pre_file_diagnostics`'s post-analysis sibling list (called from
|
|
975
|
+
# `Runner#assemble_run_diagnostics`, which only runs on an ADR-45 cache MISS): the refusal history is
|
|
976
|
+
# a function of the plugin code and the resolved paths for THIS configuration, so it is deterministic
|
|
977
|
+
# across runs of the same inputs and the row that lands in a miss's cached diagnostics blob is the
|
|
978
|
+
# row a later warm HIT correctly re-serves — the same regeneration contract every other stream
|
|
979
|
+
# aggregated in `#pre_file_diagnostics` / `#assemble_run_diagnostics` already relies on (see
|
|
980
|
+
# `docs/type-specification/diagnostic-policy.md` § "Run-level rows and the record-and-validate
|
|
981
|
+
# cache"). It is also never routed through `IncrementalSession`'s per-file cache (`#788`): that cache
|
|
982
|
+
# holds only `Runner#per_file_diagnostics`, and this row is not part of that stream.
|
|
983
|
+
#
|
|
984
|
+
# Scope: `plugin_registry` here is the coordinator-side registry, which only actually RUNS `#prepare`
|
|
985
|
+
# / per-file analysis in sequential mode (`--workers` unset, the default) — a pooled run (`--workers
|
|
986
|
+
# N`) prepares and analyses on per-worker `WorkerSession` registries this reader never sees, so a
|
|
987
|
+
# refusal confined to a pooled worker's slice is not reported. Left out deliberately: draining it
|
|
988
|
+
# needs a fourth marshalled channel beside `drain_reporters` / `drain_dependencies` / `drain_effects`
|
|
989
|
+
# in `Runner::PoolCoordinator`, and the default (unpooled) path already covers the reported bug.
|
|
990
|
+
def plugin_trust_refusal_diagnostics
|
|
991
|
+
return [] if plugin_registry.empty?
|
|
992
|
+
|
|
993
|
+
plugin_registry.plugins.filter_map { |plugin| plugin_trust_refusal_diagnostic(plugin) }
|
|
994
|
+
end
|
|
995
|
+
|
|
996
|
+
# Issue #1051 — the run-scoped plugin disclosures ({Plugin::Base#disclose_once}), the run's
|
|
997
|
+
# project-global notices about its own inputs. Two sources feed one table:
|
|
998
|
+
#
|
|
999
|
+
# - the coordinator-side registry, which is where a SEQUENTIAL run's `#prepare` and per-file hooks
|
|
1000
|
+
# ran; and
|
|
1001
|
+
# - `pooled_run_disclosures`, the pool coordinator's already-de-duplicated collection from the
|
|
1002
|
+
# pre-fork parent session and every worker payload.
|
|
1003
|
+
#
|
|
1004
|
+
# Both are keyed `[plugin id, key]` and the first registration of a pair wins, so a run emits one
|
|
1005
|
+
# row per pair no matter how many plugin instances (workers) reached it — the #1051 bug, where a
|
|
1006
|
+
# per-instance `@emitted` flag produced one row per WORKER.
|
|
1007
|
+
#
|
|
1008
|
+
# The emitted order is `(registry position, key)`, NOT registration order: a worker's slice
|
|
1009
|
+
# determines which instance registers a key first, so registration order is a function of
|
|
1010
|
+
# `--workers N` and would make a pooled run's stream differ from a sequential one's even with the
|
|
1011
|
+
# duplicates gone. Registry position is the plugin load order (topological by `consumes:`), which
|
|
1012
|
+
# both modes share.
|
|
1013
|
+
#
|
|
1014
|
+
# Position is `.rigor.yml:1:1` for every row; see {Plugin::Base#disclose_once} for why that and not
|
|
1015
|
+
# the first analysed file. A positioned batch ({Plugin::Base#emit_once}) shares the table but not
|
|
1016
|
+
# this stream — see {#plugin_run_emission_diagnostics}.
|
|
1017
|
+
def plugin_run_disclosure_diagnostics
|
|
1018
|
+
ordered_run_disclosure_records
|
|
1019
|
+
.reject { |record| record.key?(:diagnostics) }
|
|
1020
|
+
.map { |record| run_disclosure_diagnostic(record) }
|
|
1021
|
+
end
|
|
1022
|
+
|
|
1023
|
+
# Issue #1060 — the positioned batches ({Plugin::Base#emit_once}) from the same table, de-duplicated
|
|
1024
|
+
# by the same `[plugin id, key]` identity over the same sources, so the first registration of a key
|
|
1025
|
+
# wins whole and a batch is never merged row by row across workers. Unlike a disclosure, every row
|
|
1026
|
+
# keeps the position the plugin gave it; the engine only stamps `source_family: "plugin.<id>"`, the
|
|
1027
|
+
# same stamp a `#diagnostics_for_file` row gets, so a baseline keyed to the row's own file and
|
|
1028
|
+
# qualified rule matches it before and after a plugin moves onto this channel.
|
|
1029
|
+
#
|
|
1030
|
+
# Order is `(registry position, key)` and then the batch's own row order — the same
|
|
1031
|
+
# `--workers`-independent order the disclosure stream uses. The runner appends this stream right
|
|
1032
|
+
# after the per-file stream rather than into the run-level block: these rows are about files, and
|
|
1033
|
+
# the files they name are usually not among the analysed targets (a view template), so there is no
|
|
1034
|
+
# file slot to splice them into.
|
|
1035
|
+
def plugin_run_emission_diagnostics
|
|
1036
|
+
ordered_run_disclosure_records
|
|
1037
|
+
.select { |record| record.key?(:diagnostics) }
|
|
1038
|
+
.flat_map { |record| record[:diagnostics].map { |row| run_emission_diagnostic(row, record[:plugin_id]) } }
|
|
1039
|
+
end
|
|
1040
|
+
|
|
1041
|
+
def ordered_run_disclosure_records
|
|
1042
|
+
registry = plugin_registry
|
|
1043
|
+
return [] if registry.empty?
|
|
1044
|
+
|
|
1045
|
+
positions = {}
|
|
1046
|
+
registry.plugins.each_with_index { |plugin, index| positions[disclosure_plugin_id(plugin)] ||= index }
|
|
1047
|
+
collect_run_disclosure_records(registry)
|
|
1048
|
+
.sort_by { |record| [positions.fetch(record[:plugin_id], positions.size), record[:key].to_s] }
|
|
1049
|
+
end
|
|
1050
|
+
|
|
1051
|
+
def collect_run_disclosure_records(registry)
|
|
1052
|
+
records = {}
|
|
1053
|
+
Array(pooled_run_disclosures).each do |record|
|
|
1054
|
+
records[[record[:plugin_id], record[:key]]] ||= record
|
|
1055
|
+
end
|
|
1056
|
+
registry.plugins.each do |plugin|
|
|
1057
|
+
plugin_id = disclosure_plugin_id(plugin)
|
|
1058
|
+
Array(plugin.run_disclosure_records).each do |record|
|
|
1059
|
+
records[[plugin_id, record[:key]]] ||= record.merge(plugin_id: plugin_id)
|
|
1060
|
+
end
|
|
1061
|
+
rescue StandardError
|
|
1062
|
+
next
|
|
1063
|
+
end
|
|
1064
|
+
records.values
|
|
1065
|
+
end
|
|
1066
|
+
|
|
1067
|
+
def run_disclosure_diagnostic(record)
|
|
1068
|
+
Diagnostic.new(
|
|
1069
|
+
path: ".rigor.yml", line: 1, column: 1,
|
|
1070
|
+
message: record.fetch(:message),
|
|
1071
|
+
severity: record.fetch(:severity),
|
|
1072
|
+
rule: record.fetch(:rule),
|
|
1073
|
+
source_family: "plugin.#{record[:plugin_id]}"
|
|
1074
|
+
)
|
|
1075
|
+
end
|
|
1076
|
+
|
|
1077
|
+
def run_emission_diagnostic(row, plugin_id)
|
|
1078
|
+
Diagnostic.new(
|
|
1079
|
+
path: row.path, line: row.line, column: row.column,
|
|
1080
|
+
message: row.message,
|
|
1081
|
+
severity: row.severity,
|
|
1082
|
+
rule: row.rule,
|
|
1083
|
+
source_family: "plugin.#{plugin_id}"
|
|
1084
|
+
)
|
|
1085
|
+
end
|
|
1086
|
+
|
|
1087
|
+
def disclosure_plugin_id(plugin)
|
|
1088
|
+
plugin.manifest.id
|
|
1089
|
+
rescue StandardError
|
|
1090
|
+
plugin.class.to_s
|
|
1091
|
+
end
|
|
1092
|
+
|
|
1093
|
+
def plugin_trust_refusal_diagnostic(plugin)
|
|
1094
|
+
summary = plugin.io_boundary.refusal_summary
|
|
1095
|
+
return nil if summary.nil?
|
|
1096
|
+
|
|
1097
|
+
plugin_id = plugin.manifest.id
|
|
1098
|
+
Diagnostic.new(
|
|
1099
|
+
path: ".rigor.yml", line: 1, column: 1,
|
|
1100
|
+
message: "plugin #{plugin_id.inspect} had #{summary[:count]} read(s) refused by the trust " \
|
|
1101
|
+
"policy; first refused path: #{summary[:first_path].inspect}, outside read root " \
|
|
1102
|
+
"#{summary[:nearest_root].inspect}. Spell the path the way that read root spells it " \
|
|
1103
|
+
"(a symlink alias such as macOS' /tmp does not match its real path), or add a " \
|
|
1104
|
+
"`plugins_io.allowed_paths:` entry in .rigor.yml covering the path.",
|
|
1105
|
+
severity: :info,
|
|
1106
|
+
rule: "plugin_trust.read-refused",
|
|
1107
|
+
source_family: :builtin
|
|
1108
|
+
)
|
|
1109
|
+
rescue StandardError
|
|
1110
|
+
nil
|
|
1111
|
+
end
|
|
1112
|
+
|
|
814
1113
|
def build_reporter_diagnostic(source_location, rule:, message:)
|
|
815
1114
|
path, line, column = location_fields(source_location)
|
|
816
1115
|
Diagnostic.new(
|
|
@@ -877,6 +1176,10 @@ module Rigor
|
|
|
877
1176
|
@cached_plugin_prepare_diagnostics_reader.call
|
|
878
1177
|
end
|
|
879
1178
|
|
|
1179
|
+
def pooled_run_disclosures
|
|
1180
|
+
@pooled_run_disclosures_reader.call
|
|
1181
|
+
end
|
|
1182
|
+
|
|
880
1183
|
def pre_eval_diagnostics_from_scanner
|
|
881
1184
|
@pre_eval_diagnostics_from_scanner_reader.call
|
|
882
1185
|
end
|
|
@@ -889,6 +1192,10 @@ module Rigor
|
|
|
889
1192
|
@quarantined_signatures_snapshot_reader.call
|
|
890
1193
|
end
|
|
891
1194
|
|
|
1195
|
+
def signature_standdowns_snapshot
|
|
1196
|
+
@signature_standdowns_snapshot_reader.call
|
|
1197
|
+
end
|
|
1198
|
+
|
|
892
1199
|
def env_build_failure_snapshot
|
|
893
1200
|
@env_build_failure_snapshot_reader.call
|
|
894
1201
|
end
|
|
@@ -58,8 +58,7 @@ module Rigor
|
|
|
58
58
|
"every run of the project."
|
|
59
59
|
private_constant :MESSAGE
|
|
60
60
|
|
|
61
|
-
# @param
|
|
62
|
-
# @param virtual_rbs [Array<Array(String, String)>, nil] `[buffer name, RBS source]` pairs the
|
|
61
|
+
# @param virtual_rbs — `[buffer name, RBS source]` pairs the
|
|
63
62
|
# run ALREADY resolved; never a loader built for this pass. Empty / nil simply drops the
|
|
64
63
|
# virtual-RBS stratum.
|
|
65
64
|
def initialize(configuration:, virtual_rbs: nil)
|
|
@@ -67,7 +66,7 @@ module Rigor
|
|
|
67
66
|
@virtual_rbs = virtual_rbs
|
|
68
67
|
end
|
|
69
68
|
|
|
70
|
-
# @return
|
|
69
|
+
# @return zero or one.
|
|
71
70
|
def diagnostics
|
|
72
71
|
return NO_DIAGNOSTICS if @configuration.effects_enabled?
|
|
73
72
|
return NO_DIAGNOSTICS if @configuration.disabled_rules.include?(RULE)
|
|
@@ -78,22 +78,21 @@ module Rigor
|
|
|
78
78
|
LABELS_CONSEQUENCE = "the label is not registered"
|
|
79
79
|
private_constant :LABELS_CONSEQUENCE
|
|
80
80
|
|
|
81
|
-
# @param
|
|
82
|
-
# @param
|
|
83
|
-
# @param
|
|
84
|
-
# @param discovery [#call] forces and returns the cross-file discovery tables as
|
|
81
|
+
# @param rbs_loader — the run's loader; nil disables the pass.
|
|
82
|
+
# @param effect_table — the propagated graph.
|
|
83
|
+
# @param discovery — forces and returns the cross-file discovery tables as
|
|
85
84
|
# `[def_sources, singleton_def_sources, class_sources]`. Called only when a finding needs a
|
|
86
85
|
# position — a judged-clean envelope never forces it.
|
|
87
|
-
# @param sources
|
|
88
|
-
# @param unit_sources
|
|
86
|
+
# @param sources — in-memory sources, for the buffer-backed run path.
|
|
87
|
+
# @param unit_sources — `Runner#effect_sources` — where each effect
|
|
89
88
|
# unit is defined, which is what an `effects.envelopes[].match:` path glob selects on. Its paths
|
|
90
89
|
# are relativised against the working directory, which is the project root for every run that
|
|
91
90
|
# reaches here (the same assumption `Snapshot.build` makes about `reach:`).
|
|
92
|
-
# @param ancestry
|
|
91
|
+
# @param ancestry — returns the run's as-written superclass table
|
|
93
92
|
# (`FileCollection#superclasses`) — the nominal relation `effect.liskov-widened` reads. A
|
|
94
93
|
# lambda, and called only once an envelope exists, because merging the run's collections is
|
|
95
|
-
# not free.
|
|
96
|
-
# @param apply_tolerated
|
|
94
|
+
# not free. nil leaves that relation empty.
|
|
95
|
+
# @param apply_tolerated — false runs the judgment with an empty tolerated set
|
|
97
96
|
# (`--no-tolerated-effects`).
|
|
98
97
|
def initialize(configuration:, rbs_loader:, effect_table:, discovery:, # rubocop:disable Metrics/ParameterLists
|
|
99
98
|
sources: nil, unit_sources: nil, ancestry: nil, apply_tolerated: true,
|
|
@@ -109,7 +108,7 @@ module Rigor
|
|
|
109
108
|
@apply_tolerated = apply_tolerated
|
|
110
109
|
end
|
|
111
110
|
|
|
112
|
-
# @return
|
|
111
|
+
# @return one per (method, exceeding label) plus one per unrecognised
|
|
113
112
|
# label, suppression already applied.
|
|
114
113
|
def diagnostics
|
|
115
114
|
return NO_DIAGNOSTICS unless @configuration.effects_check?
|
|
@@ -251,9 +250,7 @@ module Rigor
|
|
|
251
250
|
)
|
|
252
251
|
end
|
|
253
252
|
|
|
254
|
-
def table_class_names
|
|
255
|
-
@effect_table.keys.filter_map { |key| Effects::MethodKey.owner(key) }.uniq
|
|
256
|
-
end
|
|
253
|
+
def table_class_names = @effect_table.keys.filter_map { |k| Effects::MethodKey.envelope_owner(k) }.uniq
|
|
257
254
|
|
|
258
255
|
def judge(scan)
|
|
259
256
|
Effects::EnvelopeCheck.run(
|
|
@@ -302,7 +299,7 @@ module Rigor
|
|
|
302
299
|
|
|
303
300
|
def build_diagnostic(finding)
|
|
304
301
|
Diagnostic.new(
|
|
305
|
-
path: finding.path || ".rigor.yml",
|
|
302
|
+
path: finding.path || unit_source_path(finding.key) || ".rigor.yml",
|
|
306
303
|
line: finding.line,
|
|
307
304
|
column: 1,
|
|
308
305
|
message: message_for(finding),
|
|
@@ -313,6 +310,13 @@ module Rigor
|
|
|
313
310
|
)
|
|
314
311
|
end
|
|
315
312
|
|
|
313
|
+
# #393 — a template unit has no `def` for {Effects::EnvelopeCheck::Positions} to find, so a view
|
|
314
|
+
# finding would land on `.rigor.yml` — the config file, not the template the reviewer has to open.
|
|
315
|
+
# `Runner#effect_sources` already records the file every unit key came from; the line stays at the
|
|
316
|
+
# finding's own (1 for a whole-file unit), because the bound is exceeded by the unit, not by one
|
|
317
|
+
# line of it, and the explanation chain names the origin site.
|
|
318
|
+
def unit_source_path(key) = Effects::MethodKey.template_unit?(key) ? @unit_sources[key.to_s]&.first : nil
|
|
319
|
+
|
|
316
320
|
def message_for(finding)
|
|
317
321
|
EnvelopeMessages.exceeded(finding)
|
|
318
322
|
end
|