rigortype 0.4.6 → 0.4.7
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/gem_overlay/activesupport/core_ext.rbs +16 -13
- data/data/vendored_gem_sigs/bundler/bundler.rbs +1 -1
- data/data/vendored_gem_sigs/rubygems/rubygems_extras.rbs +4 -3
- data/docs/handbook/01-getting-started.md +5 -2
- data/docs/handbook/11-sig-gen.md +50 -3
- data/docs/handbook/appendix-phpstan.md +4 -4
- data/docs/manual/02-cli-reference.md +152 -26
- data/docs/manual/03-configuration.md +36 -3
- data/docs/manual/06-baseline.md +6 -4
- data/docs/manual/09-editor-integration.md +13 -2
- data/docs/manual/10-mcp-server.md +38 -2
- data/docs/manual/12-caching.md +4 -3
- data/docs/manual/plugins/rigor-actionpack.md +19 -11
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +20 -1
- data/lib/rigor/analysis/baseline.rb +24 -27
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +5 -6
- data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +4 -4
- data/lib/rigor/analysis/check_rules/duplicate_hash_key_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/inferred_param_guard.rb +85 -13
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +3 -2
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +0 -1
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +5 -8
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +1 -1
- data/lib/rigor/analysis/check_rules/rebinding_block_callees.rb +3 -3
- data/lib/rigor/analysis/check_rules/return_in_ensure_collector.rb +1 -2
- data/lib/rigor/analysis/check_rules/rule_ids.rb +1 -1
- data/lib/rigor/analysis/check_rules/rule_walk.rb +9 -7
- data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +3 -4
- data/lib/rigor/analysis/check_rules/special_global_setters.rb +3 -3
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +1 -1
- data/lib/rigor/analysis/check_rules.rb +124 -44
- data/lib/rigor/analysis/crash_signature.rb +2 -2
- data/lib/rigor/analysis/dependency_recorder.rb +4 -4
- data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +14 -3
- data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +1 -1
- data/lib/rigor/analysis/dependency_source_inference/index.rb +6 -8
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
- data/lib/rigor/analysis/edit_replay.rb +93 -6
- data/lib/rigor/analysis/fact_store.rb +3 -3
- data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +2 -2
- data/lib/rigor/analysis/incremental_run_slot.rb +2 -2
- data/lib/rigor/analysis/incremental_session.rb +27 -16
- data/lib/rigor/analysis/rule_catalog.rb +2 -2
- data/lib/rigor/analysis/run_stats.rb +2 -2
- data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +2 -2
- data/lib/rigor/analysis/runner/declaration_position.rb +1 -1
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +193 -93
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +1 -1
- data/lib/rigor/analysis/runner/pool_coordinator.rb +147 -323
- data/lib/rigor/analysis/runner/project_pre_passes.rb +3 -3
- data/lib/rigor/analysis/runner/run_level_facts.rb +304 -0
- data/lib/rigor/analysis/runner/run_snapshots.rb +44 -54
- data/lib/rigor/analysis/runner/worker_payload.rb +36 -0
- data/lib/rigor/analysis/runner.rb +77 -71
- data/lib/rigor/analysis/self_call_resolution_recorder.rb +1 -1
- data/lib/rigor/analysis/template_unit_positions.rb +2 -3
- data/lib/rigor/analysis/template_units.rb +9 -1
- data/lib/rigor/analysis/worker_session.rb +24 -31
- data/lib/rigor/bleeding_edge.rb +3 -6
- data/lib/rigor/builtins/imported_refinements.rb +6 -8
- data/lib/rigor/builtins/predefined_constant_refinements.rb +1 -1
- data/lib/rigor/builtins/regex_refinement.rb +4 -6
- data/lib/rigor/cache/descriptor.rb +6 -5
- data/lib/rigor/cache/incremental_snapshot.rb +31 -12
- data/lib/rigor/cache/rbs_cache_producer.rb +2 -2
- data/lib/rigor/cache/rbs_class_ancestor_table.rb +1 -1
- data/lib/rigor/cache/rbs_class_type_param_names.rb +2 -2
- data/lib/rigor/cache/rbs_constant_table.rb +1 -1
- data/lib/rigor/cache/rbs_descriptor.rb +54 -3
- data/lib/rigor/cache/rbs_environment.rb +4 -1
- data/lib/rigor/cache/rbs_environment_marshal_patch.rb +2 -2
- data/lib/rigor/cache/rbs_known_class_names.rb +1 -1
- data/lib/rigor/cache/store.rb +11 -10
- data/lib/rigor/ci_detector.rb +1 -1
- data/lib/rigor/cli/annotate_command.rb +24 -19
- data/lib/rigor/cli/baseline_command.rb +145 -55
- data/lib/rigor/cli/catalogue.rb +256 -0
- data/lib/rigor/cli/check_command.rb +108 -102
- data/lib/rigor/cli/check_runner_factory.rb +2 -2
- data/lib/rigor/cli/command.rb +15 -1
- data/lib/rigor/cli/coverage_command.rb +21 -8
- data/lib/rigor/cli/coverage_mutation.rb +5 -7
- data/lib/rigor/cli/coverage_renderer.rb +2 -1
- data/lib/rigor/cli/coverage_scan.rb +3 -5
- data/lib/rigor/cli/diff_command.rb +25 -20
- data/lib/rigor/cli/docs_command.rb +1 -2
- data/lib/rigor/cli/doctor_command.rb +12 -12
- data/lib/rigor/cli/effects_command.rb +50 -40
- data/lib/rigor/cli/effects_diff_renderer.rb +18 -17
- data/lib/rigor/cli/effects_explain_renderer.rb +13 -12
- data/lib/rigor/cli/effects_renderer.rb +2 -1
- data/lib/rigor/cli/effects_snapshot_command.rb +18 -17
- data/lib/rigor/cli/explain_command.rb +18 -8
- data/lib/rigor/cli/fused_protection_renderer.rb +2 -1
- data/lib/rigor/cli/json_document.rb +41 -0
- data/lib/rigor/cli/lens_command.rb +12 -8
- data/lib/rigor/cli/lsp_command.rb +250 -23
- data/lib/rigor/cli/mcp_command.rb +12 -7
- data/lib/rigor/cli/mutation_fork_scan.rb +1 -1
- data/lib/rigor/cli/mutation_protection_renderer.rb +3 -2
- data/lib/rigor/cli/options.rb +40 -1
- data/lib/rigor/cli/plugin_command.rb +93 -46
- data/lib/rigor/cli/plugins_command.rb +17 -18
- data/lib/rigor/cli/plugins_renderer.rb +10 -6
- data/lib/rigor/cli/protection_fork_scan.rb +2 -2
- data/lib/rigor/cli/protection_renderer.rb +2 -1
- data/lib/rigor/cli/show_bleedingedge_command.rb +21 -15
- data/lib/rigor/cli/sig_gen_command.rb +84 -27
- data/lib/rigor/cli/skill_command.rb +32 -3
- data/lib/rigor/cli/skill_deep_probe.rb +1 -1
- data/lib/rigor/cli/skill_describe.rb +1 -1
- data/lib/rigor/cli/trace_command.rb +14 -9
- data/lib/rigor/cli/triage_command.rb +10 -11
- data/lib/rigor/cli/triage_renderer.rb +2 -1
- data/lib/rigor/cli/type_of_command.rb +16 -11
- data/lib/rigor/cli/type_of_project_scope.rb +1 -4
- data/lib/rigor/cli/type_of_renderer.rb +4 -1
- data/lib/rigor/cli/type_scan_command.rb +14 -9
- data/lib/rigor/cli/type_scan_renderer.rb +2 -1
- data/lib/rigor/cli/unused_command.rb +27 -17
- data/lib/rigor/cli/upgrade_command.rb +5 -0
- data/lib/rigor/cli.rb +209 -54
- data/lib/rigor/config_audit.rb +1 -1
- data/lib/rigor/configuration/severity_profile.rb +5 -5
- data/lib/rigor/configuration.rb +72 -30
- data/lib/rigor/effects/definition_context.rb +0 -2
- data/lib/rigor/effects/envelope.rb +1 -1
- data/lib/rigor/effects/framework_units.rb +1 -1
- data/lib/rigor/effects/mutation_classifier.rb +4 -7
- data/lib/rigor/effects/propagator.rb +1 -1
- data/lib/rigor/effects/registry.rb +2 -2
- data/lib/rigor/effects/snapshot.rb +1 -1
- data/lib/rigor/effects/taint_cause.rb +0 -2
- data/lib/rigor/effects/unit_scan.rb +9 -13
- data/lib/rigor/environment/bundle_sig_discovery.rb +5 -9
- data/lib/rigor/environment/class_registry.rb +3 -3
- data/lib/rigor/environment/core_root.rb +77 -0
- data/lib/rigor/environment/default_libraries.rb +1 -1
- data/lib/rigor/environment/deferred_signature_plan.rb +283 -0
- data/lib/rigor/environment/gated_signature_guard.rb +1 -1
- data/lib/rigor/environment/gated_signature_plan.rb +5 -2
- data/lib/rigor/environment/lockfile_resolver.rb +28 -12
- data/lib/rigor/environment/member_consistency/comparator.rb +18 -1
- data/lib/rigor/environment/member_consistency.rb +56 -7
- data/lib/rigor/environment/missing_gem_constant_index.rb +3 -2
- data/lib/rigor/environment/project_path_gems.rb +124 -0
- data/lib/rigor/environment/rbs_hierarchy.rb +6 -15
- data/lib/rigor/environment/rbs_loader.rb +480 -67
- data/lib/rigor/environment/reflection.rb +7 -7
- data/lib/rigor/environment/required_features.rb +0 -3
- data/lib/rigor/environment/ruby_library_roots.rb +1 -1
- data/lib/rigor/environment/vendored_signature_plan.rb +153 -0
- data/lib/rigor/environment.rb +41 -10
- data/lib/rigor/flow_contribution/merger.rb +4 -4
- data/lib/rigor/inference/acceptance.rb +93 -32
- data/lib/rigor/inference/block_parameter_binder.rb +2 -3
- data/lib/rigor/inference/block_run_count.rb +178 -0
- data/lib/rigor/inference/budget_trace.rb +8 -2
- data/lib/rigor/inference/builtins/exception_catalog.rb +2 -2
- data/lib/rigor/inference/builtins/numeric_catalog.rb +2 -5
- data/lib/rigor/inference/builtins/random_catalog.rb +2 -2
- data/lib/rigor/inference/callee_mutation_chain.rb +88 -77
- data/lib/rigor/inference/callee_write_census.rb +815 -0
- data/lib/rigor/inference/construction_escape.rb +217 -0
- data/lib/rigor/inference/declaration_walk/traversal.rb +1 -1
- data/lib/rigor/inference/deep_erasure.rb +39 -7
- data/lib/rigor/inference/def_handle.rb +1 -1
- data/lib/rigor/inference/def_node_resolver.rb +1 -1
- data/lib/rigor/inference/def_return_typer.rb +46 -4
- data/lib/rigor/inference/definer_resolution.rb +4 -2
- data/lib/rigor/inference/definers_index.rb +106 -0
- data/lib/rigor/inference/direct_ivar_writes.rb +300 -0
- data/lib/rigor/inference/element_read_widening.rb +49 -3
- data/lib/rigor/inference/expression_typer.rb +116 -49
- data/lib/rigor/inference/external_ancestor_resolution.rb +3 -4
- data/lib/rigor/inference/global_write_census.rb +76 -2
- data/lib/rigor/inference/global_writer_reach.rb +260 -0
- data/lib/rigor/inference/hkt_body.rb +1 -2
- data/lib/rigor/inference/hkt_body_parser.rb +3 -5
- data/lib/rigor/inference/hkt_reducer.rb +2 -2
- data/lib/rigor/inference/hkt_registry.rb +3 -5
- data/lib/rigor/inference/indexed_narrowing.rb +4 -7
- data/lib/rigor/inference/intervening_ivar_reset.rb +26 -4
- data/lib/rigor/inference/ivar_writer_census.rb +51 -0
- data/lib/rigor/inference/key_presence_guard.rb +2 -1
- data/lib/rigor/inference/loop_value_record.rb +8 -4
- data/lib/rigor/inference/match_rebinding/frame.rb +46 -0
- data/lib/rigor/inference/match_rebinding/yielding_match.rb +45 -0
- data/lib/rigor/inference/match_rebinding.rb +11 -1
- data/lib/rigor/inference/memo_audit.rb +55 -0
- data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/argument_distribution.rb +40 -0
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +3 -3
- data/lib/rigor/inference/method_dispatcher/contested_overloads.rb +89 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/no_match_fallback.rb +54 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +39 -27
- data/lib/rigor/inference/method_dispatcher/random_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +203 -17
- data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/self_substitute.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/set_folding.rb +9 -7
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +83 -20
- data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +0 -1
- data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +50 -17
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -5
- data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +4 -6
- data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher.rb +64 -14
- data/lib/rigor/inference/module_function_state.rb +11 -1
- data/lib/rigor/inference/multi_target_binder.rb +1 -1
- data/lib/rigor/inference/mutation_rejoin.rb +240 -4
- data/lib/rigor/inference/mutation_widening.rb +157 -27
- data/lib/rigor/inference/narrowing.rb +47 -33
- data/lib/rigor/inference/optimistic_origin.rb +1 -1
- data/lib/rigor/inference/out_buffer_mutation.rb +72 -0
- data/lib/rigor/inference/parameter_inference_collector.rb +5 -6
- data/lib/rigor/inference/pre_eval_constants.rb +1 -1
- data/lib/rigor/inference/project_method_ownership.rb +6 -3
- data/lib/rigor/inference/project_yielder.rb +11 -17
- data/lib/rigor/inference/receiver_alias.rb +20 -0
- data/lib/rigor/inference/refined_dispatch/constructed_class.rb +3 -1
- data/lib/rigor/inference/refined_dispatch/own_method.rb +2 -1
- data/lib/rigor/inference/remover_holder_scan.rb +233 -0
- data/lib/rigor/inference/remover_narrowing.rb +224 -0
- data/lib/rigor/inference/rewrite_mutation.rb +53 -2
- data/lib/rigor/inference/scope_indexer/certainty.rb +0 -1
- data/lib/rigor/inference/scope_indexer/constant_ivar_value.rb +93 -0
- data/lib/rigor/inference/scope_indexer/declared_param_writes.rb +58 -15
- data/lib/rigor/inference/scope_indexer/derived_param_value.rb +112 -0
- data/lib/rigor/inference/scope_indexer/empty_seed.rb +99 -0
- data/lib/rigor/inference/scope_indexer/ivar_contributions.rb +135 -0
- data/lib/rigor/inference/scope_indexer.rb +137 -46
- data/lib/rigor/inference/self_call_ivar_writes.rb +84 -12
- data/lib/rigor/inference/set_mutation.rb +189 -0
- data/lib/rigor/inference/singleton_hook_decline.rb +1 -2
- data/lib/rigor/inference/statement_evaluator.rb +2328 -138
- data/lib/rigor/inference/struct_fold_safety.rb +4 -6
- data/lib/rigor/inference/synthetic_method_scanner.rb +5 -6
- data/lib/rigor/inference/toplevel_def_census.rb +59 -0
- data/lib/rigor/inference/unknown_store_widening.rb +103 -4
- data/lib/rigor/inference/unthreaded_rebinds.rb +2 -3
- data/lib/rigor/inference/void_tail_summary.rb +2 -1
- data/lib/rigor/language_server/buffer_table.rb +3 -3
- data/lib/rigor/language_server/completion_provider.rb +26 -20
- data/lib/rigor/language_server/config_warning_announcer.rb +28 -0
- data/lib/rigor/language_server/diagnostic_publisher.rb +8 -3
- data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
- data/lib/rigor/language_server/folding_range_provider.rb +1 -2
- data/lib/rigor/language_server/hover_provider.rb +1 -7
- data/lib/rigor/language_server/hover_renderer.rb +6 -8
- data/lib/rigor/language_server/project_context.rb +39 -1
- data/lib/rigor/language_server/publish_batcher.rb +3 -4
- data/lib/rigor/language_server/selection_range_provider.rb +2 -4
- data/lib/rigor/language_server/server.rb +7 -3
- data/lib/rigor/language_server/signature_help_provider.rb +4 -4
- data/lib/rigor/lens/plugins.rb +1 -1
- data/lib/rigor/mcp/server.rb +73 -2
- data/lib/rigor/mcp.rb +1 -1
- data/lib/rigor/plugin/access_denied_error.rb +1 -2
- data/lib/rigor/plugin/bundled_catalog.rb +1 -12
- data/lib/rigor/plugin/io_boundary.rb +1 -1
- data/lib/rigor/plugin/loader.rb +25 -8
- data/lib/rigor/plugin/macro/heredoc_template.rb +7 -8
- data/lib/rigor/plugin/macro/trait_registry.rb +6 -9
- data/lib/rigor/plugin/manifest.rb +9 -13
- data/lib/rigor/plugin/registry.rb +3 -3
- data/lib/rigor/plugin/services.rb +2 -3
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -0
- data/lib/rigor/plugin/trust_policy.rb +2 -2
- data/lib/rigor/plugin/type_node_resolver.rb +2 -4
- data/lib/rigor/plugin.rb +6 -8
- data/lib/rigor/plugin_gap_advisory.rb +5 -1
- data/lib/rigor/project_environment.rb +16 -2
- data/lib/rigor/protection/analysis_guard.rb +1 -1
- data/lib/rigor/protection/discovery_seed.rb +44 -5
- data/lib/rigor/protection/mutator.rb +1 -1
- data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
- data/lib/rigor/rbs_extended/hkt_directives.rb +6 -10
- data/lib/rigor/rbs_extended/reporter.rb +27 -3
- data/lib/rigor/rbs_extended.rb +2 -3
- data/lib/rigor/reflection/constant_ancestors.rb +5 -3
- data/lib/rigor/rooted_glob.rb +15 -1
- data/lib/rigor/run_scoped_slots.rb +38 -0
- data/lib/rigor/runtime/jit.rb +1 -1
- data/lib/rigor/scope/discovery_index.rb +19 -6
- data/lib/rigor/scope/resolution_chain.rb +3 -1
- data/lib/rigor/scope.rb +365 -31
- data/lib/rigor/sig_gen/classification.rb +4 -0
- data/lib/rigor/sig_gen/effect_annotation.rb +3 -3
- data/lib/rigor/sig_gen/generator.rb +371 -58
- data/lib/rigor/sig_gen/generic_header_scan.rb +189 -0
- data/lib/rigor/sig_gen/inline_declarations.rb +2 -2
- data/lib/rigor/sig_gen/layout_index.rb +3 -3
- data/lib/rigor/sig_gen/method_candidate.rb +23 -4
- data/lib/rigor/sig_gen/observation_collector.rb +3 -5
- data/lib/rigor/sig_gen/observed_call.rb +1 -1
- data/lib/rigor/sig_gen/path_mapper.rb +6 -0
- data/lib/rigor/sig_gen/renderer.rb +15 -9
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +15 -2
- data/lib/rigor/sig_gen/type_name_qualification.rb +69 -0
- data/lib/rigor/sig_gen/write_reporter.rb +63 -14
- data/lib/rigor/sig_gen/write_result.rb +23 -12
- data/lib/rigor/sig_gen/writer.rb +217 -37
- data/lib/rigor/type/acceptance_router.rb +2 -2
- data/lib/rigor/type/accepts_result.rb +1 -1
- data/lib/rigor/type/app.rb +4 -6
- data/lib/rigor/type/combinator.rb +9 -13
- data/lib/rigor/type/constant.rb +4 -5
- data/lib/rigor/type/hash_shape.rb +21 -40
- data/lib/rigor/type/union.rb +1 -1
- data/lib/rigor/type_node/identifier.rb +1 -2
- data/lib/rigor/type_node/resolver_chain.rb +1 -1
- data/lib/rigor/type_node/string_literal.rb +1 -2
- data/lib/rigor/type_node/symbol_literal.rb +1 -2
- data/lib/rigor/type_node/union.rb +3 -6
- data/lib/rigor/value_semantics.rb +1 -10
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +2 -2
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +2 -3
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +1 -1
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +38 -36
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +4 -2
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +6 -4
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +1 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -5
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +0 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +2 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +1 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +66 -19
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +4 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/association_roots.rb +3 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +2 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +21 -31
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +10 -16
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +2 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +0 -1
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +5 -4
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +3 -4
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +1 -1
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +7 -12
- data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +1 -1
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +1 -1
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/symbolize_keys.rb +102 -0
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +19 -6
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +26 -13
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_index.rb +3 -3
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +1 -3
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +6 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +5 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +1 -1
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/params_shape.rb +2 -3
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +5 -8
- data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +0 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +1 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +10 -18
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/analyzer.rb +0 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/discoverer.rb +0 -2
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +4 -5
- data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +0 -2
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +6 -7
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +2 -4
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +2 -5
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +2 -2
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +6 -6
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +2 -1
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +3 -8
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +2 -3
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +5 -8
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +1 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +2 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +1 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +4 -11
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +1 -1
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +2 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +1 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +2 -2
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +3 -4
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +6 -8
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +3 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +4 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +6 -7
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +1 -1
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +2 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +17 -21
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +2 -3
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_discoverer.rb +3 -2
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_index.rb +4 -4
- data/sig/rigor/analysis/baseline.rbs +0 -3
- data/sig/rigor/analysis/fact_store.rbs +1 -0
- data/sig/rigor/analysis/reachability/scan_cache.rbs +1 -1
- data/sig/rigor/cli/diff_command.rbs +1 -1
- data/sig/rigor/cli/explain_command.rbs +1 -1
- data/sig/rigor/effects/registry.rbs +2 -2
- data/sig/rigor/inference.rbs +4 -1
- data/sig/rigor/plugin/additional_initializer.rbs +0 -5
- data/sig/rigor/plugin/base.rbs +1 -0
- data/sig/rigor/plugin/effect_attribution.rbs +3 -3
- data/sig/rigor/plugin/effect_edge.rbs +1 -1
- data/sig/rigor/plugin/effect_entry_points.rbs +3 -3
- data/sig/rigor/plugin/io_boundary.rbs +2 -1
- data/sig/rigor/plugin/manifest.rbs +9 -9
- data/sig/rigor/plugin/protocol_contract.rbs +3 -7
- data/sig/rigor/scope.rbs +23 -3
- data/skills/rigor-plugin-author/SKILL.md +4 -4
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +5 -5
- data/skills/rigor-plugin-review/SKILL.md +3 -3
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +12 -1
- metadata +36 -3
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "did_you_mean"
|
|
3
4
|
require "optionparser"
|
|
4
5
|
|
|
5
6
|
require_relative "../configuration"
|
|
@@ -50,6 +51,38 @@ module Rigor
|
|
|
50
51
|
run_report
|
|
51
52
|
end
|
|
52
53
|
|
|
54
|
+
# The parser this command parses with, built without parsing anything: the catalogue reads the
|
|
55
|
+
# flags and formats from it (ADR-126 WD3). `options` is only written by the switches' blocks.
|
|
56
|
+
def option_parser(options = {})
|
|
57
|
+
OptionParser.new do |opts|
|
|
58
|
+
opts.banner = USAGE
|
|
59
|
+
Options.add_config(opts, options)
|
|
60
|
+
Options.add_format(opts, options, "Output format: text (default) or json")
|
|
61
|
+
opts.on("--full", "List every method, including the ones with nothing to say") do
|
|
62
|
+
options[:full] = true
|
|
63
|
+
end
|
|
64
|
+
opts.on("--label=LABEL", "Only methods carrying LABEL (or a label under it), in either lane") do |value|
|
|
65
|
+
options[:label].concat(value.split(",").map(&:strip).reject(&:empty?))
|
|
66
|
+
end
|
|
67
|
+
opts.on("--pure", "Only methods proven to do nothing beyond mutate.local — the %a{pure} set") do
|
|
68
|
+
options[:pure] = true
|
|
69
|
+
end
|
|
70
|
+
opts.on("--limit=N", Integer, "Print at most N methods") { |value| options[:limit] = value }
|
|
71
|
+
opts.on("--why", "Expand each method's unresolved reasons and declared-lane sources") do
|
|
72
|
+
options[:why] = true
|
|
73
|
+
end
|
|
74
|
+
opts.on("--list-labels", "Print the effect vocabulary this project can name, and exit") do
|
|
75
|
+
options[:list_labels] = true
|
|
76
|
+
end
|
|
77
|
+
# Accepted here and deliberately inert, exactly as it is on `update`: the report is an
|
|
78
|
+
# observation, and observations are undischarged. Only a JUDGMENT reads `effects.tolerated:` —
|
|
79
|
+
# `rigor effects check` / `diff`, and `rigor check`'s envelope contract.
|
|
80
|
+
opts.on("--no-tolerated-effects", "Judge as if effects.tolerated: were empty (inert on the report)") do
|
|
81
|
+
options[:no_tolerated] = true
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
53
86
|
private
|
|
54
87
|
|
|
55
88
|
def run_verb(verb)
|
|
@@ -91,7 +124,7 @@ module Rigor
|
|
|
91
124
|
|
|
92
125
|
def run_report
|
|
93
126
|
options = parse_options
|
|
94
|
-
return
|
|
127
|
+
return CLI::EXIT_USAGE if misspelled_verb?
|
|
95
128
|
|
|
96
129
|
configuration = Configuration.load(options.fetch(:config)).with_effects_enabled
|
|
97
130
|
return list_labels(configuration) if options.fetch(:list_labels)
|
|
@@ -107,6 +140,20 @@ module Rigor
|
|
|
107
140
|
0
|
|
108
141
|
end
|
|
109
142
|
|
|
143
|
+
# A first word that is no path but is one edit from a snapshot verb (`rigor effects updat`) is a misspelled verb,
|
|
144
|
+
# not a scope: the report would otherwise run to completion and say only that no unit lives in `updat`.
|
|
145
|
+
def misspelled_verb?
|
|
146
|
+
word = @argv.first
|
|
147
|
+
return false if word.nil? || word.match?(%r{[/.]}) || File.exist?(word)
|
|
148
|
+
|
|
149
|
+
nearest = ::DidYouMean::SpellChecker.new(dictionary: EffectsSnapshotCommand::VERBS).correct(word).first
|
|
150
|
+
return false unless nearest
|
|
151
|
+
|
|
152
|
+
@err.puts("rigor: unknown effects subcommand: #{word}")
|
|
153
|
+
@err.puts("Did you mean `rigor effects #{nearest}`?")
|
|
154
|
+
true
|
|
155
|
+
end
|
|
156
|
+
|
|
110
157
|
# A path argument is a **view**, and the note says so (#439).
|
|
111
158
|
#
|
|
112
159
|
# It used to narrow the analysed set, and effect labels are transitive over whatever was analysed —
|
|
@@ -131,48 +178,13 @@ module Rigor
|
|
|
131
178
|
"label is the one the whole-project run reports")
|
|
132
179
|
end
|
|
133
180
|
|
|
134
|
-
FORMATS = %w[text json].freeze
|
|
135
|
-
private_constant :FORMATS
|
|
136
|
-
|
|
137
181
|
def parse_options
|
|
138
182
|
options = { config: nil, format: "text", full: false, no_tolerated: false, label: [], pure: false,
|
|
139
183
|
limit: nil, why: false, list_labels: false }
|
|
140
|
-
|
|
141
|
-
opts.banner = USAGE
|
|
142
|
-
Options.add_config(opts, options)
|
|
143
|
-
opts.on("--format=FORMAT", "Output format: text (default) or json") { |value| options[:format] = value }
|
|
144
|
-
opts.on("--full", "List every method, including the ones with nothing to say") do
|
|
145
|
-
options[:full] = true
|
|
146
|
-
end
|
|
147
|
-
opts.on("--label=LABEL", "Only methods carrying LABEL (or a label under it), in either lane") do |value|
|
|
148
|
-
options[:label].concat(value.split(",").map(&:strip).reject(&:empty?))
|
|
149
|
-
end
|
|
150
|
-
opts.on("--pure", "Only methods proven to do nothing beyond mutate.local — the %a{pure} set") do
|
|
151
|
-
options[:pure] = true
|
|
152
|
-
end
|
|
153
|
-
opts.on("--limit=N", Integer, "Print at most N methods") { |value| options[:limit] = value }
|
|
154
|
-
opts.on("--why", "Expand each method's unresolved reasons and declared-lane sources") do
|
|
155
|
-
options[:why] = true
|
|
156
|
-
end
|
|
157
|
-
opts.on("--list-labels", "Print the effect vocabulary this project can name, and exit") do
|
|
158
|
-
options[:list_labels] = true
|
|
159
|
-
end
|
|
160
|
-
# Accepted here and deliberately inert, exactly as it is on `update`: the report is an
|
|
161
|
-
# observation, and observations are undischarged. Only a JUDGMENT reads `effects.tolerated:` —
|
|
162
|
-
# `rigor effects check` / `diff`, and `rigor check`'s envelope contract.
|
|
163
|
-
opts.on("--no-tolerated-effects", "Judge as if effects.tolerated: were empty (inert on the report)") do
|
|
164
|
-
options[:no_tolerated] = true
|
|
165
|
-
end
|
|
166
|
-
end.parse!(@argv)
|
|
184
|
+
option_parser(options).parse!(@argv)
|
|
167
185
|
options
|
|
168
186
|
end
|
|
169
187
|
|
|
170
|
-
def usage_error(message)
|
|
171
|
-
@err.puts(message)
|
|
172
|
-
@err.puts(USAGE)
|
|
173
|
-
CLI::EXIT_USAGE
|
|
174
|
-
end
|
|
175
|
-
|
|
176
188
|
# Sequential and cache-backed, through the same ADR-45 whole-run result cache `rigor check` uses:
|
|
177
189
|
# the diagnostics entry serves the run and the #382 effects sidecar serves the collections, leaving
|
|
178
190
|
# only the fixpoint. Sequential is not a cache decision — the run-result cache declines pool mode —
|
|
@@ -222,9 +234,7 @@ module Rigor
|
|
|
222
234
|
|
|
223
235
|
# The analysed set is the configured `paths:` **plus** whatever the arguments name — never the
|
|
224
236
|
# arguments alone (#439). An effect summary is transitive over whatever was analysed, so analysing
|
|
225
|
-
# less does not filter the report, it lowers every answer in it
|
|
226
|
-
# app/controllers/issues_controller.rb` used to report `IssuesController#create: [] …?` where the
|
|
227
|
-
# whole-project run reported four labels and a declared lane, with nothing marking the difference.
|
|
237
|
+
# less does not filter the report, it lowers every answer in it.
|
|
228
238
|
#
|
|
229
239
|
# The union rather than the configured paths alone, so that pointing the command at a tree the
|
|
230
240
|
# configuration does not cover — which is what every `rigor effects PATH` invocation from outside a
|
|
@@ -6,6 +6,7 @@ require_relative "../effects/definition_lines"
|
|
|
6
6
|
require_relative "../effects/snapshot"
|
|
7
7
|
require_relative "../effects/snapshot_diff"
|
|
8
8
|
require_relative "renderable"
|
|
9
|
+
require_relative "json_document"
|
|
9
10
|
|
|
10
11
|
module Rigor
|
|
11
12
|
class CLI
|
|
@@ -121,7 +122,7 @@ module Rigor
|
|
|
121
122
|
# method that no longer exists was not defined by it. Such a row renders exactly as it did before
|
|
122
123
|
# this suffix existed.
|
|
123
124
|
#
|
|
124
|
-
# @return
|
|
125
|
+
# @return a relative path and line per file, the line nil when that
|
|
125
126
|
# file spells the key with no `def` — an accessor, or a definition the nesting cannot name.
|
|
126
127
|
def sources_of(symbol)
|
|
127
128
|
Array(@sources[symbol]).map do |path|
|
|
@@ -175,22 +176,22 @@ module Rigor
|
|
|
175
176
|
end
|
|
176
177
|
|
|
177
178
|
def render_json(diff)
|
|
178
|
-
@out.puts(JSON.pretty_generate(
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
179
|
+
@out.puts(JSON.pretty_generate(JsonDocument.stamp({
|
|
180
|
+
"fresh" => diff.fresh?,
|
|
181
|
+
"events" => diff.events.map { |event| event_json(event) },
|
|
182
|
+
"footer" => {
|
|
183
|
+
"added_symbols" => diff.footer[:added_symbols],
|
|
184
|
+
"removed_symbols" => diff.footer[:removed_symbols],
|
|
185
|
+
"suppressed" => diff.footer[:suppressed]
|
|
186
|
+
},
|
|
187
|
+
"regeneration" => diff.regeneration?,
|
|
188
|
+
"header" => {
|
|
189
|
+
"snapshot" => @path,
|
|
190
|
+
"gate" => diff.gate.to_s,
|
|
191
|
+
"recorded" => diff.recorded&.header,
|
|
192
|
+
"current" => diff.current.header
|
|
193
|
+
}
|
|
194
|
+
})))
|
|
194
195
|
end
|
|
195
196
|
end
|
|
196
197
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "json"
|
|
4
4
|
|
|
5
5
|
require_relative "renderable"
|
|
6
|
+
require_relative "json_document"
|
|
6
7
|
|
|
7
8
|
module Rigor
|
|
8
9
|
class CLI
|
|
@@ -53,18 +54,18 @@ module Rigor
|
|
|
53
54
|
end
|
|
54
55
|
|
|
55
56
|
def render_json(rows)
|
|
56
|
-
@out.puts(JSON.pretty_generate(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
57
|
+
@out.puts(JSON.pretty_generate(JsonDocument.stamp({
|
|
58
|
+
"paths" => rows.map do |row|
|
|
59
|
+
{
|
|
60
|
+
"table" => row.table,
|
|
61
|
+
"symbol" => row.symbol,
|
|
62
|
+
"label" => row.label,
|
|
63
|
+
"path" => row.path,
|
|
64
|
+
"origin" => row.origin,
|
|
65
|
+
"causes" => row.causes
|
|
66
|
+
}
|
|
67
|
+
end
|
|
68
|
+
})))
|
|
68
69
|
end
|
|
69
70
|
end
|
|
70
71
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "json"
|
|
4
4
|
|
|
5
5
|
require_relative "renderable"
|
|
6
|
+
require_relative "json_document"
|
|
6
7
|
|
|
7
8
|
module Rigor
|
|
8
9
|
class CLI
|
|
@@ -85,7 +86,7 @@ module Rigor
|
|
|
85
86
|
end
|
|
86
87
|
}
|
|
87
88
|
payload["totals"] = report.totals.to_h.transform_keys(&:to_s) if report.totals
|
|
88
|
-
@out.puts(JSON.pretty_generate(payload))
|
|
89
|
+
@out.puts(JSON.pretty_generate(JsonDocument.stamp(payload)))
|
|
89
90
|
end
|
|
90
91
|
end
|
|
91
92
|
end
|
|
@@ -38,9 +38,6 @@ module Rigor
|
|
|
38
38
|
class EffectsSnapshotCommand < Command
|
|
39
39
|
VERBS = %w[update check diff explain].freeze
|
|
40
40
|
|
|
41
|
-
FORMATS = %w[text json].freeze
|
|
42
|
-
private_constant :FORMATS
|
|
43
|
-
|
|
44
41
|
# The verbs that read a committed record, and so accept `--baseline PATH` —
|
|
45
42
|
# `--baseline <(git show origin/main:.rigor-effects.yml)` is the bot form.
|
|
46
43
|
COMPARING_VERBS = %w[check diff explain].freeze
|
|
@@ -54,8 +51,6 @@ module Rigor
|
|
|
54
51
|
# @return 0 fresh / written, 1 on drift under `check`, 64 on a usage error.
|
|
55
52
|
def run
|
|
56
53
|
options = parse_options
|
|
57
|
-
return usage_error("unsupported format: #{options.fetch(:format)}") unless
|
|
58
|
-
FORMATS.include?(options[:format])
|
|
59
54
|
return usage_error("rigor effects #{@verb} takes no paths; it records the configured paths:") unless
|
|
60
55
|
@argv.empty?
|
|
61
56
|
|
|
@@ -64,6 +59,22 @@ module Rigor
|
|
|
64
59
|
usage_error(e.message)
|
|
65
60
|
end
|
|
66
61
|
|
|
62
|
+
# The parser this command parses with, built without parsing anything: the catalogue reads the
|
|
63
|
+
# flags and formats from it (ADR-126 WD3). `options` is only written by the switches' blocks.
|
|
64
|
+
def option_parser(options = {})
|
|
65
|
+
OptionParser.new do |opts|
|
|
66
|
+
opts.banner = "Usage: rigor effects #{@verb} [options]"
|
|
67
|
+
Options.add_config(opts, options)
|
|
68
|
+
add_common_options(opts, options)
|
|
69
|
+
add_comparison_options(opts, options) if COMPARING_VERBS.include?(@verb)
|
|
70
|
+
if @verb == "explain"
|
|
71
|
+
opts.on("--symbol=KEY", "Explain this unit instead of the changed ones") do |value|
|
|
72
|
+
options[:symbol] = value
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
67
78
|
private
|
|
68
79
|
|
|
69
80
|
def execute(options)
|
|
@@ -273,17 +284,7 @@ module Rigor
|
|
|
273
284
|
def parse_options
|
|
274
285
|
options = { config: nil, format: "text", full: false, baseline: nil, symbol: nil,
|
|
275
286
|
strict_tolerated: false, no_tolerated: false }
|
|
276
|
-
|
|
277
|
-
opts.banner = "Usage: rigor effects #{@verb} [options]"
|
|
278
|
-
Options.add_config(opts, options)
|
|
279
|
-
add_common_options(opts, options)
|
|
280
|
-
add_comparison_options(opts, options) if COMPARING_VERBS.include?(@verb)
|
|
281
|
-
if @verb == "explain"
|
|
282
|
-
opts.on("--symbol=KEY", "Explain this unit instead of the changed ones") do |value|
|
|
283
|
-
options[:symbol] = value
|
|
284
|
-
end
|
|
285
|
-
end
|
|
286
|
-
end.parse!(@argv)
|
|
287
|
+
option_parser(options).parse!(@argv)
|
|
287
288
|
options
|
|
288
289
|
end
|
|
289
290
|
|
|
@@ -292,7 +293,7 @@ module Rigor
|
|
|
292
293
|
# byte-identical files. A flag that changed the record would make the file a function of policy and
|
|
293
294
|
# a policy change indistinguishable from a code change.
|
|
294
295
|
def add_common_options(opts, options)
|
|
295
|
-
|
|
296
|
+
Options.add_format(opts, options, "Output format: text (default) or json")
|
|
296
297
|
opts.on("--full", "Record every method, including the omitted trivial and synthesised ones") do
|
|
297
298
|
options[:full] = true
|
|
298
299
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
|
+
require_relative "json_document"
|
|
4
5
|
require "optionparser"
|
|
5
6
|
|
|
6
7
|
require_relative "../analysis/rule_catalog"
|
|
@@ -46,22 +47,28 @@ module Rigor
|
|
|
46
47
|
0
|
|
47
48
|
end
|
|
48
49
|
|
|
50
|
+
# The parser this command parses with, built without parsing anything: the catalogue reads the
|
|
51
|
+
# flags and formats from it (ADR-126 WD3). `options` is only written by the switches' blocks.
|
|
52
|
+
def option_parser(options = {})
|
|
53
|
+
OptionParser.new do |opt|
|
|
54
|
+
opt.banner = USAGE
|
|
55
|
+
Options.add_format(opt, options, "Output format (text | json). Default: text.")
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
49
59
|
private
|
|
50
60
|
|
|
51
61
|
def parse_options
|
|
52
62
|
options = { format: "text" }
|
|
53
|
-
|
|
54
|
-
opt.banner = USAGE
|
|
55
|
-
opt.on("--format=FORMAT", %w[text json], "Output format (text | json). Default: text.") do |fmt|
|
|
56
|
-
options[:format] = fmt
|
|
57
|
-
end
|
|
58
|
-
end.parse!(@argv)
|
|
63
|
+
option_parser(options).parse!(@argv)
|
|
59
64
|
options
|
|
60
65
|
end
|
|
61
66
|
|
|
62
67
|
def render_index(format)
|
|
63
68
|
case format
|
|
64
|
-
when "json"
|
|
69
|
+
when "json"
|
|
70
|
+
@out.puts(JSON.pretty_generate(Analysis::RuleCatalog.all.map(&:to_h)))
|
|
71
|
+
@err.puts(JsonDocument::SHAPE_NOTICES.fetch(:explain_rules))
|
|
65
72
|
else render_index_text
|
|
66
73
|
end
|
|
67
74
|
end
|
|
@@ -87,6 +94,7 @@ module Rigor
|
|
|
87
94
|
def render_skip_reason(entry, format)
|
|
88
95
|
if format == "json"
|
|
89
96
|
@out.puts(JSON.pretty_generate(entry.to_h))
|
|
97
|
+
@err.puts(JsonDocument::SHAPE_NOTICES.fetch(:explain_skip_reasons))
|
|
90
98
|
return
|
|
91
99
|
end
|
|
92
100
|
|
|
@@ -106,7 +114,9 @@ module Rigor
|
|
|
106
114
|
|
|
107
115
|
def render_entries(entries, format)
|
|
108
116
|
case format
|
|
109
|
-
when "json"
|
|
117
|
+
when "json"
|
|
118
|
+
@out.puts(JSON.pretty_generate(entries.map(&:to_h)))
|
|
119
|
+
@err.puts(JsonDocument::SHAPE_NOTICES.fetch(:explain_rules))
|
|
110
120
|
else
|
|
111
121
|
entries.each_with_index do |entry, index|
|
|
112
122
|
@out.puts("") if index.positive?
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
|
+
require_relative "json_document"
|
|
4
5
|
|
|
5
6
|
module Rigor
|
|
6
7
|
class CLI
|
|
@@ -23,7 +24,7 @@ module Rigor
|
|
|
23
24
|
private
|
|
24
25
|
|
|
25
26
|
def render_json(report)
|
|
26
|
-
@out.puts(JSON.pretty_generate(report.to_h))
|
|
27
|
+
@out.puts(JSON.pretty_generate(JsonDocument.stamp(report.to_h)))
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def render_text(report)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rigor
|
|
4
|
+
class CLI
|
|
5
|
+
# The version marker every `--format=json` document Rigor defines carries (ADR-126 WD2, ADR-50 WD1).
|
|
6
|
+
#
|
|
7
|
+
# `schema_version` is the first top-level key and counts per document (per `mode` where a flag selects a
|
|
8
|
+
# different document). Adding a key keeps the version; removing or renaming one is a major-only change at
|
|
9
|
+
# v1.0.0. `lens` (`schema`/`revision`), `baseline dump` (`version`) and `check`'s external formats keep
|
|
10
|
+
# their own markers and do not pass through here.
|
|
11
|
+
module JsonDocument
|
|
12
|
+
SCHEMA_VERSION = 1
|
|
13
|
+
|
|
14
|
+
# @param payload — the document's top-level object (string or symbol keys).
|
|
15
|
+
# @param mode — names the document when a flag selects among several; nil when the command has one.
|
|
16
|
+
# @return a new Hash whose first key is `schema_version` (then `mode`, when given).
|
|
17
|
+
def self.stamp(payload, mode: nil)
|
|
18
|
+
head = { "schema_version" => SCHEMA_VERSION }
|
|
19
|
+
head["mode"] = mode if mode
|
|
20
|
+
head.merge(payload)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# The one-line stderr notice for `type-of`, `explain` and `trace`, whose top-level JSON shape changes in
|
|
24
|
+
# the next minor (ADR-126 WD4). stdout stays byte-identical until then. The MCP server appends the same
|
|
25
|
+
# text as its own content block, recognised by {NOTICE_PATTERN}.
|
|
26
|
+
def self.shape_notice(command, replacement)
|
|
27
|
+
"rigor: note — `rigor #{command} --format=json` will print #{replacement} from the next minor " \
|
|
28
|
+
"release (currently a different top-level shape); update JSON consumers now. See ADR-126."
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
NOTICE_PATTERN = /^rigor: note — `rigor [a-z-]+ --format=json` will print .*$/
|
|
32
|
+
|
|
33
|
+
SHAPE_NOTICES = {
|
|
34
|
+
type_of: shape_notice("type-of", '{ "schema_version": 1, "results": [...] }').freeze,
|
|
35
|
+
trace: shape_notice("trace", '{ "schema_version": 1, "events": [...] }').freeze,
|
|
36
|
+
explain_rules: shape_notice("explain", '{ "schema_version": 1, "rules": [...] }').freeze,
|
|
37
|
+
explain_skip_reasons: shape_notice("explain", '{ "schema_version": 1, "skip_reasons": [...] }').freeze
|
|
38
|
+
}.freeze
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -15,7 +15,6 @@ module Rigor
|
|
|
15
15
|
# computes them (ADR-113; output contract docs/internal-spec/lens.md). Experimental until `lens/v1`.
|
|
16
16
|
class LensCommand < Command
|
|
17
17
|
USAGE = "Usage: rigor lens [--format=text|json] [--config=PATH] [--workers=N] FILE..."
|
|
18
|
-
FORMATS = %w[text json].freeze
|
|
19
18
|
|
|
20
19
|
def run
|
|
21
20
|
options = parse_options
|
|
@@ -35,17 +34,22 @@ module Rigor
|
|
|
35
34
|
outcome.targets.any? { |target| target.status == "ok" } ? 0 : 1
|
|
36
35
|
end
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def
|
|
41
|
-
options = { format: "text", config: nil, workers: nil }
|
|
37
|
+
# The parser this command parses with, built without parsing anything: the catalogue reads the
|
|
38
|
+
# flags and formats from it (ADR-126 WD3). `options` is only written by the switches' blocks.
|
|
39
|
+
def option_parser(options = {})
|
|
42
40
|
OptionParser.new do |opts|
|
|
43
41
|
opts.banner = USAGE
|
|
44
|
-
|
|
42
|
+
Options.add_format(opts, options, "Output format: text (default) or json")
|
|
45
43
|
opts.on("--workers=N", Integer, "Worker processes for a cold run") { |value| options[:workers] = value }
|
|
46
44
|
Options.add_config(opts, options)
|
|
47
|
-
end
|
|
48
|
-
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def parse_options
|
|
51
|
+
options = { format: "text", config: nil, workers: nil }
|
|
52
|
+
option_parser(options).parse!(@argv)
|
|
49
53
|
return usage_error("no FILE given") if @argv.empty?
|
|
50
54
|
|
|
51
55
|
options
|