rigortype 0.3.7 → 0.3.9
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 +1 -1
- data/data/capability_roles/capability_roles.rbs +36 -0
- data/data/gem_overlay/activesupport/core_ext.rbs +109 -13
- data/docs/handbook/02-everyday-types.md +17 -14
- data/docs/handbook/03-narrowing.md +37 -4
- 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 +14 -1
- data/docs/handbook/11-sig-gen.md +96 -15
- 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 +39 -4
- data/docs/manual/03-configuration.md +11 -0
- data/docs/manual/04-diagnostics.md +12 -1
- data/docs/manual/07-plugins.md +15 -5
- data/docs/manual/08-skills.md +23 -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 +6 -1
- data/docs/manual/18-removing-dead-code.md +10 -8
- data/docs/manual/plugins/rigor-actionpack.md +18 -0
- data/docs/manual/plugins/rigor-activerecord.md +28 -0
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +32 -2
- data/docs/manual/plugins/rigor-rbs-inline.md +42 -1
- data/lib/rigor/analysis/baseline.rb +2 -2
- 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/ivar_write_collector.rb +10 -2
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +1 -1
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +15 -6
- data/lib/rigor/analysis/check_rules/rule_ids.rb +1 -1
- data/lib/rigor/analysis/check_rules/rule_walk.rb +39 -4
- 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/unreachable_clause_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +0 -1
- data/lib/rigor/analysis/check_rules.rb +200 -32
- data/lib/rigor/analysis/crash_signature.rb +69 -13
- 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 +6 -1
- data/lib/rigor/analysis/incremental.rb +16 -0
- data/lib/rigor/analysis/incremental_session.rb +100 -29
- data/lib/rigor/analysis/plugin_fact_fingerprint.rb +0 -1
- data/lib/rigor/analysis/reachability/graph.rb +3 -5
- data/lib/rigor/analysis/reachability/plugin_roots.rb +6 -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 +2 -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 +4 -1
- data/lib/rigor/analysis/run_cache_key.rb +1 -1
- 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 +316 -40
- data/lib/rigor/analysis/runner/effect_annotation_residual_pass.rb +2 -3
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +9 -10
- data/lib/rigor/analysis/runner/pool_coordinator.rb +430 -77
- data/lib/rigor/analysis/runner/project_pre_passes.rb +12 -6
- data/lib/rigor/analysis/runner/run_snapshots.rb +13 -3
- data/lib/rigor/analysis/runner.rb +200 -43
- data/lib/rigor/analysis/worker_session.rb +36 -12
- data/lib/rigor/bleeding_edge.rb +12 -24
- data/lib/rigor/builtins/hkt_builtins.rb +2 -2
- data/lib/rigor/builtins/imported_refinements.rb +166 -30
- data/lib/rigor/builtins/predefined_constant_refinements.rb +5 -7
- data/lib/rigor/builtins/regex_refinement.rb +4 -4
- data/lib/rigor/builtins/static_return_refinements.rb +5 -6
- data/lib/rigor/cache/annotation_location.rb +70 -0
- data/lib/rigor/cache/descriptor.rb +58 -20
- data/lib/rigor/cache/engine_source.rb +4 -4
- data/lib/rigor/cache/file_digest.rb +9 -1
- data/lib/rigor/cache/incremental_snapshot.rb +40 -6
- 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 +79 -11
- data/lib/rigor/cache/rbs_environment.rb +8 -4
- data/lib/rigor/cache/rbs_environment_marshal_patch.rb +39 -0
- data/lib/rigor/cache/rbs_known_class_names.rb +0 -3
- data/lib/rigor/cache/store.rb +85 -33
- 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 +3 -3
- data/lib/rigor/cli/docs_command.rb +2 -2
- 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 +1 -1
- data/lib/rigor/cli/plugins_command.rb +2 -1
- data/lib/rigor/cli/prism_colorizer.rb +2 -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 +31 -2
- data/lib/rigor/cli/skill_command.rb +1 -1
- data/lib/rigor/cli/skill_deep_probe.rb +4 -4
- data/lib/rigor/cli/skill_describe.rb +36 -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 +10 -6
- 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 +68 -6
- data/lib/rigor/config_audit.rb +30 -5
- data/lib/rigor/configuration/severity_profile.rb +6 -6
- data/lib/rigor/configuration.rb +43 -4
- data/lib/rigor/effects/attribution.rb +1 -3
- data/lib/rigor/effects/config_envelopes.rb +6 -8
- data/lib/rigor/effects/definition_lines.rb +25 -6
- data/lib/rigor/effects/effect_table.rb +0 -1
- data/lib/rigor/effects/entry_points.rb +0 -2
- data/lib/rigor/effects/envelope_check.rb +8 -8
- data/lib/rigor/effects/envelope_index.rb +5 -8
- data/lib/rigor/effects/framework_units.rb +4 -6
- data/lib/rigor/effects/identity.rb +4 -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/method_key.rb +1 -1
- data/lib/rigor/effects/plugin_facts.rb +4 -6
- data/lib/rigor/effects/propagator.rb +2 -3
- data/lib/rigor/effects/scanner.rb +1 -1
- data/lib/rigor/effects/signature_sources.rb +3 -5
- data/lib/rigor/effects/snapshot.rb +10 -10
- data/lib/rigor/effects/snapshot_diff.rb +1 -1
- data/lib/rigor/effects/unit_scan.rb +10 -10
- data/lib/rigor/effects/unknown_label_check.rb +3 -8
- data/lib/rigor/effects/unknown_label_report.rb +3 -4
- 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 +28 -0
- data/lib/rigor/environment/installed_gem_set.rb +85 -0
- data/lib/rigor/environment/lockfile_resolver.rb +51 -4
- 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 +613 -113
- data/lib/rigor/environment.rb +189 -27
- data/lib/rigor/flow_contribution/merger.rb +0 -2
- data/lib/rigor/flow_contribution.rb +11 -13
- data/lib/rigor/inference/acceptance.rb +153 -8
- data/lib/rigor/inference/block_parameter_binder.rb +2 -3
- data/lib/rigor/inference/body_fixpoint.rb +5 -5
- data/lib/rigor/inference/budget_trace.rb +1 -5
- data/lib/rigor/inference/captured_locals.rb +2 -3
- data/lib/rigor/inference/closure_escape_analyzer.rb +2 -4
- data/lib/rigor/inference/coverage_scanner.rb +4 -6
- data/lib/rigor/inference/dynamic_origin.rb +1 -1
- data/lib/rigor/inference/element_read_widening.rb +168 -0
- data/lib/rigor/inference/expression_typer.rb +763 -143
- data/lib/rigor/inference/fork_map.rb +5 -7
- data/lib/rigor/inference/hkt_reducer.rb +2 -3
- data/lib/rigor/inference/hkt_registry.rb +19 -10
- data/lib/rigor/inference/hkt_sugar_translator.rb +15 -21
- data/lib/rigor/inference/index_write_widening.rb +1 -5
- data/lib/rigor/inference/macro_block_self_type.rb +1 -4
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +2 -9
- 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/file_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +2 -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/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 +61 -47
- data/lib/rigor/inference/method_dispatcher/random_folding.rb +82 -0
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +165 -31
- 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/set_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +1 -1
- 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 +4 -5
- 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 +12 -13
- data/lib/rigor/inference/method_parameter_binder.rb +4 -6
- data/lib/rigor/inference/multi_target_binder.rb +1 -3
- data/lib/rigor/inference/mutation_rejoin.rb +168 -0
- data/lib/rigor/inference/mutation_widening.rb +100 -51
- data/lib/rigor/inference/narrowing.rb +299 -46
- data/lib/rigor/inference/optimistic_origin.rb +1 -7
- data/lib/rigor/inference/origin_lookup.rb +2 -3
- data/lib/rigor/inference/parameter_inference_collector.rb +5 -6
- data/lib/rigor/inference/pre_eval_constants.rb +6 -5
- data/lib/rigor/inference/precision_scanner.rb +3 -4
- data/lib/rigor/inference/project_patched_methods.rb +2 -2
- data/lib/rigor/inference/project_patched_scanner.rb +3 -3
- 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 +3 -3
- data/lib/rigor/inference/refinement_mutation.rb +72 -0
- data/lib/rigor/inference/scope_indexer.rb +688 -151
- data/lib/rigor/inference/statement_evaluator.rb +221 -50
- data/lib/rigor/inference/string_mutation.rb +60 -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/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 +1 -1
- data/lib/rigor/language_server/diagnostic_publisher.rb +4 -4
- 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 +2 -2
- data/lib/rigor/language_server/incremental_sync.rb +6 -6
- data/lib/rigor/language_server/project_context.rb +2 -5
- 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/plugin/base.rb +90 -21
- data/lib/rigor/plugin/bundled_catalog.rb +167 -0
- data/lib/rigor/plugin/effect_attribution.rb +7 -7
- 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 +31 -12
- 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 +23 -1
- data/lib/rigor/plugin/registry.rb +67 -14
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +12 -1
- data/lib/rigor/plugin/trust_policy.rb +2 -4
- data/lib/rigor/plugin/type_node_resolver.rb +3 -3
- 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 +11 -11
- data/lib/rigor/protection/kill_signature.rb +2 -4
- data/lib/rigor/protection/measurement_integrity.rb +1 -3
- data/lib/rigor/protection/mutation_cache.rb +6 -9
- 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 +12 -13
- data/lib/rigor/rbs_extended/hkt_directives.rb +16 -1
- data/lib/rigor/rbs_extended/reporter.rb +122 -16
- data/lib/rigor/rbs_extended.rb +67 -22
- data/lib/rigor/reflection/constant_path.rb +126 -0
- data/lib/rigor/reflection.rb +26 -10
- data/lib/rigor/runtime/jit.rb +6 -8
- data/lib/rigor/scope/discovery_index.rb +30 -0
- data/lib/rigor/scope.rb +203 -4
- data/lib/rigor/sig_gen/generator.rb +181 -102
- 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/observation_collector.rb +17 -15
- 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 +17 -11
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +111 -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/writer.rb +23 -6
- 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 +2 -5
- 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 +68 -5
- data/lib/rigor/type/data_class.rb +2 -2
- data/lib/rigor/type/data_instance.rb +4 -4
- data/lib/rigor/type/float_range.rb +128 -0
- data/lib/rigor/type/hash_shape.rb +5 -5
- data/lib/rigor/type/integer_range.rb +13 -8
- data/lib/rigor/type/nominal.rb +8 -2
- data/lib/rigor/type/refined.rb +3 -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/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.rb +1 -0
- 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 +1 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +33 -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.rb +28 -2
- data/plugins/rigor-actionpack/sig/action_controller.rbs +71 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +0 -4
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -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 +1 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +3 -4
- 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 +42 -7
- data/plugins/rigor-activerecord/sig/active_record/framework.rbs +123 -0
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +1 -0
- 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 +119 -14
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +1 -0
- data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +1 -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 +1 -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.rb +36 -4
- data/plugins/rigor-ffi-rzmq/lib/rigor/plugin/ffi_rzmq.rb +1 -0
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +8 -6
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +6 -3
- 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 +0 -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 +1 -0
- 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 +1 -0
- 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 +1 -10
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +3 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +2 -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 +1 -0
- 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.rb +128 -3
- 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 +1 -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 +1 -0
- 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 +4 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +7 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +5 -5
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +1 -0
- data/sig/rigor/analysis/reachability/scan_cache.rbs +12 -0
- data/sig/rigor/cache.rbs +2 -3
- data/sig/rigor/environment.rbs +11 -0
- data/sig/rigor/inference.rbs +3 -10
- data/sig/rigor/plugin/io_boundary.rbs +4 -0
- data/sig/rigor/plugin/manifest.rbs +2 -1
- data/sig/rigor/reflection.rbs +3 -1
- data/sig/rigor/scope.rbs +24 -3
- data/sig/rigor/sig_gen/skip_reason_catalog.rbs +14 -0
- data/sig/rigor/type.rbs +27 -1
- data/sig/rigor.rbs +1 -0
- data/skills/rigor-ask/SKILL.md +8 -6
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +13 -2
- data/skills/rigor-project-init/SKILL.md +6 -3
- data/skills/rigor-project-init/references/02-configure.md +10 -6
- data/skills/rigor-project-init/references/06-agent-contract.md +67 -0
- data/skills/rigor-type-oracle/SKILL.md +228 -0
- data/skills/rigor-type-oracle/references/01-oracle-commands.md +261 -0
- data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +52 -0
- data/skills/rigor-type-oracle/references/03-gap-protocol.md +128 -0
- data/skills/rigor-unused-adjudicate/SKILL.md +8 -5
- metadata +28 -3
- data/lib/rigor/cli/probe_environment.rb +0 -85
- data/sig/rigor/inference/builtins/numeric_catalog.rbs +0 -3
|
@@ -17,10 +17,9 @@ module Rigor
|
|
|
17
17
|
# {.for} answers `nil` unless {LabelIntent} says the spelling is evidently a label — the whole
|
|
18
18
|
# point of the diagnostic is that it fires where intent is evident and nowhere else.
|
|
19
19
|
class UnknownLabelReport < Data.define(:token, :suggestion, :retirement)
|
|
20
|
-
# @param token
|
|
21
|
-
# @param registry
|
|
22
|
-
# @param siblings
|
|
23
|
-
# @return [UnknownLabelReport, nil]
|
|
20
|
+
# @param token — the spelling as written.
|
|
21
|
+
# @param registry — the vocabulary after plugin load.
|
|
22
|
+
# @param siblings — the other tokens written alongside it.
|
|
24
23
|
def self.for(token:, registry:, siblings: [])
|
|
25
24
|
return nil unless LabelIntent.evident?(token, registry, siblings: siblings)
|
|
26
25
|
|
|
@@ -46,14 +46,14 @@ module Rigor
|
|
|
46
46
|
"bundler", "rubygems"
|
|
47
47
|
].freeze
|
|
48
48
|
|
|
49
|
-
# @param bundle_path
|
|
49
|
+
# @param bundle_path — explicit path to the bundler install root. When `nil`,
|
|
50
50
|
# falls back to `auto_detect` if `auto_detect:` is true.
|
|
51
|
-
# @param project_root
|
|
52
|
-
# @param auto_detect
|
|
51
|
+
# @param project_root — resolution base for relative `bundle_path:` and the auto-detect search.
|
|
52
|
+
# @param auto_detect — when true and `bundle_path:` is nil, try `.bundle/config`'s
|
|
53
53
|
# `BUNDLE_PATH:` and `vendor/bundle/` under `project_root`.
|
|
54
|
-
# @param skip_gems
|
|
54
|
+
# @param skip_gems — gem names to exclude from discovery. Defaults to
|
|
55
55
|
# {SKIPPED_GEMS_BY_DEFAULT}.
|
|
56
|
-
# @param locked_gems
|
|
56
|
+
# @param locked_gems — Optional O4-Layer-3 filter.
|
|
57
57
|
# When non-nil and non-empty, only `sig/` directories whose gem `(name, version, platform)` tuple
|
|
58
58
|
# matches a lockfile entry are returned. Bundle entries absent from the lockfile (or at a drifted
|
|
59
59
|
# version) are silently dropped — the lockfile is treated as the source of truth for "what gems this
|
|
@@ -63,7 +63,7 @@ module Rigor
|
|
|
63
63
|
# source keeps its stale `bundler/gems/` directory under the SAME name until a `bundle clean`. Pass
|
|
64
64
|
# `nil` (the default) to keep the pre-Layer-3 behaviour of returning every non-skipped `sig/` under
|
|
65
65
|
# the bundle.
|
|
66
|
-
# @return
|
|
66
|
+
# @return every `<gem-dir>/sig` directory under the resolved bundle path, minus any
|
|
67
67
|
# whose gem name is in `skip_gems` and (when `locked_gems` is supplied) minus any whose `(name,
|
|
68
68
|
# version, platform)` does not match a lockfile entry.
|
|
69
69
|
def self.discover(bundle_path:, project_root: Dir.pwd, auto_detect: true,
|
|
@@ -136,8 +136,10 @@ module Rigor
|
|
|
136
136
|
|
|
137
137
|
private
|
|
138
138
|
|
|
139
|
+
# Allocates only when there is a prefix to strip (see `Environment#normalize_class_name`).
|
|
139
140
|
def normalize_name(name)
|
|
140
|
-
name.to_s
|
|
141
|
+
name = name.to_s
|
|
142
|
+
name.start_with?("::") ? name.delete_prefix("::") : name
|
|
141
143
|
end
|
|
142
144
|
end
|
|
143
145
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rigor
|
|
4
|
+
class Environment
|
|
5
|
+
# Issue #784 — a mutable, first-write-wins record of one shared-build failure, held by the otherwise
|
|
6
|
+
# frozen {Environment} the way {HktRegistryHolder} holds a memoised value. A lazy build that raises
|
|
7
|
+
# during per-file analysis records here at its seam instead of raising into every file's
|
|
8
|
+
# `analyze_body` rescue; the coordinator snapshots the slot after the file loop (the build is lazy, so
|
|
9
|
+
# a snapshot taken before the loop reads nothing) and the aggregator surfaces it once for the run.
|
|
10
|
+
#
|
|
11
|
+
# First-write-wins: the build is memoised, so a second failure can only be the same one re-observed.
|
|
12
|
+
#
|
|
13
|
+
# Concurrency: single-threaded use only, the same discipline as {HktRegistryHolder}.
|
|
14
|
+
class FailureSlot
|
|
15
|
+
def initialize
|
|
16
|
+
@value = nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @param value — a Marshal-clean tuple — the fork pool ships it back from the worker.
|
|
20
|
+
def record(value)
|
|
21
|
+
@value = value.freeze if @value.nil?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @return the recorded tuple, or nil when the build never failed.
|
|
25
|
+
attr_reader :value
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lockfile_resolver"
|
|
4
|
+
|
|
5
|
+
module Rigor
|
|
6
|
+
class Environment
|
|
7
|
+
# Issue #530 — the gem set for a project that has NO `Gemfile.lock`.
|
|
8
|
+
#
|
|
9
|
+
# ADR-82 WD9's constant-ownership index is driven by the LOCKED gem set, so a project without a
|
|
10
|
+
# lockfile (a plain library, a `gemspec`-only gem, an app vendored outside Bundler) handed the index
|
|
11
|
+
# nothing at all: every constant reaching into a real, installed, RBS-less gem recorded the generic
|
|
12
|
+
# cause, and the entire gem boundary reported as `engine_gap` — "report this to Rigor" — where the
|
|
13
|
+
# honest story is `add_rbs`. Measured on slim, whose whole Temple boundary lands that way while haml,
|
|
14
|
+
# which has a lockfile, attributes the same gem correctly.
|
|
15
|
+
#
|
|
16
|
+
# Degrading to the gems that are actually INSTALLED keeps ADR-82's honesty criterion intact. A name
|
|
17
|
+
# here is a gem that exists on disk; the index still has to READ its entry file before claiming any
|
|
18
|
+
# constant, and its lack of RBS is established by the same {RbsCoverageReport.classify} pass the
|
|
19
|
+
# lock-driven path uses. The version is the one on disk rather than a declared one — which is the
|
|
20
|
+
# version a lockfile-less project would load anyway.
|
|
21
|
+
#
|
|
22
|
+
# Only the missing-gem provenance index consumes this. The ADR-72 gem overlays stay Gemfile.lock-gated:
|
|
23
|
+
# an overlay changes what type-checks, so it needs the project's own declaration, while this
|
|
24
|
+
# side-channel only changes a label.
|
|
25
|
+
module InstalledGemSet
|
|
26
|
+
module_function
|
|
27
|
+
|
|
28
|
+
# @param bundle_path — the target's resolved bundler install root, or nil.
|
|
29
|
+
# @return frozen `gem name => LockfileResolver::LockedGem`, the shape
|
|
30
|
+
# {RbsCoverageReport.classify} consumes. Empty when neither resolver sees anything, which leaves
|
|
31
|
+
# today's generic cause in place.
|
|
32
|
+
def gems(bundle_path: nil)
|
|
33
|
+
found = from_bundle_tree(bundle_path)
|
|
34
|
+
found = from_installed_specs if found.empty?
|
|
35
|
+
found.freeze
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# `<bundle>/ruby/X.Y.Z/gems/<name>-<version>/` — the same pure-filesystem layout
|
|
39
|
+
# {MissingGemConstantIndex.bundle_gem_dirs} walks, preferred over the host's gems so a project that
|
|
40
|
+
# vendored its bundle without committing the lockfile is read from its own tree. A platform-tagged
|
|
41
|
+
# directory (`ffi-1.17.4-aarch64-linux-gnu`) does not split into a name/version pair and is skipped:
|
|
42
|
+
# those gems ship native code, not the pure-Ruby constants this feeds.
|
|
43
|
+
def from_bundle_tree(bundle_path)
|
|
44
|
+
return {} if bundle_path.nil?
|
|
45
|
+
|
|
46
|
+
base = Pathname.new(bundle_path)
|
|
47
|
+
return {} unless base.directory?
|
|
48
|
+
|
|
49
|
+
Dir.glob(base.join("ruby", "*", "gems", "*")).each_with_object({}) do |dir, acc|
|
|
50
|
+
name, version = split_name_version(File.basename(dir))
|
|
51
|
+
next unless name
|
|
52
|
+
|
|
53
|
+
acc[name] ||= locked_gem(name, version)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# The gems the RUNNING Ruby can load. For the shipped `gem install rigortype` distribution that IS a
|
|
58
|
+
# lockfile-less project's gem environment — the same set its own `require` would reach. Under
|
|
59
|
+
# `bundle exec` it is the analyzer's own bundle instead (the `Gem.paths`-no-ops-under-Bundler
|
|
60
|
+
# mechanism ADR-90 documents), which yields fewer names, never wrong ones. Highest version per name,
|
|
61
|
+
# because `stubs` promises no ordering.
|
|
62
|
+
def from_installed_specs
|
|
63
|
+
Gem::Specification.stubs.each_with_object({}) do |stub, acc|
|
|
64
|
+
previous = acc[stub.name]
|
|
65
|
+
next if previous && Gem::Version.new(previous.version) >= stub.version
|
|
66
|
+
|
|
67
|
+
acc[stub.name] = locked_gem(stub.name, stub.version.to_s)
|
|
68
|
+
end
|
|
69
|
+
rescue StandardError
|
|
70
|
+
{}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def locked_gem(name, version)
|
|
74
|
+
LockfileResolver::LockedGem.new(name: name, version: version, platform: "ruby")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Splits a gem install directory's basename. The version tail is anchored on a leading digit and must
|
|
78
|
+
# carry no further hyphen, which is what excludes the platform-tagged variants above.
|
|
79
|
+
def split_name_version(basename)
|
|
80
|
+
match = /\A(.+)-(\d[^-]*)\z/.match(basename)
|
|
81
|
+
match ? [match[1], match[2]] : nil
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -39,13 +39,13 @@ module Rigor
|
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
# @param lockfile_path
|
|
42
|
+
# @param lockfile_path — explicit path to the Gemfile.lock. When `nil`, falls
|
|
43
43
|
# back to `auto_detect` if `auto_detect:` is true.
|
|
44
|
-
# @param project_root
|
|
44
|
+
# @param project_root — resolution base for a relative `lockfile_path:` and the auto-detect
|
|
45
45
|
# search.
|
|
46
|
-
# @param auto_detect
|
|
46
|
+
# @param auto_detect — when true and `lockfile_path:` is nil, look for
|
|
47
47
|
# `<project_root>/Gemfile.lock`.
|
|
48
|
-
# @return
|
|
48
|
+
# @return frozen map of gem name → locked entry. Returns the empty frozen
|
|
49
49
|
# hash when no lockfile is resolvable, when the file is unreadable, or when Bundler refuses to parse
|
|
50
50
|
# it.
|
|
51
51
|
def self.locked_gems(lockfile_path:, project_root: Dir.pwd, auto_detect: true)
|
|
@@ -59,6 +59,53 @@ module Rigor
|
|
|
59
59
|
parse(resolved)
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
# The gems the project declares for itself — the lockfile's `DEPENDENCIES` section, which is what a
|
|
63
|
+
# `Gemfile` actually asked for, as opposed to {locked_gems}'s full resolved graph. A consumer that
|
|
64
|
+
# advises the user about their own stack has to read this one: `minitest`, `i18n`, `activesupport` and
|
|
65
|
+
# `ffi` sit in nearly every Rails lock as somebody else's dependency, so matching against the resolved
|
|
66
|
+
# graph advises about gems the project never chose.
|
|
67
|
+
#
|
|
68
|
+
# @param lockfile_path — explicit path to the Gemfile.lock; `nil` falls back to `auto_detect`.
|
|
69
|
+
# @param project_root — resolution base for a relative `lockfile_path:` and the auto-detect search.
|
|
70
|
+
# @param auto_detect — when true and `lockfile_path:` is nil, look for `<project_root>/Gemfile.lock`.
|
|
71
|
+
# @return frozen set of gem names. Empty when no lockfile is resolvable, when it is unreadable, when
|
|
72
|
+
# Bundler refuses to parse it, or when the lockfile has no `DEPENDENCIES` section at all.
|
|
73
|
+
def self.direct_dependency_names(lockfile_path:, project_root: Dir.pwd, auto_detect: true)
|
|
74
|
+
resolved = resolve_lockfile_path(
|
|
75
|
+
lockfile_path: lockfile_path,
|
|
76
|
+
project_root: project_root,
|
|
77
|
+
auto_detect: auto_detect
|
|
78
|
+
)
|
|
79
|
+
return EMPTY_NAMES unless resolved
|
|
80
|
+
|
|
81
|
+
parse_dependency_names(resolved)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
EMPTY_NAMES = Set.new.freeze
|
|
85
|
+
private_constant :EMPTY_NAMES
|
|
86
|
+
|
|
87
|
+
def self.parse_dependency_names(path)
|
|
88
|
+
require "bundler"
|
|
89
|
+
rescue LoadError => e
|
|
90
|
+
warn "rigor: cannot read #{path}: bundler is not available (#{e.message})"
|
|
91
|
+
EMPTY_NAMES
|
|
92
|
+
else
|
|
93
|
+
do_parse_dependency_names(path)
|
|
94
|
+
end
|
|
95
|
+
private_class_method :parse_dependency_names
|
|
96
|
+
|
|
97
|
+
def self.do_parse_dependency_names(path)
|
|
98
|
+
parser = Bundler::LockfileParser.new(File.read(path.to_s))
|
|
99
|
+
# `#dependencies` is the parsed `DEPENDENCIES` section keyed by gem name, so the version constraint
|
|
100
|
+
# and the pinned-source `!` suffix are already stripped for us. The upstream bundler RBS shim does
|
|
101
|
+
# not declare it.
|
|
102
|
+
parser.dependencies.keys.to_set { |name| -name.to_s }.freeze # rigor:disable undefined-method
|
|
103
|
+
rescue StandardError => e
|
|
104
|
+
warn "rigor: ignoring malformed #{path} (#{e.class}: #{e.message})"
|
|
105
|
+
EMPTY_NAMES
|
|
106
|
+
end
|
|
107
|
+
private_class_method :do_parse_dependency_names
|
|
108
|
+
|
|
62
109
|
# Returns the resolved lockfile path (`Pathname`) or `nil` when neither explicit nor auto-detect
|
|
63
110
|
# produces one. Public so the stats banner can show what rigor picked up.
|
|
64
111
|
def self.resolve_lockfile_path(lockfile_path:, project_root: Dir.pwd, auto_detect: true)
|
|
@@ -37,12 +37,12 @@ module Rigor
|
|
|
37
37
|
module MissingGemConstantIndex
|
|
38
38
|
module_function
|
|
39
39
|
|
|
40
|
-
# @param gems
|
|
40
|
+
# @param gems — `[gem_name, version]` pairs (the `:missing` rows of
|
|
41
41
|
# {RbsCoverageReport}).
|
|
42
|
-
# @param bundle_path
|
|
43
|
-
# @param spec_resolver
|
|
42
|
+
# @param bundle_path — the target's resolved bundler install root, or nil.
|
|
43
|
+
# @param spec_resolver — `(name, version) -> String?` fallback dir resolver. Injectable for
|
|
44
44
|
# specs; the default is the RubyGems-metadata lookup (no code load).
|
|
45
|
-
# @return
|
|
45
|
+
# @return frozen `root constant name => gem name`. On a collision (two gems
|
|
46
46
|
# declaring the same top-level constant) the first gem wins — the CAUSE recorded downstream
|
|
47
47
|
# (external gem without RBS) is true under either owner.
|
|
48
48
|
def build(gems, bundle_path: nil, spec_resolver: method(:installed_gem_dir))
|
|
@@ -37,17 +37,17 @@ module Rigor
|
|
|
37
37
|
DEFAULT_COLLECTION_PATH = ".gem_rbs_collection"
|
|
38
38
|
private_constant :DEFAULT_COLLECTION_PATH
|
|
39
39
|
|
|
40
|
-
# @param lockfile_path
|
|
40
|
+
# @param lockfile_path — explicit path to `rbs_collection.lock.yaml`. When `nil`,
|
|
41
41
|
# falls back to `auto_detect` if `auto_detect:` is true.
|
|
42
|
-
# @param project_root
|
|
42
|
+
# @param project_root — resolution base for relative `lockfile_path:` and the auto-detect
|
|
43
43
|
# search.
|
|
44
|
-
# @param auto_detect
|
|
44
|
+
# @param auto_detect — when true and `lockfile_path:` is nil, look for
|
|
45
45
|
# `<project_root>/rbs_collection.lock.yaml`.
|
|
46
|
-
# @param skip_gem_names
|
|
46
|
+
# @param skip_gem_names — gem names rigor already loads from its bundled
|
|
47
47
|
# stdlib (the merged `DEFAULT_LIBRARIES + libraries:` set). Entries whose `name` is in this set are
|
|
48
48
|
# dropped regardless of `source.type` to avoid `RBS::DuplicatedDeclarationError` on
|
|
49
49
|
# stdlib-extracted default gems. Defaults to empty.
|
|
50
|
-
# @return
|
|
50
|
+
# @return every `<collection_path>/<gem-name>/<gem-version>/` directory listed in the
|
|
51
51
|
# lockfile whose entry has a non-skipped source type, whose `name` is not in `skip_gem_names:`, and
|
|
52
52
|
# whose directory exists on disk. Returns `[]` when no lockfile is resolvable, when the YAML is
|
|
53
53
|
# unreadable, or when the collection path doesn't exist.
|
|
@@ -35,16 +35,16 @@ module Rigor
|
|
|
35
35
|
"idn-ruby", "mysql2", "nokogiri", "pg", "prism", "racc", "redis", "rubygems"
|
|
36
36
|
].freeze
|
|
37
37
|
|
|
38
|
-
# @param locked_gems
|
|
38
|
+
# @param locked_gems — The lockfile-resolved gem set. Empty
|
|
39
39
|
# hash → no coverage analysis to do.
|
|
40
|
-
# @param default_libraries
|
|
40
|
+
# @param default_libraries — gem names rigor auto-loads through
|
|
41
41
|
# `RBS::EnvironmentLoader#add(library:)`. Pass `Rigor::Environment::DEFAULT_LIBRARIES` from callers
|
|
42
42
|
# running in a project context.
|
|
43
|
-
# @param bundle_sig_paths
|
|
43
|
+
# @param bundle_sig_paths — the discovered `<bundle>/.../gems/<name>-<ver>/sig`
|
|
44
44
|
# paths from {BundleSigDiscovery.discover}.
|
|
45
|
-
# @param rbs_collection_paths
|
|
45
|
+
# @param rbs_collection_paths — the discovered `<collection>/<name>/<version>/`
|
|
46
46
|
# paths from {RbsCollectionDiscovery.discover}.
|
|
47
|
-
# @return
|
|
47
|
+
# @return one row per locked gem; sorted by gem name for deterministic output.
|
|
48
48
|
def self.classify(locked_gems:, default_libraries:,
|
|
49
49
|
bundle_sig_paths:, rbs_collection_paths:)
|
|
50
50
|
default_set = default_libraries.to_set
|
|
@@ -63,8 +63,10 @@ module Rigor
|
|
|
63
63
|
@ancestor_names_cache[key] = loader.ancestor_names_for(key)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
# Allocates only when there is a prefix to strip (see `Environment#normalize_class_name`).
|
|
66
67
|
def normalize_name(name)
|
|
67
|
-
name.to_s
|
|
68
|
+
name = name.to_s
|
|
69
|
+
name.start_with?("::") ? name.delete_prefix("::") : name
|
|
68
70
|
end
|
|
69
71
|
end
|
|
70
72
|
end
|