rigortype 0.2.7 → 0.2.8
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/docs/manual/04-diagnostics.md +7 -4
- data/docs/manual/06-baseline.md +5 -2
- data/docs/manual/15-type-protection-coverage.md +6 -4
- data/lib/rigor/analysis/baseline.rb +56 -96
- data/lib/rigor/analysis/buffer_binding.rb +13 -20
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +29 -48
- data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +35 -54
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +23 -37
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +16 -23
- data/lib/rigor/analysis/check_rules/rule_walk.rb +48 -71
- data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +19 -28
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +48 -67
- data/lib/rigor/analysis/check_rules.rb +174 -274
- data/lib/rigor/analysis/dependency_recorder.rb +26 -38
- data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +13 -25
- data/lib/rigor/analysis/dependency_source_inference/builder.rb +17 -30
- data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +15 -26
- data/lib/rigor/analysis/dependency_source_inference/index.rb +45 -76
- data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +23 -40
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +50 -83
- data/lib/rigor/analysis/dependency_source_inference.rb +6 -10
- data/lib/rigor/analysis/diagnostic.rb +48 -75
- data/lib/rigor/analysis/erb_template_detector.rb +13 -18
- data/lib/rigor/analysis/fact_store.rb +12 -22
- data/lib/rigor/analysis/incremental.rb +47 -63
- data/lib/rigor/analysis/incremental_session.rb +74 -100
- data/lib/rigor/analysis/project_scan.rb +12 -23
- data/lib/rigor/analysis/result.rb +3 -5
- data/lib/rigor/analysis/rule_catalog.rb +67 -95
- data/lib/rigor/analysis/run_stats.rb +38 -61
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +101 -160
- data/lib/rigor/analysis/runner/pool_coordinator.rb +121 -188
- data/lib/rigor/analysis/runner/project_pre_passes.rb +62 -96
- data/lib/rigor/analysis/runner/run_snapshots.rb +12 -18
- data/lib/rigor/analysis/runner.rb +220 -333
- data/lib/rigor/analysis/self_call_resolution_recorder.rb +30 -43
- data/lib/rigor/analysis/worker_session.rb +64 -102
- data/lib/rigor/ast/type_node.rb +6 -8
- data/lib/rigor/ast.rb +6 -10
- data/lib/rigor/bleeding_edge.rb +27 -35
- data/lib/rigor/builtins/hkt_builtins.rb +7 -14
- data/lib/rigor/builtins/imported_refinements.rb +106 -149
- data/lib/rigor/builtins/predefined_constant_refinements.rb +51 -65
- data/lib/rigor/builtins/regex_refinement.rb +32 -43
- data/lib/rigor/builtins/static_return_refinements.rb +57 -81
- data/lib/rigor/cache/descriptor.rb +58 -94
- data/lib/rigor/cache/incremental_snapshot.rb +32 -48
- data/lib/rigor/cache/rbs_cache_producer.rb +10 -15
- data/lib/rigor/cache/rbs_class_ancestor_table.rb +10 -16
- data/lib/rigor/cache/rbs_class_type_param_names.rb +10 -16
- data/lib/rigor/cache/rbs_constant_table.rb +8 -13
- data/lib/rigor/cache/rbs_descriptor.rb +8 -13
- data/lib/rigor/cache/rbs_environment.rb +11 -19
- data/lib/rigor/cache/rbs_environment_marshal_patch.rb +11 -19
- data/lib/rigor/cache/rbs_known_class_names.rb +8 -12
- data/lib/rigor/cache/store.rb +96 -151
- data/lib/rigor/cli/annotate_command.rb +51 -88
- data/lib/rigor/cli/baseline_command.rb +10 -17
- data/lib/rigor/cli/check_command.rb +121 -199
- data/lib/rigor/cli/check_runner_factory.rb +8 -14
- data/lib/rigor/cli/ci_detector.rb +9 -14
- data/lib/rigor/cli/command.rb +8 -14
- data/lib/rigor/cli/coverage_command.rb +19 -26
- data/lib/rigor/cli/coverage_mutation.rb +14 -19
- data/lib/rigor/cli/coverage_report.rb +0 -2
- data/lib/rigor/cli/coverage_scan.rb +7 -11
- data/lib/rigor/cli/diagnostic_formats.rb +43 -62
- data/lib/rigor/cli/diff_command.rb +10 -20
- data/lib/rigor/cli/docs_command.rb +26 -40
- data/lib/rigor/cli/doctor_command.rb +8 -9
- data/lib/rigor/cli/explain_command.rb +4 -7
- data/lib/rigor/cli/fused_protection_renderer.rb +4 -5
- data/lib/rigor/cli/fused_protection_report.rb +6 -8
- data/lib/rigor/cli/lsp_command.rb +11 -19
- data/lib/rigor/cli/mcp_command.rb +4 -6
- data/lib/rigor/cli/mutation_protection_renderer.rb +3 -4
- data/lib/rigor/cli/mutation_protection_report.rb +6 -9
- data/lib/rigor/cli/options.rb +11 -19
- data/lib/rigor/cli/plugin_command.rb +18 -30
- data/lib/rigor/cli/plugins_command.rb +29 -51
- data/lib/rigor/cli/plugins_renderer.rb +12 -20
- data/lib/rigor/cli/prism_colorizer.rb +13 -19
- data/lib/rigor/cli/protection_renderer.rb +5 -7
- data/lib/rigor/cli/protection_report.rb +27 -17
- data/lib/rigor/cli/renderable.rb +4 -6
- data/lib/rigor/cli/show_bleedingedge_command.rb +5 -8
- data/lib/rigor/cli/sig_gen_command.rb +14 -26
- data/lib/rigor/cli/skill_command.rb +30 -47
- data/lib/rigor/cli/skill_describe.rb +40 -64
- data/lib/rigor/cli/trace_command.rb +9 -16
- data/lib/rigor/cli/trace_renderer.rb +35 -51
- data/lib/rigor/cli/triage_command.rb +6 -10
- data/lib/rigor/cli/triage_renderer.rb +1 -2
- data/lib/rigor/cli/type_of_command.rb +14 -23
- data/lib/rigor/cli/type_of_renderer.rb +3 -5
- data/lib/rigor/cli/type_scan_command.rb +6 -10
- data/lib/rigor/cli/type_scan_renderer.rb +3 -5
- data/lib/rigor/cli/type_scan_report.rb +2 -3
- data/lib/rigor/cli/upgrade_command.rb +2 -3
- data/lib/rigor/cli.rb +16 -28
- data/lib/rigor/config_audit.rb +35 -44
- data/lib/rigor/configuration/dependencies.rb +41 -70
- data/lib/rigor/configuration/severity_profile.rb +28 -42
- data/lib/rigor/configuration.rb +150 -241
- data/lib/rigor/environment/bundle_sig_discovery.rb +74 -118
- data/lib/rigor/environment/class_registry.rb +19 -26
- data/lib/rigor/environment/constant_type_cache_holder.rb +14 -21
- data/lib/rigor/environment/hkt_registry_holder.rb +6 -12
- data/lib/rigor/environment/lockfile_resolver.rb +31 -47
- data/lib/rigor/environment/rbs_collection_discovery.rb +39 -63
- data/lib/rigor/environment/rbs_coverage_report.rb +24 -42
- data/lib/rigor/environment/rbs_loader.rb +420 -518
- data/lib/rigor/environment/reflection.rb +28 -53
- data/lib/rigor/environment/reporters.rb +13 -24
- data/lib/rigor/environment.rb +176 -291
- data/lib/rigor/flow_contribution/conflict.rb +16 -27
- data/lib/rigor/flow_contribution/element.rb +7 -12
- data/lib/rigor/flow_contribution/fact.rb +33 -57
- data/lib/rigor/flow_contribution/merge_result.rb +6 -9
- data/lib/rigor/flow_contribution/merger.rb +32 -47
- data/lib/rigor/flow_contribution.rb +37 -55
- data/lib/rigor/inference/acceptance.rb +133 -219
- data/lib/rigor/inference/block_parameter_binder.rb +52 -82
- data/lib/rigor/inference/body_fixpoint.rb +22 -30
- data/lib/rigor/inference/budget_trace.rb +43 -63
- data/lib/rigor/inference/builtins/array_catalog.rb +4 -6
- data/lib/rigor/inference/builtins/comparable_catalog.rb +4 -6
- data/lib/rigor/inference/builtins/complex_catalog.rb +13 -19
- data/lib/rigor/inference/builtins/date_catalog.rb +38 -67
- data/lib/rigor/inference/builtins/encoding_catalog.rb +22 -36
- data/lib/rigor/inference/builtins/enumerable_catalog.rb +4 -6
- data/lib/rigor/inference/builtins/exception_catalog.rb +38 -57
- data/lib/rigor/inference/builtins/hash_catalog.rb +9 -14
- data/lib/rigor/inference/builtins/method_catalog.rb +29 -48
- data/lib/rigor/inference/builtins/numeric_catalog.rb +13 -18
- data/lib/rigor/inference/builtins/pathname_catalog.rb +8 -13
- data/lib/rigor/inference/builtins/proc_catalog.rb +38 -62
- data/lib/rigor/inference/builtins/random_catalog.rb +21 -32
- data/lib/rigor/inference/builtins/range_catalog.rb +12 -21
- data/lib/rigor/inference/builtins/rational_catalog.rb +9 -15
- data/lib/rigor/inference/builtins/re_catalog.rb +29 -48
- data/lib/rigor/inference/builtins/set_catalog.rb +18 -27
- data/lib/rigor/inference/builtins/string_catalog.rb +12 -19
- data/lib/rigor/inference/builtins/struct_catalog.rb +18 -30
- data/lib/rigor/inference/builtins/time_catalog.rb +28 -44
- data/lib/rigor/inference/closure_escape_analyzer.rb +44 -67
- data/lib/rigor/inference/coverage_scanner.rb +13 -18
- data/lib/rigor/inference/def_return_typer.rb +8 -14
- data/lib/rigor/inference/dynamic_origin.rb +23 -20
- data/lib/rigor/inference/expression_typer.rb +774 -1152
- data/lib/rigor/inference/fallback.rb +8 -12
- data/lib/rigor/inference/fallback_tracer.rb +4 -10
- data/lib/rigor/inference/flow_tracer.rb +25 -36
- data/lib/rigor/inference/hkt_body.rb +45 -68
- data/lib/rigor/inference/hkt_body_parser.rb +33 -52
- data/lib/rigor/inference/hkt_reducer.rb +38 -59
- data/lib/rigor/inference/hkt_registry.rb +50 -76
- data/lib/rigor/inference/indexed_narrowing.rb +55 -81
- data/lib/rigor/inference/macro_block_self_type.rb +21 -34
- data/lib/rigor/inference/method_dispatcher/array_to_h_folding.rb +11 -18
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +49 -83
- data/lib/rigor/inference/method_dispatcher/call_context.rb +16 -23
- data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +13 -22
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +307 -454
- data/lib/rigor/inference/method_dispatcher/data_folding.rb +24 -34
- data/lib/rigor/inference/method_dispatcher/file_folding.rb +22 -37
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +52 -81
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +51 -78
- data/lib/rigor/inference/method_dispatcher/literal_string_folding.rb +60 -97
- data/lib/rigor/inference/method_dispatcher/math_folding.rb +23 -34
- data/lib/rigor/inference/method_dispatcher/member_shape_projection.rb +18 -26
- data/lib/rigor/inference/method_dispatcher/method_folding.rb +37 -71
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +114 -182
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +122 -193
- data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +15 -24
- data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +64 -93
- data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +31 -45
- data/lib/rigor/inference/method_dispatcher/set_folding.rb +6 -9
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +356 -511
- data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +22 -32
- data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +15 -21
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +66 -82
- data/lib/rigor/inference/method_dispatcher/time_folding.rb +10 -15
- data/lib/rigor/inference/method_dispatcher/uri_folding.rb +9 -13
- data/lib/rigor/inference/method_dispatcher.rb +378 -524
- data/lib/rigor/inference/method_parameter_binder.rb +81 -114
- data/lib/rigor/inference/multi_target_binder.rb +51 -68
- data/lib/rigor/inference/mutation_widening.rb +115 -158
- data/lib/rigor/inference/narrowing.rb +509 -727
- data/lib/rigor/inference/origin_lookup.rb +38 -0
- data/lib/rigor/inference/parameter_inference_collector.rb +100 -100
- data/lib/rigor/inference/precision_scanner.rb +26 -35
- data/lib/rigor/inference/project_patched_methods.rb +20 -32
- data/lib/rigor/inference/project_patched_scanner.rb +23 -37
- data/lib/rigor/inference/protection_scanner.rb +16 -18
- data/lib/rigor/inference/rbs_type_translator.rb +49 -66
- data/lib/rigor/inference/scope_indexer.rb +473 -817
- data/lib/rigor/inference/statement_evaluator.rb +706 -1111
- data/lib/rigor/inference/struct_fold_safety.rb +34 -48
- data/lib/rigor/inference/synthetic_method.rb +9 -16
- data/lib/rigor/inference/synthetic_method_index.rb +20 -35
- data/lib/rigor/inference/synthetic_method_scanner.rb +63 -103
- data/lib/rigor/language_server/buffer_resolution.rb +6 -9
- data/lib/rigor/language_server/buffer_table.rb +11 -18
- data/lib/rigor/language_server/completion_provider.rb +69 -116
- data/lib/rigor/language_server/debouncer.rb +16 -25
- data/lib/rigor/language_server/diagnostic_publisher.rb +26 -40
- data/lib/rigor/language_server/document_symbol_provider.rb +14 -19
- data/lib/rigor/language_server/folding_range_provider.rb +11 -19
- data/lib/rigor/language_server/hover_provider.rb +8 -11
- data/lib/rigor/language_server/hover_renderer.rb +56 -93
- data/lib/rigor/language_server/loop.rb +14 -19
- data/lib/rigor/language_server/project_context.rb +46 -74
- data/lib/rigor/language_server/selection_range_provider.rb +9 -12
- data/lib/rigor/language_server/server.rb +55 -83
- data/lib/rigor/language_server/signature_help_provider.rb +29 -46
- data/lib/rigor/language_server/synchronized_writer.rb +4 -7
- data/lib/rigor/language_server/uri.rb +8 -13
- data/lib/rigor/language_server.rb +4 -6
- data/lib/rigor/mcp/loop.rb +2 -3
- data/lib/rigor/mcp/server.rb +4 -7
- data/lib/rigor/mcp.rb +3 -6
- data/lib/rigor/plugin/access_denied_error.rb +5 -8
- data/lib/rigor/plugin/additional_initializer.rb +21 -31
- data/lib/rigor/plugin/base.rb +335 -518
- data/lib/rigor/plugin/blueprint.rb +14 -23
- data/lib/rigor/plugin/box.rb +18 -29
- data/lib/rigor/plugin/fact_store.rb +16 -26
- data/lib/rigor/plugin/inflector.rb +37 -53
- data/lib/rigor/plugin/io_boundary.rb +33 -56
- data/lib/rigor/plugin/isolation.rb +42 -55
- data/lib/rigor/plugin/load_error.rb +10 -15
- data/lib/rigor/plugin/loader.rb +30 -49
- data/lib/rigor/plugin/macro/block_as_method.rb +20 -32
- data/lib/rigor/plugin/macro/heredoc_template.rb +35 -58
- data/lib/rigor/plugin/macro/nested_class_template.rb +22 -36
- data/lib/rigor/plugin/macro/trait_registry.rb +34 -51
- data/lib/rigor/plugin/macro.rb +10 -15
- data/lib/rigor/plugin/manifest.rb +85 -144
- data/lib/rigor/plugin/node_context.rb +14 -22
- data/lib/rigor/plugin/node_rule_walk.rb +49 -74
- data/lib/rigor/plugin/protocol_contract.rb +25 -39
- data/lib/rigor/plugin/registry.rb +132 -205
- data/lib/rigor/plugin/services.rb +21 -33
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -19
- data/lib/rigor/plugin/trust_policy.rb +24 -38
- data/lib/rigor/plugin/type_node_resolver.rb +15 -24
- data/lib/rigor/protection/diagnostic_oracle.rb +11 -13
- data/lib/rigor/protection/mutation_scanner.rb +27 -35
- data/lib/rigor/protection/mutator.rb +50 -70
- data/lib/rigor/protection/test_suite_oracle.rb +20 -27
- data/lib/rigor/rbs_extended/conformance_checker.rb +48 -68
- data/lib/rigor/rbs_extended/hkt_directives.rb +28 -54
- data/lib/rigor/rbs_extended/reporter.rb +24 -40
- data/lib/rigor/rbs_extended.rb +107 -197
- data/lib/rigor/reflection.rb +68 -86
- data/lib/rigor/scope/discovery_index.rb +14 -19
- data/lib/rigor/scope.rb +255 -310
- data/lib/rigor/sig_gen/classification.rb +6 -10
- data/lib/rigor/sig_gen/generator.rb +197 -323
- data/lib/rigor/sig_gen/layout_index.rb +12 -20
- data/lib/rigor/sig_gen/method_candidate.rb +12 -17
- data/lib/rigor/sig_gen/observation_collector.rb +38 -70
- data/lib/rigor/sig_gen/observed_call.rb +13 -23
- data/lib/rigor/sig_gen/path_mapper.rb +17 -29
- data/lib/rigor/sig_gen/renderer.rb +7 -13
- data/lib/rigor/sig_gen/type_elaborator.rb +15 -28
- data/lib/rigor/sig_gen/write_result.rb +8 -16
- data/lib/rigor/sig_gen/writer.rb +95 -174
- data/lib/rigor/sig_gen.rb +3 -6
- data/lib/rigor/signature_path_audit.rb +24 -30
- data/lib/rigor/source/constant_path.rb +10 -14
- data/lib/rigor/source/literals.rb +31 -45
- data/lib/rigor/source/node_locator.rb +9 -11
- data/lib/rigor/source/node_walker.rb +9 -13
- data/lib/rigor/source.rb +3 -4
- data/lib/rigor/testing.rb +16 -20
- data/lib/rigor/triage/catalogue.rb +38 -62
- data/lib/rigor/triage.rb +31 -52
- data/lib/rigor/trinary.rb +9 -13
- data/lib/rigor/type/acceptance_router.rb +4 -6
- data/lib/rigor/type/accepts_result.rb +10 -14
- data/lib/rigor/type/app.rb +19 -27
- data/lib/rigor/type/bot.rb +4 -6
- data/lib/rigor/type/bound_method.rb +10 -15
- data/lib/rigor/type/combinator.rb +165 -257
- data/lib/rigor/type/constant.rb +23 -34
- data/lib/rigor/type/data_class.rb +10 -15
- data/lib/rigor/type/data_instance.rb +14 -20
- data/lib/rigor/type/difference.rb +21 -32
- data/lib/rigor/type/dynamic.rb +3 -5
- data/lib/rigor/type/hash_shape.rb +32 -18
- data/lib/rigor/type/integer_range.rb +11 -16
- data/lib/rigor/type/intersection.rb +27 -42
- data/lib/rigor/type/nominal.rb +10 -15
- data/lib/rigor/type/plain_lattice.rb +9 -13
- data/lib/rigor/type/refined.rb +67 -114
- data/lib/rigor/type/singleton.rb +4 -6
- data/lib/rigor/type/struct_class.rb +11 -16
- data/lib/rigor/type/struct_instance.rb +15 -21
- data/lib/rigor/type/tuple.rb +14 -19
- data/lib/rigor/type/union.rb +30 -42
- data/lib/rigor/type_node/generic.rb +14 -26
- data/lib/rigor/type_node/identifier.rb +12 -19
- data/lib/rigor/type_node.rb +3 -12
- data/lib/rigor/value_semantics.rb +16 -21
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +18 -30
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +16 -29
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +12 -23
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +22 -39
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +26 -46
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +51 -87
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +10 -17
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +26 -39
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +118 -176
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +30 -51
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +57 -92
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +71 -108
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +13 -22
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +15 -25
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +8 -13
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +16 -24
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +30 -47
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +79 -129
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +36 -57
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +27 -41
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +16 -24
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +148 -235
- data/plugins/rigor-activerecord/lib/rigor-activerecord.rb +3 -5
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +8 -14
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +9 -15
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +4 -7
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +23 -41
- data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +3 -5
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +6 -10
- data/plugins/rigor-activesupport-core-ext/lib/rigor-activesupport-core-ext.rb +8 -11
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +30 -45
- data/plugins/rigor-devise/lib/rigor-devise.rb +3 -5
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +43 -69
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +26 -35
- data/plugins/rigor-dry-schema/lib/rigor-dry-schema.rb +3 -5
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +30 -47
- data/plugins/rigor-dry-struct/lib/rigor-dry-struct.rb +3 -5
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +67 -113
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +29 -46
- data/plugins/rigor-dry-types/lib/rigor-dry-types.rb +3 -5
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -20
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +14 -23
- data/plugins/rigor-dry-validation/lib/rigor-dry-validation.rb +2 -3
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +22 -37
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +28 -46
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +13 -17
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +30 -47
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +52 -80
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +21 -31
- data/plugins/rigor-graphql/lib/rigor-graphql.rb +3 -5
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +11 -17
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +20 -34
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +45 -75
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +22 -36
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +22 -41
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +17 -32
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +6 -12
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +4 -8
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +17 -32
- data/plugins/rigor-rails/lib/rigor-rails.rb +11 -18
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +58 -92
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +20 -34
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +20 -31
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +49 -82
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +55 -92
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +51 -90
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +17 -30
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +38 -70
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +42 -74
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +280 -497
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +54 -89
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +32 -54
- data/plugins/rigor-rbs-inline/lib/rigor-rbs-inline.rb +8 -13
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +9 -16
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +24 -39
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +13 -22
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +34 -56
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/scope_walker.rb +22 -42
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +43 -75
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +27 -39
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/http_status_codes.rb +14 -19
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +20 -34
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +28 -47
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +21 -37
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +13 -22
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +18 -31
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +6 -10
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +14 -29
- data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +23 -41
- data/plugins/rigor-sinatra/lib/rigor-sinatra.rb +3 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +23 -38
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +57 -96
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +22 -35
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +41 -69
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/method_signature.rb +6 -10
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +24 -41
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +29 -50
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +55 -88
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +159 -262
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +21 -29
- data/plugins/rigor-statesman/lib/rigor-statesman.rb +3 -5
- data/plugins/rigor-typescript-utility-types/lib/rigor/plugin/typescript_utility_types.rb +23 -37
- data/plugins/rigor-typescript-utility-types/lib/rigor-typescript-utility-types.rb +4 -6
- data/sig/rigor/scope.rbs +6 -0
- metadata +2 -1
data/lib/rigor/configuration.rb
CHANGED
|
@@ -10,32 +10,25 @@ module Rigor
|
|
|
10
10
|
class Configuration # rubocop:disable Metrics/ClassLength
|
|
11
11
|
# File-discovery order for `Configuration.load(nil)`.
|
|
12
12
|
#
|
|
13
|
-
# The first file present is loaded; the others are NOT
|
|
14
|
-
#
|
|
15
|
-
# winning file MUST list the base via `includes:`.
|
|
13
|
+
# The first file present is loaded; the others are NOT implicitly merged. To extend a base config
|
|
14
|
+
# explicitly the winning file MUST list the base via `includes:`.
|
|
16
15
|
#
|
|
17
|
-
# `.rigor.yml` is a developer-local override (typically
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
# developer's local override wins outright — there is no
|
|
21
|
-
# implicit auto-merge.
|
|
16
|
+
# `.rigor.yml` is a developer-local override (typically gitignored); `.rigor.dist.yml` is the project
|
|
17
|
+
# default (committed to the repo). When both are present the developer's local override wins outright —
|
|
18
|
+
# there is no implicit auto-merge.
|
|
22
19
|
DISCOVERY_ORDER = %w[.rigor.yml .rigor.dist.yml].freeze
|
|
23
|
-
# Back-compat alias. Keep here so external callers that read
|
|
24
|
-
#
|
|
25
|
-
# still work; the discovery list is the canonical source.
|
|
20
|
+
# Back-compat alias. Keep here so external callers that read `Configuration::DEFAULT_PATH` for help text /
|
|
21
|
+
# fixture paths still work; the discovery list is the canonical source.
|
|
26
22
|
DEFAULT_PATH = DISCOVERY_ORDER.first
|
|
27
23
|
|
|
28
|
-
# Built-in exclusion patterns appended to `exclude:` so vendored
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
# any of these paths is essentially never what the user wants
|
|
33
|
-
# (they're build outputs / external dependencies, not source).
|
|
24
|
+
# Built-in exclusion patterns appended to `exclude:` so vendored dependencies, Bundler artefacts, and
|
|
25
|
+
# JavaScript node_modules are never analysed by accident when a directory glob expands. Users cannot
|
|
26
|
+
# disable these defaults; the trade-off is that analysing any of these paths is essentially never what
|
|
27
|
+
# the user wants (they're build outputs / external dependencies, not source).
|
|
34
28
|
#
|
|
35
|
-
# We deliberately keep this list narrow. `tmp/` and similar
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
# in `.rigor.yml` cover the project-specific cases.
|
|
29
|
+
# We deliberately keep this list narrow. `tmp/` and similar directories vary across project layouts
|
|
30
|
+
# (Rails has `tmp/`, libraries usually don't); user-supplied `exclude:` entries in `.rigor.yml` cover the
|
|
31
|
+
# project-specific cases.
|
|
39
32
|
BUILTIN_EXCLUDES = %w[
|
|
40
33
|
**/vendor/bundle/**
|
|
41
34
|
**/.bundle/**
|
|
@@ -50,35 +43,26 @@ module Rigor
|
|
|
50
43
|
"disable" => [],
|
|
51
44
|
"libraries" => [],
|
|
52
45
|
"signature_paths" => nil,
|
|
53
|
-
# ADR-17 — project-side monkey-patch pre-evaluation.
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
# plumbing only — listed files are validated at config-load
|
|
59
|
-
# time (`pre-eval.file-not-found` on a missing path), but
|
|
60
|
-
# the dispatcher tier consuming the registry lands in
|
|
61
|
-
# slice 2.
|
|
46
|
+
# ADR-17 — project-side monkey-patch pre-evaluation. Empty by default; users opt in by listing explicit
|
|
47
|
+
# files that the analyzer walks before per-file inference so patched-method declarations are visible
|
|
48
|
+
# across the project (e.g. `lib/core_ext/string_extensions.rb`). Slice 1 plumbing only — listed files
|
|
49
|
+
# are validated at config-load time (`pre-eval.file-not-found` on a missing path), but the dispatcher
|
|
50
|
+
# tier consuming the registry lands in slice 2.
|
|
62
51
|
"pre_eval" => [],
|
|
63
|
-
# ADR-22 — baseline file path. nil (default) means no
|
|
64
|
-
#
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
# The presence of `.rigor-baseline.yml` on disk alone does
|
|
68
|
-
# NOT activate filtering — the path must be named here
|
|
69
|
-
# (WD2 (b) of ADR-22).
|
|
52
|
+
# ADR-22 — baseline file path. nil (default) means no baseline is loaded; the `false` literal is
|
|
53
|
+
# treated as the explicit-disable form for `.rigor.yml`-side override of an upstream `.rigor.dist.yml`
|
|
54
|
+
# `baseline:` declaration. The presence of `.rigor-baseline.yml` on disk alone does NOT activate
|
|
55
|
+
# filtering — the path must be named here (WD2 (b) of ADR-22).
|
|
70
56
|
"baseline" => nil,
|
|
71
57
|
"fold_platform_specific_paths" => false,
|
|
72
58
|
"cache" => {
|
|
73
59
|
"path" => ".rigor/cache",
|
|
74
|
-
# LRU eviction cap in bytes (ADR-54 WD3). The least-recently-used
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
# live entries. Set explicitly to `null` to disable eviction
|
|
81
|
-
# (pre-WD3 behaviour: the cache grows until `--clear-cache`).
|
|
60
|
+
# LRU eviction cap in bytes (ADR-54 WD3). The least-recently-used entries are removed at the end of a
|
|
61
|
+
# run when the total exceeds this limit. The 256 MB default exists to reap orphans — entries whose
|
|
62
|
+
# content key nothing references any more (an rbs gem bump, a signature change) and that no run
|
|
63
|
+
# would otherwise ever delete; a full active per-project set is ~2 MB, so the cap never touches live
|
|
64
|
+
# entries. Set explicitly to `null` to disable eviction (pre-WD3 behaviour: the cache grows until
|
|
65
|
+
# `--clear-cache`).
|
|
82
66
|
"max_bytes" => 268_435_456
|
|
83
67
|
},
|
|
84
68
|
"plugins_io" => {
|
|
@@ -88,100 +72,74 @@ module Rigor
|
|
|
88
72
|
},
|
|
89
73
|
"severity_profile" => "balanced",
|
|
90
74
|
"severity_overrides" => {},
|
|
91
|
-
# ADR-50 § WD2 — bleeding-edge overlay opt-in. Selects which of
|
|
92
|
-
#
|
|
93
|
-
#
|
|
94
|
-
# `
|
|
95
|
-
#
|
|
96
|
-
# `{ all: true, except: [ids] }` (adopt all but the named). The
|
|
97
|
-
# overlay is empty today, so every form is currently a no-op; it
|
|
98
|
-
# becomes live when the first discipline is queued for a major.
|
|
75
|
+
# ADR-50 § WD2 — bleeding-edge overlay opt-in. Selects which of the *next major's* queued changes
|
|
76
|
+
# ({Rigor::BleedingEdge}) this project adopts early. Orthogonal to `severity_profile:`. Accepts `false`
|
|
77
|
+
# (default — adopt none), `true` (adopt the whole overlay), a list of feature ids (adopt only those),
|
|
78
|
+
# or `{ all: true, except: [ids] }` (adopt all but the named). The overlay is empty today, so every
|
|
79
|
+
# form is currently a no-op; it becomes live when the first discipline is queued for a major.
|
|
99
80
|
"bleeding_edge" => false,
|
|
100
81
|
"dependencies" => {
|
|
101
82
|
"source_inference" => [],
|
|
102
83
|
"budget_per_gem" => Configuration::Dependencies::DEFAULT_BUDGET_PER_GEM
|
|
103
84
|
},
|
|
104
85
|
"parallel" => {
|
|
105
|
-
# ADR-15 Phase 4c — when greater than zero, `rigor check`
|
|
106
|
-
#
|
|
107
|
-
#
|
|
108
|
-
#
|
|
109
|
-
# bit-for-bit unchanged. The CLI's `--workers=N` flag
|
|
110
|
-
# and the `RIGOR_RACTOR_WORKERS` env var both override
|
|
111
|
-
# this setting; precedence is CLI > env > config > 0.
|
|
86
|
+
# ADR-15 Phase 4c — when greater than zero, `rigor check` dispatches per-file analysis across N
|
|
87
|
+
# Ractor workers built around {Rigor::Analysis::WorkerSession}. `0` (default) keeps the sequential
|
|
88
|
+
# coordinator path bit-for-bit unchanged. The CLI's `--workers=N` flag and the `RIGOR_RACTOR_WORKERS`
|
|
89
|
+
# env var both override this setting; precedence is CLI > env > config > 0.
|
|
112
90
|
"workers" => 0
|
|
113
91
|
},
|
|
114
92
|
"bundler" => {
|
|
115
|
-
# Open item O4 — target-project Bundler awareness.
|
|
116
|
-
#
|
|
117
|
-
#
|
|
118
|
-
#
|
|
119
|
-
#
|
|
120
|
-
# already declares the same constant) degrade gracefully
|
|
121
|
-
# to "no RBS env" with a single-line warning naming the
|
|
122
|
-
# offending file, rather than hanging.
|
|
93
|
+
# Open item O4 — target-project Bundler awareness. When `bundle_path:` is set (or auto-detected),
|
|
94
|
+
# Rigor walks `<bundle_path>/ruby/*/gems/*/sig/` and adds each gem-shipped sig directory to
|
|
95
|
+
# `signature_paths:`. With O7's failure-memo in place, conflicts (a vendored sig already declares the
|
|
96
|
+
# same constant) degrade gracefully to "no RBS env" with a single-line warning naming the offending
|
|
97
|
+
# file, rather than hanging.
|
|
123
98
|
#
|
|
124
|
-
# `bundle_path:` (String, optional): explicit path to the
|
|
125
|
-
#
|
|
126
|
-
#
|
|
127
|
-
# (`paths:`'s base) when relative.
|
|
99
|
+
# `bundle_path:` (String, optional): explicit path to the bundler install root (e.g.,
|
|
100
|
+
# "vendor/bundle" or an absolute path). Resolved relative to the project root (`paths:`'s base) when
|
|
101
|
+
# relative.
|
|
128
102
|
#
|
|
129
|
-
# `auto_detect:` (Boolean, default true): when no
|
|
130
|
-
#
|
|
131
|
-
#
|
|
132
|
-
#
|
|
133
|
-
# found, no extra sigs are added — the analyzer sees
|
|
134
|
-
# only rigor's vendored RBS and the user's
|
|
135
|
-
# `signature_paths:`.
|
|
103
|
+
# `auto_detect:` (Boolean, default true): when no explicit `bundle_path:` is set, try
|
|
104
|
+
# `.bundle/config`'s `BUNDLE_PATH:` first; fall back to `vendor/bundle/` under the project root if it
|
|
105
|
+
# exists. When neither is found, no extra sigs are added — the analyzer sees only rigor's vendored
|
|
106
|
+
# RBS and the user's `signature_paths:`.
|
|
136
107
|
#
|
|
137
108
|
# O4 Layer 3 keys:
|
|
138
109
|
#
|
|
139
|
-
# `lockfile:` (String, optional): explicit path to a
|
|
140
|
-
#
|
|
141
|
-
#
|
|
142
|
-
# `
|
|
143
|
-
#
|
|
144
|
-
# directories: only gems whose `(name, version,
|
|
145
|
-
# platform)` matches a lockfile entry are admitted to
|
|
146
|
-
# `signature_paths:`. Stale or out-of-band gems sitting
|
|
147
|
-
# in the bundle install tree are silently dropped.
|
|
110
|
+
# `lockfile:` (String, optional): explicit path to a `Gemfile.lock`. Resolved relative to the
|
|
111
|
+
# project root when relative. When set (or auto-detected via the `auto_detect:` flag below) Rigor
|
|
112
|
+
# parses the lockfile and uses it to FILTER the bundle-discovered `sig/` directories: only gems whose
|
|
113
|
+
# `(name, version, platform)` matches a lockfile entry are admitted to `signature_paths:`. Stale or
|
|
114
|
+
# out-of-band gems sitting in the bundle install tree are silently dropped.
|
|
148
115
|
#
|
|
149
|
-
# `auto_detect:` (Boolean, also gates the lockfile
|
|
150
|
-
#
|
|
151
|
-
# `<project_root>/Gemfile.lock`.
|
|
116
|
+
# `auto_detect:` (Boolean, also gates the lockfile search): when true and `lockfile:` is nil, look
|
|
117
|
+
# for `<project_root>/Gemfile.lock`.
|
|
152
118
|
"bundle_path" => nil,
|
|
153
119
|
"auto_detect" => true,
|
|
154
120
|
"lockfile" => nil
|
|
155
121
|
},
|
|
156
122
|
"rbs_collection" => {
|
|
157
|
-
# Open item O4 Layer 3 slice 2 — `rbs collection
|
|
158
|
-
#
|
|
159
|
-
#
|
|
160
|
-
#
|
|
161
|
-
#
|
|
162
|
-
# holds the downloaded `.rbs` files. Rigor parses the
|
|
163
|
-
# lockfile and auto-feeds each gem's
|
|
164
|
-
# `<collection_root>/<name>/<version>/` directory into
|
|
165
|
-
# `RbsLoader`'s `signature_paths:`. Sources of type
|
|
166
|
-
# `stdlib` are skipped because rigor's bundled
|
|
123
|
+
# Open item O4 Layer 3 slice 2 — `rbs collection install` awareness. When the target project has been
|
|
124
|
+
# set up with `rbs collection install`, the resulting `rbs_collection.lock.yaml` carries the resolved
|
|
125
|
+
# (gem, version, source) triples and `.gem_rbs_collection/` holds the downloaded `.rbs` files. Rigor
|
|
126
|
+
# parses the lockfile and auto-feeds each gem's `<collection_root>/<name>/<version>/` directory into
|
|
127
|
+
# `RbsLoader`'s `signature_paths:`. Sources of type `stdlib` are skipped because rigor's bundled
|
|
167
128
|
# `DEFAULT_LIBRARIES` already covers that surface.
|
|
168
129
|
#
|
|
169
|
-
# `lockfile:` (String, optional): explicit path to
|
|
170
|
-
#
|
|
171
|
-
# project root when relative.
|
|
130
|
+
# `lockfile:` (String, optional): explicit path to `rbs_collection.lock.yaml`. Resolved relative to
|
|
131
|
+
# the project root when relative.
|
|
172
132
|
#
|
|
173
|
-
# `auto_detect:` (Boolean, default true): when no
|
|
174
|
-
# explicit `lockfile:` is set, look for
|
|
133
|
+
# `auto_detect:` (Boolean, default true): when no explicit `lockfile:` is set, look for
|
|
175
134
|
# `<project_root>/rbs_collection.lock.yaml`.
|
|
176
135
|
"lockfile" => nil,
|
|
177
136
|
"auto_detect" => true
|
|
178
137
|
}
|
|
179
138
|
}.freeze
|
|
180
139
|
|
|
181
|
-
# Top-level keys whose values are file/directory paths that
|
|
182
|
-
#
|
|
183
|
-
#
|
|
184
|
-
# are glob patterns (`**/vendor/**`), not paths.
|
|
140
|
+
# Top-level keys whose values are file/directory paths that MUST be resolved relative to the config
|
|
141
|
+
# file's directory. `exclude:` is intentionally NOT in this list — its entries are glob patterns
|
|
142
|
+
# (`**/vendor/**`), not paths.
|
|
185
143
|
PATH_KEYS = %w[paths signature_paths pre_eval].freeze
|
|
186
144
|
private_constant :PATH_KEYS
|
|
187
145
|
|
|
@@ -199,18 +157,14 @@ module Rigor
|
|
|
199
157
|
|
|
200
158
|
# Loads a configuration file.
|
|
201
159
|
#
|
|
202
|
-
# `path == nil` triggers auto-discovery against
|
|
203
|
-
# {DISCOVERY_ORDER}. The first present file in that list is
|
|
160
|
+
# `path == nil` triggers auto-discovery against {DISCOVERY_ORDER}. The first present file in that list is
|
|
204
161
|
# loaded; if none exist the built-in {DEFAULTS} are used.
|
|
205
162
|
#
|
|
206
|
-
# When a path is supplied (whether by auto-discovery or by
|
|
207
|
-
#
|
|
208
|
-
#
|
|
209
|
-
#
|
|
210
|
-
#
|
|
211
|
-
# The resolution is per-file: an included file's relative
|
|
212
|
-
# paths resolve against the included file's directory, not
|
|
213
|
-
# the top-level file. Path resolution mirrors
|
|
163
|
+
# When a path is supplied (whether by auto-discovery or by the caller) the YAML body is processed for
|
|
164
|
+
# `includes:` recursively, and every relative path inside path-bearing keys (`paths:`,
|
|
165
|
+
# `signature_paths:`, `plugins_io.allowed_paths:`, `includes:`) is resolved against THAT file's
|
|
166
|
+
# directory. The resolution is per-file: an included file's relative paths resolve against the included
|
|
167
|
+
# file's directory, not the top-level file. Path resolution mirrors
|
|
214
168
|
# [PHPStan](https://phpstan.org/config-reference#paths).
|
|
215
169
|
def self.load(path = nil)
|
|
216
170
|
resolved = path || discover
|
|
@@ -220,22 +174,17 @@ module Rigor
|
|
|
220
174
|
new(DEFAULTS.merge(data))
|
|
221
175
|
end
|
|
222
176
|
|
|
223
|
-
# Returns the path to the config file Rigor would load
|
|
224
|
-
#
|
|
225
|
-
# exists. Public so the CLI / spec drift checks can
|
|
226
|
-
# introspect the resolved file.
|
|
177
|
+
# Returns the path to the config file Rigor would load under auto-discovery, or `nil` when neither
|
|
178
|
+
# candidate exists. Public so the CLI / spec drift checks can introspect the resolved file.
|
|
227
179
|
def self.discover
|
|
228
180
|
DISCOVERY_ORDER.find { |candidate| File.exist?(candidate) }
|
|
229
181
|
end
|
|
230
182
|
|
|
231
|
-
# Reads `path` (which MUST exist) plus every file listed in
|
|
232
|
-
#
|
|
233
|
-
#
|
|
234
|
-
#
|
|
235
|
-
#
|
|
236
|
-
# Public so the CLI can run the include-aware load before
|
|
237
|
-
# applying `--treat-all-as-inline-rbs`'s plugin injection
|
|
238
|
-
# (see {CLI::CheckCommand#load_check_configuration}).
|
|
183
|
+
# Reads `path` (which MUST exist) plus every file listed in its `includes:` chain, merging them under the
|
|
184
|
+
# order: included files first (in declaration order), then the current file's own keys override.
|
|
185
|
+
# Relative paths inside each file are resolved against that file's directory. Public so the CLI can run
|
|
186
|
+
# the include-aware load before applying `--treat-all-as-inline-rbs`'s plugin injection (see
|
|
187
|
+
# {CLI::CheckCommand#load_check_configuration}).
|
|
239
188
|
def self.load_with_includes(path, visited: Set.new)
|
|
240
189
|
absolute = File.expand_path(path)
|
|
241
190
|
raise ArgumentError, "circular include: #{absolute}" if visited.include?(absolute)
|
|
@@ -265,12 +214,10 @@ module Rigor
|
|
|
265
214
|
deep_merge(accumulated, data)
|
|
266
215
|
end
|
|
267
216
|
|
|
268
|
-
# Per-file path resolution. Each path-bearing key listed in
|
|
269
|
-
#
|
|
270
|
-
#
|
|
271
|
-
#
|
|
272
|
-
# left as-is so end-user messages (e.g. `--cache-stats`
|
|
273
|
-
# output) keep the project-relative form the user wrote.
|
|
217
|
+
# Per-file path resolution. Each path-bearing key listed in {PATH_KEYS} plus the nested
|
|
218
|
+
# `plugins_io.allowed_paths:` entries get their relative paths expanded against the config file's
|
|
219
|
+
# directory. `cache.path:` is intentionally left as-is so end-user messages (e.g. `--cache-stats` output)
|
|
220
|
+
# keep the project-relative form the user wrote.
|
|
274
221
|
def self.resolve_paths_in(data, base_dir)
|
|
275
222
|
return data unless data.is_a?(Hash)
|
|
276
223
|
|
|
@@ -305,14 +252,11 @@ module Rigor
|
|
|
305
252
|
merged
|
|
306
253
|
end
|
|
307
254
|
|
|
308
|
-
# Most keys are right-wins (override) or recursively
|
|
309
|
-
#
|
|
310
|
-
#
|
|
311
|
-
#
|
|
312
|
-
#
|
|
313
|
-
# still merges deeply; only the inner array gets
|
|
314
|
-
# concatenated so {Dependencies.from_h} sees every
|
|
315
|
-
# contributor's entries and can dedupe them.
|
|
255
|
+
# Most keys are right-wins (override) or recursively merged hashes. ADR-10 § "config-conflict
|
|
256
|
+
# diagnostic" carves out `dependencies.source_inference[]`: the per-gem merge across `includes:` chains
|
|
257
|
+
# needs union behaviour with mode-conflict detection. The Hash itself still merges deeply; only the
|
|
258
|
+
# inner array gets concatenated so {Dependencies.from_h} sees every contributor's entries and can dedupe
|
|
259
|
+
# them.
|
|
316
260
|
def self.merge_value(key, merged, value)
|
|
317
261
|
if key == "dependencies" && merged[key].is_a?(Hash) && value.is_a?(Hash)
|
|
318
262
|
merge_dependencies_hash(merged[key], value)
|
|
@@ -388,15 +332,10 @@ module Rigor
|
|
|
388
332
|
rclf = rbs_collection.fetch("lockfile")
|
|
389
333
|
@rbs_collection_lockfile = rclf.nil? ? nil : rclf.to_s.dup.freeze
|
|
390
334
|
@rbs_collection_auto_detect = rbs_collection.fetch("auto_detect") == true
|
|
391
|
-
# Ractor migration Phase 2a: deep-freeze the
|
|
392
|
-
#
|
|
393
|
-
#
|
|
394
|
-
#
|
|
395
|
-
# collection / value object; freezing `self` makes the
|
|
396
|
-
# whole carrier safe to send across Ractor boundaries
|
|
397
|
-
# (and catches accidental post-init mutation in any
|
|
398
|
-
# caller). See
|
|
399
|
-
# `docs/design/20260514-ractor-migration.md`.
|
|
335
|
+
# Ractor migration Phase 2a: deep-freeze the Configuration so it is `Ractor.shareable?`. Every ivar
|
|
336
|
+
# above is now either a frozen value (Symbol / nil / Boolean) or an explicitly frozen collection /
|
|
337
|
+
# value object; freezing `self` makes the whole carrier safe to send across Ractor boundaries (and
|
|
338
|
+
# catches accidental post-init mutation in any caller). See `docs/design/20260514-ractor-migration.md`.
|
|
400
339
|
freeze
|
|
401
340
|
end
|
|
402
341
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
@@ -440,23 +379,19 @@ module Rigor
|
|
|
440
379
|
}
|
|
441
380
|
end
|
|
442
381
|
|
|
443
|
-
# ADR-50 § WD2 — returns a sibling Configuration whose bleeding-edge
|
|
444
|
-
#
|
|
445
|
-
#
|
|
446
|
-
#
|
|
447
|
-
#
|
|
448
|
-
#
|
|
449
|
-
# normalised through the same {#coerce_bleeding_edge} path, so an unknown
|
|
450
|
-
# id stays inert.
|
|
382
|
+
# ADR-50 § WD2 — returns a sibling Configuration whose bleeding-edge selection (and the derived
|
|
383
|
+
# `bleeding_edge_severity_overrides` the two {SeverityProfile.resolve} sites consult) is replaced by
|
|
384
|
+
# `value`, leaving every other field shared with the receiver. `value` takes the same forms as the
|
|
385
|
+
# `bleeding_edge:` config key — `false` / `true` / a feature-id Array / `{ "all" => true, "except" =>
|
|
386
|
+
# [...] }` — and is normalised through the same {#coerce_bleeding_edge} path, so an unknown id stays
|
|
387
|
+
# inert.
|
|
451
388
|
#
|
|
452
|
-
# The CLI's `--bleeding-edge[=ids]` / `--no-bleeding-edge` flag uses this
|
|
453
|
-
#
|
|
454
|
-
#
|
|
455
|
-
#
|
|
456
|
-
#
|
|
457
|
-
#
|
|
458
|
-
# deeply frozen, and the re-`freeze` keeps the result `Ractor.shareable?`
|
|
459
|
-
# for the worker path.
|
|
389
|
+
# The CLI's `--bleeding-edge[=ids]` / `--no-bleeding-edge` flag uses this to override the configured
|
|
390
|
+
# selection for a single run (the same CLI-over-config precedence `--workers` and `--no-cache` follow).
|
|
391
|
+
# It is a frozen `dup` with the two bleeding-edge ivars re-set: `dup` returns an unfrozen shallow copy
|
|
392
|
+
# (every other ivar is the receiver's deeply-frozen value, safe to share read-only), the two replacements
|
|
393
|
+
# are themselves deeply frozen, and the re-`freeze` keeps the result `Ractor.shareable?` for the worker
|
|
394
|
+
# path.
|
|
460
395
|
def with_bleeding_edge(value)
|
|
461
396
|
selector = coerce_bleeding_edge(value)
|
|
462
397
|
copy = dup
|
|
@@ -468,17 +403,13 @@ module Rigor
|
|
|
468
403
|
|
|
469
404
|
private
|
|
470
405
|
|
|
471
|
-
# ADR-17 slice 4 — `pre_eval:` glob expansion. Each entry is
|
|
472
|
-
#
|
|
473
|
-
# `
|
|
474
|
-
#
|
|
475
|
-
#
|
|
476
|
-
#
|
|
477
|
-
#
|
|
478
|
-
# `:error` (slice 1 behaviour); glob entries that match
|
|
479
|
-
# nothing degrade silently to "no contribution from this
|
|
480
|
-
# entry" so a templated `**` pattern in a fresh project
|
|
481
|
-
# doesn't generate an error per match-less pattern.
|
|
406
|
+
# ADR-17 slice 4 — `pre_eval:` glob expansion. Each entry is accepted as either a literal path (slice 1
|
|
407
|
+
# contract) OR a `File.fnmatch?`-shaped glob pattern (`lib/core_ext/**/*.rb`). Glob meta characters (`*`,
|
|
408
|
+
# `?`, `[`) trigger `Dir.glob` expansion; the resulting file list is folded into the `pre_eval:` set with
|
|
409
|
+
# `uniq`. Literal entries that don't exist on disk continue to surface as `pre-eval.file-not-found`
|
|
410
|
+
# `:error` (slice 1 behaviour); glob entries that match nothing degrade silently to "no contribution from
|
|
411
|
+
# this entry" so a templated `**` pattern in a fresh project doesn't generate an error per match-less
|
|
412
|
+
# pattern.
|
|
482
413
|
def expand_pre_eval_entries(entries)
|
|
483
414
|
entries.flat_map do |entry|
|
|
484
415
|
glob_pattern?(entry) ? Dir.glob(entry, sort: true) : [entry]
|
|
@@ -489,10 +420,8 @@ module Rigor
|
|
|
489
420
|
path.include?("*") || path.include?("?") || path.include?("[")
|
|
490
421
|
end
|
|
491
422
|
|
|
492
|
-
# Accepts either `"rigor-foo"` (gem-name shorthand) or
|
|
493
|
-
#
|
|
494
|
-
# (full form). Returns the canonical hash form so the loader
|
|
495
|
-
# works against a single shape.
|
|
423
|
+
# Accepts either `"rigor-foo"` (gem-name shorthand) or `{ "gem" => "rigor-foo", "id" => "foo", "config" =>
|
|
424
|
+
# {...} }` (full form). Returns the canonical hash form so the loader works against a single shape.
|
|
496
425
|
def coerce_plugin_entry(entry)
|
|
497
426
|
case entry
|
|
498
427
|
when String
|
|
@@ -505,16 +434,12 @@ module Rigor
|
|
|
505
434
|
end
|
|
506
435
|
end
|
|
507
436
|
|
|
508
|
-
# `target_ruby` is passed to `Prism.parse_file(path, version:)` at
|
|
509
|
-
#
|
|
510
|
-
#
|
|
511
|
-
#
|
|
512
|
-
#
|
|
513
|
-
#
|
|
514
|
-
# the literal `"latest"`. Prism itself enforces the supported
|
|
515
|
-
# set and raises `ArgumentError` for versions it does not
|
|
516
|
-
# recognise (e.g. `"1.0"`); the parse-time error message names
|
|
517
|
-
# the version, so the user can correct the setting.
|
|
437
|
+
# `target_ruby` is passed to `Prism.parse_file(path, version:)` at the analyser's three parse sites
|
|
438
|
+
# (`Analysis::Runner`, `CLI::TypeOfCommand`, `CLI::TypeScanCommand`) so projects that target an older
|
|
439
|
+
# Ruby get parse errors for syntax their target doesn't support. Format validation here is loose —
|
|
440
|
+
# accepts any `<major>.<minor>` or `<major>.<minor>.<patch>` form, plus the literal `"latest"`. Prism
|
|
441
|
+
# itself enforces the supported set and raises `ArgumentError` for versions it does not recognise (e.g.
|
|
442
|
+
# `"1.0"`); the parse-time error message names the version, so the user can correct the setting.
|
|
518
443
|
TARGET_RUBY_FORMAT = /\A(?:\d+\.\d+(?:\.\d+)?|latest)\z/
|
|
519
444
|
private_constant :TARGET_RUBY_FORMAT
|
|
520
445
|
|
|
@@ -528,22 +453,17 @@ module Rigor
|
|
|
528
453
|
s.dup.freeze
|
|
529
454
|
end
|
|
530
455
|
|
|
531
|
-
# YAML scalar may arrive as a String or already as a Symbol;
|
|
532
|
-
#
|
|
533
|
-
# `TrustPolicy` constructor stays strict.
|
|
456
|
+
# YAML scalar may arrive as a String or already as a Symbol; coerce to the canonical Symbol shape so the
|
|
457
|
+
# downstream `TrustPolicy` constructor stays strict.
|
|
534
458
|
#
|
|
535
|
-
# The accepted set is duplicated from
|
|
536
|
-
#
|
|
537
|
-
# `
|
|
538
|
-
# load time (Configuration is loaded before Plugin in
|
|
539
|
-
# `lib/rigor.rb`); the two stay in lockstep via spec.
|
|
459
|
+
# The accepted set is duplicated from {Rigor::Plugin::TrustPolicy::VALID_NETWORK_POLICIES} so
|
|
460
|
+
# `Configuration` does not require the plugin namespace at load time (Configuration is loaded before
|
|
461
|
+
# Plugin in `lib/rigor.rb`); the two stay in lockstep via spec.
|
|
540
462
|
VALID_NETWORK_POLICIES = %i[disabled allowlist].freeze
|
|
541
463
|
private_constant :VALID_NETWORK_POLICIES
|
|
542
464
|
|
|
543
|
-
# ADR-15 Phase 4c — accepts a non-negative Integer (or a
|
|
544
|
-
#
|
|
545
|
-
# annotations). Negative / non-integer values raise so
|
|
546
|
-
# typos / bad YAML fail loudly rather than silently
|
|
465
|
+
# ADR-15 Phase 4c — accepts a non-negative Integer (or a string-shaped one from YAML files that miss type
|
|
466
|
+
# annotations). Negative / non-integer values raise so typos / bad YAML fail loudly rather than silently
|
|
547
467
|
# disabling parallelism.
|
|
548
468
|
def coerce_parallel_workers(value)
|
|
549
469
|
integer = Integer(value)
|
|
@@ -554,11 +474,9 @@ module Rigor
|
|
|
554
474
|
raise ArgumentError, "parallel.workers must be a non-negative Integer, got #{value.inspect} (#{e.message})"
|
|
555
475
|
end
|
|
556
476
|
|
|
557
|
-
# ADR-22 WD2 (b) — `baseline: <path>` activates the file;
|
|
558
|
-
# `
|
|
559
|
-
#
|
|
560
|
-
# that names a baseline). `nil` (default / absent key) is
|
|
561
|
-
# also "no baseline".
|
|
477
|
+
# ADR-22 WD2 (b) — `baseline: <path>` activates the file; `baseline: false` is the explicit-disable form
|
|
478
|
+
# (useful in `.rigor.yml` to override an upstream `.rigor.dist.yml` that names a baseline). `nil`
|
|
479
|
+
# (default / absent key) is also "no baseline".
|
|
562
480
|
def coerce_baseline_path(value)
|
|
563
481
|
return nil if value.nil? || value == false
|
|
564
482
|
|
|
@@ -575,9 +493,8 @@ module Rigor
|
|
|
575
493
|
sym
|
|
576
494
|
end
|
|
577
495
|
|
|
578
|
-
# ADR-8 § "Severity profile" — accepts the canonical Symbol
|
|
579
|
-
#
|
|
580
|
-
# so typos fail loudly.
|
|
496
|
+
# ADR-8 § "Severity profile" — accepts the canonical Symbol form or its String spelling; rejects unknown
|
|
497
|
+
# profile names so typos fail loudly.
|
|
581
498
|
def coerce_severity_profile(value)
|
|
582
499
|
sym = value.to_sym
|
|
583
500
|
unless SeverityProfile::VALID_PROFILES.include?(sym)
|
|
@@ -589,21 +506,17 @@ module Rigor
|
|
|
589
506
|
sym
|
|
590
507
|
end
|
|
591
508
|
|
|
592
|
-
# ADR-8 § "Severity profile" — `severity_overrides:` is a
|
|
593
|
-
# `
|
|
594
|
-
# (`
|
|
595
|
-
#
|
|
596
|
-
# (`:error` / `:warning` / `:info` / `:off`). Unknown
|
|
597
|
-
# severities raise; unknown rule ids are silently kept (the
|
|
598
|
-
# override is inert until the rule lands).
|
|
509
|
+
# ADR-8 § "Severity profile" — `severity_overrides:` is a `{ rule => severity }` map. Keys are canonical
|
|
510
|
+
# rule ids (`call.undefined-method`) or family wildcards (`call`). Values are
|
|
511
|
+
# {SeverityProfile::VALID_SEVERITIES} symbols (`:error` / `:warning` / `:info` / `:off`). Unknown
|
|
512
|
+
# severities raise; unknown rule ids are silently kept (the override is inert until the rule lands).
|
|
599
513
|
def coerce_severity_overrides(value)
|
|
600
514
|
raise ArgumentError, "severity_overrides must be a Hash, got #{value.inspect}" unless value.is_a?(Hash)
|
|
601
515
|
|
|
602
516
|
value.to_h do |k, v|
|
|
603
|
-
# YAML 1.1 parses bare `off`/`on`/`no`/`yes`/`true`/`false`
|
|
604
|
-
#
|
|
605
|
-
#
|
|
606
|
-
# non-String case before `to_sym` blows up with a backtrace.
|
|
517
|
+
# YAML 1.1 parses bare `off`/`on`/`no`/`yes`/`true`/`false` as booleans, so a user who wrote `off` (a
|
|
518
|
+
# valid severity) without quotes hands us `false`. Catch the non-Symbol / non-String case before
|
|
519
|
+
# `to_sym` blows up with a backtrace.
|
|
607
520
|
unless v.is_a?(String) || v.is_a?(Symbol)
|
|
608
521
|
hint = v == false ? %( — did you mean the string "off"?) : ""
|
|
609
522
|
raise ArgumentError,
|
|
@@ -623,12 +536,10 @@ module Rigor
|
|
|
623
536
|
end.freeze
|
|
624
537
|
end
|
|
625
538
|
|
|
626
|
-
# ADR-50 § WD2 — normalizes the `bleeding_edge:` selector to a
|
|
627
|
-
#
|
|
628
|
-
#
|
|
629
|
-
#
|
|
630
|
-
# inert, like an unknown `severity_overrides:` rule). Deep-frozen so
|
|
631
|
-
# the Configuration stays `Ractor.shareable?`.
|
|
539
|
+
# ADR-50 § WD2 — normalizes the `bleeding_edge:` selector to a canonical `{ "mode" => … }` hash
|
|
540
|
+
# (interpreted by {Rigor::BleedingEdge}). Validates *shape* only; membership against the overlay is
|
|
541
|
+
# intentionally NOT checked here (an unknown id stays inert, like an unknown `severity_overrides:` rule).
|
|
542
|
+
# Deep-frozen so the Configuration stays `Ractor.shareable?`.
|
|
632
543
|
def coerce_bleeding_edge(value)
|
|
633
544
|
case value
|
|
634
545
|
when nil, false then { "mode" => "none" }
|
|
@@ -651,18 +562,16 @@ module Rigor
|
|
|
651
562
|
end
|
|
652
563
|
end
|
|
653
564
|
|
|
654
|
-
# Feature ids reach `coerce_bleeding_edge` from YAML, a `to_h` round-trip,
|
|
655
|
-
#
|
|
656
|
-
#
|
|
657
|
-
# the
|
|
658
|
-
# for the worker path (the same invariant `#initialize`'s final `freeze`
|
|
659
|
-
# upholds for every other field).
|
|
565
|
+
# Feature ids reach `coerce_bleeding_edge` from YAML, a `to_h` round-trip, or the CLI's
|
|
566
|
+
# `--bleeding-edge=a,b` (all runtime-created, non-frozen Strings). Each id String is frozen so the
|
|
567
|
+
# normalized selector — and thus the whole Configuration — stays deeply frozen and `Ractor.shareable?`
|
|
568
|
+
# for the worker path (the same invariant `#initialize`'s final `freeze` upholds for every other field).
|
|
660
569
|
def freeze_ids(ids)
|
|
661
570
|
ids.map { |id| id.to_s.dup.freeze }.freeze
|
|
662
571
|
end
|
|
663
572
|
|
|
664
|
-
# Renders the normalized selector back into the user-facing
|
|
665
|
-
#
|
|
573
|
+
# Renders the normalized selector back into the user-facing `bleeding_edge:` form for `#to_h`
|
|
574
|
+
# round-trips.
|
|
666
575
|
def bleeding_edge_to_h
|
|
667
576
|
case bleeding_edge["mode"]
|
|
668
577
|
when "all"
|