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
|
@@ -2,26 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
module Rigor
|
|
4
4
|
class FlowContribution
|
|
5
|
-
# Records a contradiction between two or more flow contributions
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# diagnostic per ADR-2 § "Plugin Contribution Merging".
|
|
5
|
+
# Records a contradiction between two or more flow contributions detected during {Merger.merge}. Carried on
|
|
6
|
+
# {MergeResult#conflicts} so the analyzer / formatter can surface a `:contribution_merge` diagnostic per
|
|
7
|
+
# ADR-2 § "Plugin Contribution Merging".
|
|
9
8
|
#
|
|
10
|
-
# ADR-2 § "Plugin Contribution Merging" rules out first-wins /
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
# `(target, edge, kind)` slot. The conflict object is the
|
|
15
|
-
# carrier of that report.
|
|
9
|
+
# ADR-2 § "Plugin Contribution Merging" rules out first-wins / last-wins behaviour: when contributions
|
|
10
|
+
# conflict, both sources are reported and the merger falls back to the nearest non-conflicting higher-tier
|
|
11
|
+
# (or default) value for the affected `(target, edge, kind)` slot. The conflict object is the carrier of
|
|
12
|
+
# that report.
|
|
16
13
|
#
|
|
17
14
|
# Slice-3 conflict reasons:
|
|
18
15
|
#
|
|
19
|
-
# - `:return_type_collapse` — two return-type contributions
|
|
20
|
-
#
|
|
21
|
-
# - `:
|
|
22
|
-
# incompatible non-`nil` exceptional effects.
|
|
23
|
-
# - `:lower_tier_contradiction` — a lower-tier contribution
|
|
24
|
-
# would weaken or contradict a higher-tier proof.
|
|
16
|
+
# - `:return_type_collapse` — two return-type contributions intersect to `bot`.
|
|
17
|
+
# - `:exceptional_disagreement` — two contributions assert incompatible non-`nil` exceptional effects.
|
|
18
|
+
# - `:lower_tier_contradiction` — a lower-tier contribution would weaken or contradict a higher-tier proof.
|
|
25
19
|
CONFLICT_VALID_REASONS = %i[
|
|
26
20
|
return_type_collapse
|
|
27
21
|
exceptional_disagreement
|
|
@@ -51,19 +45,14 @@ module Rigor
|
|
|
51
45
|
}
|
|
52
46
|
end
|
|
53
47
|
|
|
54
|
-
# ADR-7 § "Slice 5-C" — converts the conflict into a
|
|
55
|
-
# `
|
|
56
|
-
#
|
|
57
|
-
# qualified-rule formatter (slice 5 formatter half,
|
|
58
|
-
# `ef730b2`) prefixes the rule id with
|
|
59
|
-
# `contribution_merge.` and the JSON output side-bands
|
|
48
|
+
# ADR-7 § "Slice 5-C" — converts the conflict into a `Rigor::Analysis::Diagnostic` for the run result.
|
|
49
|
+
# Carries `source_family: :contribution_merge` so the qualified-rule formatter (slice 5 formatter half,
|
|
50
|
+
# `ef730b2`) prefixes the rule id with `contribution_merge.` and the JSON output side-bands
|
|
60
51
|
# `source_family` + `rule` for plugin attribution.
|
|
61
52
|
#
|
|
62
|
-
# The `rule` identifier is the kebab-case form of the
|
|
63
|
-
#
|
|
64
|
-
#
|
|
65
|
-
# reads `[contribution_merge.return-type-collapse]` in
|
|
66
|
-
# the standard text stream.
|
|
53
|
+
# The `rule` identifier is the kebab-case form of the conflict reason (`return_type_collapse` →
|
|
54
|
+
# `return-type-collapse`, etc.) so the qualified rule reads `[contribution_merge.return-type-collapse]`
|
|
55
|
+
# in the standard text stream.
|
|
67
56
|
def to_diagnostic(path:, line:, column:, severity: :error)
|
|
68
57
|
require_relative "../analysis/diagnostic" unless defined?(Rigor::Analysis::Diagnostic)
|
|
69
58
|
Rigor::Analysis::Diagnostic.new(
|
|
@@ -2,20 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
module Rigor
|
|
4
4
|
class FlowContribution
|
|
5
|
-
# Tagged element flattening of a {FlowContribution} bundle —
|
|
6
|
-
#
|
|
7
|
-
# Contribution Bundle"](../../../docs/adr/2-extension-api.md)
|
|
8
|
-
# routes through the {Merger}.
|
|
5
|
+
# Tagged element flattening of a {FlowContribution} bundle — the analyzer-internal representation
|
|
6
|
+
# [ADR-2 § "Flow Contribution Bundle"](../../../docs/adr/2-extension-api.md) routes through the {Merger}.
|
|
9
7
|
#
|
|
10
|
-
# The flattening is **mechanical, deterministic, and round-
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# and an array of elements rebuilds an equivalent bundle when
|
|
14
|
-
# routed through `Merger.merge`.
|
|
8
|
+
# The flattening is **mechanical, deterministic, and round-trippable** with the bundle: every non-empty slot
|
|
9
|
+
# expands into one or more elements keyed by `(target, edge, kind)`, and an array of elements rebuilds an
|
|
10
|
+
# equivalent bundle when routed through `Merger.merge`.
|
|
15
11
|
#
|
|
16
|
-
# Plugin authors should not depend on the element shape — the
|
|
17
|
-
#
|
|
18
|
-
# implementation surface the merge policy operates over.
|
|
12
|
+
# Plugin authors should not depend on the element shape — the bundle is the public contract; the element
|
|
13
|
+
# list is the implementation surface the merge policy operates over.
|
|
19
14
|
ELEMENT_VALID_EDGES = %i[normal truthy falsey post_return exceptional].freeze
|
|
20
15
|
ELEMENT_VALID_KINDS = %i[
|
|
21
16
|
return_type
|
|
@@ -2,63 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
module Rigor
|
|
4
4
|
class FlowContribution
|
|
5
|
-
# Canonical slot payload for the four edge-aware fact slots
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# `role_conformance` once those carriers grow Fact-shaped
|
|
9
|
-
# variants).
|
|
5
|
+
# Canonical slot payload for the four edge-aware fact slots (`truthy_facts`, `falsey_facts`,
|
|
6
|
+
# `post_return_facts`, plus the equivalent under `mutations` / `invalidations` / `role_conformance` once
|
|
7
|
+
# those carriers grow Fact-shaped variants).
|
|
10
8
|
#
|
|
11
|
-
# ADR-7 § "Slice 4-A" pins this object as the **single
|
|
12
|
-
# canonical translation target** for the four parallel
|
|
9
|
+
# ADR-7 § "Slice 4-A" pins this object as the **single canonical translation target** for the four parallel
|
|
13
10
|
# contribution carriers the engine has carried so far:
|
|
14
11
|
#
|
|
15
|
-
# 1. Built-in narrowing rules' direct fact emission
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
# (`Rigor::RbsExtended::PredicateEffect`).
|
|
19
|
-
# 3. RBS::Extended `assert*` directives
|
|
20
|
-
# (`Rigor::RbsExtended::AssertEffect`).
|
|
12
|
+
# 1. Built-in narrowing rules' direct fact emission (Inference::Narrowing#predicate_scopes).
|
|
13
|
+
# 2. RBS::Extended `predicate-if-*` directives (`Rigor::RbsExtended::PredicateEffect`).
|
|
14
|
+
# 3. RBS::Extended `assert*` directives (`Rigor::RbsExtended::AssertEffect`).
|
|
21
15
|
# 4. Plugin contributions via `narrowing_facts` DSL (ADR-52).
|
|
22
16
|
#
|
|
23
|
-
# Each of those four carriers translates to / from Fact at
|
|
24
|
-
#
|
|
25
|
-
# and
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
# carriers stay internal to the parser side — they hold the
|
|
29
|
-
# source-text shape, but lose their identity at the
|
|
30
|
-
# `read_flow_contribution` boundary.
|
|
17
|
+
# Each of those four carriers translates to / from Fact at its boundary; downstream of
|
|
18
|
+
# {Rigor::FlowContribution#to_element_list} and {Rigor::FlowContribution::Merger.merge}, every slot payload
|
|
19
|
+
# is a Fact (or a value that the merger compares by equality and never inspects). The typed
|
|
20
|
+
# `RbsExtended::*Effect` carriers stay internal to the parser side — they hold the source-text shape, but
|
|
21
|
+
# lose their identity at the `read_flow_contribution` boundary.
|
|
31
22
|
#
|
|
32
23
|
# ## Field set
|
|
33
24
|
#
|
|
34
|
-
# - `target_kind`: `:parameter` (call-site argument), `:self`
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
# - `
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
# name (e.g. `:x` for `expect(x).to be_a(T)`).
|
|
48
|
-
# - `type`: a `Rigor::Type::*` (Nominal, Refined,
|
|
49
|
-
# IntegerRange, Difference, …) the fact narrows the
|
|
50
|
-
# target toward (when `negative` is false) or away from
|
|
51
|
-
# (when `negative` is true).
|
|
52
|
-
# - `negative`: `true` for the `~T` negation form
|
|
53
|
-
# (`predicate-if-true x is ~Integer`), `false` for the
|
|
54
|
-
# plain positive form. Mirrors the `negative` field on
|
|
55
|
-
# `PredicateEffect` / `AssertEffect`.
|
|
25
|
+
# - `target_kind`: `:parameter` (call-site argument), `:self` (receiver), or `:local` (a named local in the
|
|
26
|
+
# surrounding scope). v0.1.8 Pillar 2 Slice 1 added `:local` so plugins recognising bespoke call shapes
|
|
27
|
+
# (`expect(x).to be_a(T)`) can narrow a specific scope-bound local without routing through the
|
|
28
|
+
# parameter-name lookup that requires an authoritative RBS sig on the called method. Future slices may
|
|
29
|
+
# extend further (`:ivar`, `:result`). The merger is agnostic to the concrete kinds and only requires
|
|
30
|
+
# equality.
|
|
31
|
+
# - `target_name`: a `Symbol`. For `:parameter` it's the declared parameter name. For `:self` it is the
|
|
32
|
+
# literal `:self` symbol so the field stays non-nil and the merge key is well-defined. For `:local` it's
|
|
33
|
+
# the local-variable name (e.g. `:x` for `expect(x).to be_a(T)`).
|
|
34
|
+
# - `type`: a `Rigor::Type::*` (Nominal, Refined, IntegerRange, Difference, …) the fact narrows the target
|
|
35
|
+
# toward (when `negative` is false) or away from (when `negative` is true).
|
|
36
|
+
# - `negative`: `true` for the `~T` negation form (`predicate-if-true x is ~Integer`), `false` for the plain
|
|
37
|
+
# positive form. Mirrors the `negative` field on `PredicateEffect` / `AssertEffect`.
|
|
56
38
|
#
|
|
57
|
-
# The `target` accessor returns `:self` for self-targeted
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
# the same parameter from different contribution sources
|
|
61
|
-
# land in the same merge bucket.
|
|
39
|
+
# The `target` accessor returns `:self` for self-targeted facts and `[:parameter, name]` otherwise — that's
|
|
40
|
+
# the value {Element#target} keys on, so two facts that narrow the same parameter from different
|
|
41
|
+
# contribution sources land in the same merge bucket.
|
|
62
42
|
FACT_VALID_TARGET_KINDS = %i[parameter self local].freeze
|
|
63
43
|
|
|
64
44
|
class Fact < Data.define(:target_kind, :target_name, :type, :negative)
|
|
@@ -77,15 +57,11 @@ module Rigor
|
|
|
77
57
|
super
|
|
78
58
|
end
|
|
79
59
|
|
|
80
|
-
# Composite target identifier the merger keys on. `:self`
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
# same symbol stay in separate buckets, which is the
|
|
86
|
-
# correct semantics: a `:local` fact narrows the surrounding
|
|
87
|
-
# scope's named local, a `:parameter` fact narrows the
|
|
88
|
-
# call-site argument matching the parameter declaration.
|
|
60
|
+
# Composite target identifier the merger keys on. `:self` for self-targeted facts; otherwise
|
|
61
|
+
# `[kind, name]` so two contributions that narrow the same `(kind, name)` pair — regardless of source
|
|
62
|
+
# family — land in the same merge bucket. `:local` and `:parameter` facts that name the same symbol stay
|
|
63
|
+
# in separate buckets, which is the correct semantics: a `:local` fact narrows the surrounding scope's
|
|
64
|
+
# named local, a `:parameter` fact narrows the call-site argument matching the parameter declaration.
|
|
89
65
|
def target
|
|
90
66
|
target_kind == :self ? :self : [target_kind, target_name]
|
|
91
67
|
end
|
|
@@ -2,16 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
module Rigor
|
|
4
4
|
class FlowContribution
|
|
5
|
-
# Result of folding any number of {FlowContribution} bundles
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# {Conflict} list collected along the way.
|
|
5
|
+
# Result of folding any number of {FlowContribution} bundles through {Merger.merge}. Surfaces the merged
|
|
6
|
+
# content slot-by-slot, the ordered list of contributing provenances, and the {Conflict} list collected
|
|
7
|
+
# along the way.
|
|
9
8
|
#
|
|
10
|
-
# The merge result is a sibling shape of {FlowContribution} —
|
|
11
|
-
# the
|
|
12
|
-
#
|
|
13
|
-
# plugin / RBS::Extended provenance. The shape is derived per
|
|
14
|
-
# ADR-2 § "Plugin Contribution Merging"; see
|
|
9
|
+
# The merge result is a sibling shape of {FlowContribution} — the analyzer reads from it to drive narrowing
|
|
10
|
+
# / dispatch / diagnostics, and the formatter reads from it to surface plugin / RBS::Extended provenance.
|
|
11
|
+
# The shape is derived per ADR-2 § "Plugin Contribution Merging"; see
|
|
15
12
|
# [`docs/internal-spec/flow-contribution-merger.md`](../../../docs/internal-spec/flow-contribution-merger.md)
|
|
16
13
|
# for the slice-3 normative description.
|
|
17
14
|
class MergeResult
|
|
@@ -6,55 +6,44 @@ require_relative "merge_result"
|
|
|
6
6
|
|
|
7
7
|
module Rigor
|
|
8
8
|
class FlowContribution
|
|
9
|
-
# Composes any number of {FlowContribution} bundles into a
|
|
10
|
-
# single
|
|
11
|
-
#
|
|
12
|
-
# the
|
|
13
|
-
# narrowing rules, `RBS::Extended` annotations, and plugins;
|
|
14
|
-
# slice 4 routes the existing internal narrowing through it
|
|
15
|
-
# and slice 6 wires plugin-side cache producers around it.
|
|
9
|
+
# Composes any number of {FlowContribution} bundles into a single {MergeResult} per ADR-2 § "Plugin
|
|
10
|
+
# Contribution Merging". The merger is the **single point of integration** the analyzer uses to combine
|
|
11
|
+
# contributions from built-in narrowing rules, `RBS::Extended` annotations, and plugins; slice 4 routes
|
|
12
|
+
# the existing internal narrowing through it and slice 6 wires plugin-side cache producers around it.
|
|
16
13
|
#
|
|
17
14
|
# ## Authority tiers
|
|
18
15
|
#
|
|
19
|
-
# - Tier 0: `:builtin` — Core Ruby semantics and accepted RBS
|
|
20
|
-
#
|
|
21
|
-
# - Tier 1: `:rbs_extended` (`RBS::Extended` directive bundles,
|
|
22
|
-
#
|
|
23
|
-
# signatures / metadata).
|
|
16
|
+
# - Tier 0: `:builtin` — Core Ruby semantics and accepted RBS contracts. Authoritative; lower tiers may
|
|
17
|
+
# not contradict.
|
|
18
|
+
# - Tier 1: `:rbs_extended` (`RBS::Extended` directive bundles, v0.0.9 group D reference impl) and
|
|
19
|
+
# `:generated` (generated signatures / metadata).
|
|
24
20
|
# - Tier 2: `:plugin` and `plugin.<id>` source families.
|
|
25
21
|
# - Tier 3: anything else — treated as the lowest tier.
|
|
26
22
|
#
|
|
27
|
-
# Within a tier, contributions are merged in deterministic
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
# pre-plugin contributions stable), then by their original
|
|
31
|
-
# input position as the final tie-break.
|
|
23
|
+
# Within a tier, contributions are merged in deterministic order: provenance-supplied `plugin_id`
|
|
24
|
+
# alphabetical (nil plugin ids sort first to keep `:rbs_extended` / `:generated` pre-plugin contributions
|
|
25
|
+
# stable), then by their original input position as the final tie-break.
|
|
32
26
|
#
|
|
33
27
|
# ## Composition rules (ADR-2)
|
|
34
28
|
#
|
|
35
|
-
# - `:return_type` — Intersect via `Type::Combinator.intersection`;
|
|
36
|
-
#
|
|
37
|
-
# - `:truthy_fact` / `:falsey_fact` / `:post_return_fact` —
|
|
38
|
-
#
|
|
39
|
-
# - `:mutation` / `:invalidation` / `:role` — Union; dedupe by
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
# exceptional effects raise `:exceptional_disagreement`.
|
|
29
|
+
# - `:return_type` — Intersect via `Type::Combinator.intersection`; collapse to bot raises
|
|
30
|
+
# `:return_type_collapse`.
|
|
31
|
+
# - `:truthy_fact` / `:falsey_fact` / `:post_return_fact` — Edge-local; accumulate while deduping by
|
|
32
|
+
# payload equality.
|
|
33
|
+
# - `:mutation` / `:invalidation` / `:role` — Union; dedupe by equality.
|
|
34
|
+
# - `:exception` — Single-valued. Two non-`nil` non-equal exceptional effects raise
|
|
35
|
+
# `:exceptional_disagreement`.
|
|
43
36
|
#
|
|
44
37
|
# ## Cross-tier contradictions
|
|
45
38
|
#
|
|
46
|
-
# Lower tiers may refine higher tiers but must not weaken them.
|
|
47
|
-
#
|
|
48
|
-
# when:
|
|
39
|
+
# Lower tiers may refine higher tiers but must not weaken them. Slice 3 surfaces contradictions through
|
|
40
|
+
# `:lower_tier_contradiction` when:
|
|
49
41
|
#
|
|
50
|
-
# - the higher tier already pinned a `return_type` and a lower
|
|
51
|
-
#
|
|
52
|
-
# - the higher tier set `exceptional` to a non-`nil` value and a
|
|
53
|
-
# lower tier disagrees.
|
|
42
|
+
# - the higher tier already pinned a `return_type` and a lower tier's intersection collapses to `bot`;
|
|
43
|
+
# - the higher tier set `exceptional` to a non-`nil` value and a lower tier disagrees.
|
|
54
44
|
#
|
|
55
|
-
# In every conflict case the result keeps the higher-tier value
|
|
56
|
-
#
|
|
57
|
-
# continues processing the remaining slots / contributions.
|
|
45
|
+
# In every conflict case the result keeps the higher-tier value for that slot, records a {Conflict} with
|
|
46
|
+
# both provenances, and continues processing the remaining slots / contributions.
|
|
58
47
|
module Merger
|
|
59
48
|
AUTHORITY_TIERS = {
|
|
60
49
|
builtin: 0,
|
|
@@ -91,8 +80,8 @@ module Rigor
|
|
|
91
80
|
private
|
|
92
81
|
|
|
93
82
|
def order_contributions(contributions)
|
|
94
|
-
# Stable sort: tier ascending, then provenance plugin_id
|
|
95
|
-
#
|
|
83
|
+
# Stable sort: tier ascending, then provenance plugin_id alphabetical (nil first), then original
|
|
84
|
+
# input position.
|
|
96
85
|
contributions.each_with_index
|
|
97
86
|
.sort_by { |c, i| [tier_for(c.provenance), plugin_id_key(c.provenance), i] }
|
|
98
87
|
.map { |c, _| c }
|
|
@@ -140,13 +129,10 @@ module Rigor
|
|
|
140
129
|
state.return_type_tier = [state.return_type_tier, tier].min
|
|
141
130
|
end
|
|
142
131
|
|
|
143
|
-
# Two types' intersection collapses to bot when neither
|
|
144
|
-
#
|
|
145
|
-
#
|
|
146
|
-
#
|
|
147
|
-
# Integer` builds a structurally-empty `Intersection`
|
|
148
|
-
# carrier), so the merger checks the disjointness condition
|
|
149
|
-
# directly via the `accepts` trinary.
|
|
132
|
+
# Two types' intersection collapses to bot when neither accepts the other under gradual mode — i.e.
|
|
133
|
+
# the value domains are disjoint. `Rigor::Type::Combinator.intersection` itself does not collapse
|
|
134
|
+
# incompatible nominals (`String ∩ Integer` builds a structurally-empty `Intersection` carrier), so
|
|
135
|
+
# the merger checks the disjointness condition directly via the `accepts` trinary.
|
|
150
136
|
def intersection_empty?(lhs, rhs)
|
|
151
137
|
return false if lhs.equal?(rhs)
|
|
152
138
|
|
|
@@ -227,9 +213,8 @@ module Rigor
|
|
|
227
213
|
end
|
|
228
214
|
end
|
|
229
215
|
|
|
230
|
-
# Internal accumulator carried through a single merge call.
|
|
231
|
-
#
|
|
232
|
-
# the end via {#to_result}.
|
|
216
|
+
# Internal accumulator carried through a single merge call. Not part of the public API; folds into a
|
|
217
|
+
# {MergeResult} at the end via {#to_result}.
|
|
233
218
|
class MergeState
|
|
234
219
|
attr_accessor :return_type, :return_type_tier, :return_type_provenance,
|
|
235
220
|
:exceptional, :exceptional_tier, :exceptional_provenance
|
|
@@ -3,33 +3,26 @@
|
|
|
3
3
|
require_relative "flow_contribution/element"
|
|
4
4
|
|
|
5
5
|
module Rigor
|
|
6
|
-
# The public packaging of a flow contribution at a single call edge.
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
# rather than letting any one source override another silently.
|
|
6
|
+
# The public packaging of a flow contribution at a single call edge. Plugins, `RBS::Extended` annotations,
|
|
7
|
+
# and built-in narrowing rules all hand the analyzer this same bundle shape; the inference engine merges
|
|
8
|
+
# contributions through the policy described in
|
|
9
|
+
# [ADR-2 § "Plugin Contribution Merging"](../../docs/adr/2-extension-api.md) rather than letting any one
|
|
10
|
+
# source override another silently.
|
|
12
11
|
#
|
|
13
|
-
# Eight content slots plus a {Provenance} block. A slot left as `nil`
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# policy treats it as absent.
|
|
12
|
+
# Eight content slots plus a {Provenance} block. A slot left as `nil` (or, for collection-shaped slots, an
|
|
13
|
+
# empty collection) means the contribution does not assert anything in that dimension; the merge policy
|
|
14
|
+
# treats it as absent.
|
|
17
15
|
#
|
|
18
|
-
# The struct is the only shape plugin authors need to learn. Richer
|
|
19
|
-
#
|
|
20
|
-
# contract — see ADR-2 § "Flow Contribution Bundle" for the binding
|
|
21
|
-
# definition.
|
|
16
|
+
# The struct is the only shape plugin authors need to learn. Richer or more permissive shapes are not part
|
|
17
|
+
# of the first public contract — see ADR-2 § "Flow Contribution Bundle" for the binding definition.
|
|
22
18
|
#
|
|
23
|
-
# `to_element_list` and `Merger` are implemented; plugin authors
|
|
24
|
-
#
|
|
25
|
-
# public contract.
|
|
19
|
+
# `to_element_list` and `Merger` are implemented; plugin authors should not depend on the `Element` shape —
|
|
20
|
+
# the bundle is the public contract.
|
|
26
21
|
class FlowContribution
|
|
27
|
-
# Provenance carries the metadata every contribution needs for
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
# contribution attaches to (or `nil` when the contribution does
|
|
32
|
-
# not need its own cache slice).
|
|
22
|
+
# Provenance carries the metadata every contribution needs for diagnostic attribution and cache
|
|
23
|
+
# invalidation. `source_family` mirrors {Rigor::Analysis::Diagnostic::DEFAULT_SOURCE_FAMILY}; `descriptor`
|
|
24
|
+
# is the {Rigor::Cache::Descriptor} this contribution attaches to (or `nil` when the contribution does not
|
|
25
|
+
# need its own cache slice).
|
|
33
26
|
class Provenance < Data.define(:source_family, :plugin_id, :node, :descriptor)
|
|
34
27
|
def self.builtin
|
|
35
28
|
new(source_family: :builtin, plugin_id: nil, node: nil, descriptor: nil)
|
|
@@ -49,27 +42,20 @@ module Rigor
|
|
|
49
42
|
|
|
50
43
|
attr_reader(*SLOT_NAMES, :provenance)
|
|
51
44
|
|
|
52
|
-
# @param return_type [Object, nil] normal-edge return type. Use
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
# truthy control-flow edge. Edge-local: a truthy-edge fact does
|
|
57
|
-
# NOT imply its falsey-edge complement (ADR-2 § "Plugin
|
|
58
|
-
# Contribution Merging").
|
|
45
|
+
# @param return_type [Object, nil] normal-edge return type. Use `nil` when the contribution does not
|
|
46
|
+
# refine the return type selected from the RBS contract.
|
|
47
|
+
# @param truthy_facts [Array, nil] facts that hold only on the truthy control-flow edge. Edge-local: a
|
|
48
|
+
# truthy-edge fact does NOT imply its falsey-edge complement (ADR-2 § "Plugin Contribution Merging").
|
|
59
49
|
# @param falsey_facts [Array, nil] dual of `truthy_facts`.
|
|
60
|
-
# @param post_return_facts [Array, nil] facts that hold after the
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
# @param
|
|
64
|
-
#
|
|
65
|
-
# @param
|
|
66
|
-
#
|
|
67
|
-
# @param
|
|
68
|
-
#
|
|
69
|
-
# @param role_conformance [Array, nil] capability-role conformance
|
|
70
|
-
# facts the contribution provides.
|
|
71
|
-
# @param provenance [Provenance] source-family, plugin-id, node,
|
|
72
|
-
# and cache-descriptor metadata. Defaults to `Provenance.builtin`.
|
|
50
|
+
# @param post_return_facts [Array, nil] facts that hold after the call returns normally on every edge —
|
|
51
|
+
# the carrier for assertion-style contributions.
|
|
52
|
+
# @param mutations [Array, nil] receiver and argument mutation effects.
|
|
53
|
+
# @param invalidations [Array, nil] targeted fact invalidations beyond what mutation effects already
|
|
54
|
+
# imply.
|
|
55
|
+
# @param exceptional [Object, nil] non-returning, raising, or unreachable effect.
|
|
56
|
+
# @param role_conformance [Array, nil] capability-role conformance facts the contribution provides.
|
|
57
|
+
# @param provenance [Provenance] source-family, plugin-id, node, and cache-descriptor metadata. Defaults
|
|
58
|
+
# to `Provenance.builtin`.
|
|
73
59
|
# rubocop:disable Metrics/ParameterLists
|
|
74
60
|
def initialize(return_type: nil, truthy_facts: nil, falsey_facts: nil,
|
|
75
61
|
post_return_facts: nil, mutations: nil, invalidations: nil,
|
|
@@ -88,9 +74,8 @@ module Rigor
|
|
|
88
74
|
freeze
|
|
89
75
|
end
|
|
90
76
|
|
|
91
|
-
# @return [Boolean] true when every content slot is unset (nil or
|
|
92
|
-
# an empty
|
|
93
|
-
# emptiness — an empty bundle still carries source attribution.
|
|
77
|
+
# @return [Boolean] true when every content slot is unset (nil or an empty collection). Provenance does
|
|
78
|
+
# not count toward emptiness — an empty bundle still carries source attribution.
|
|
94
79
|
def empty?
|
|
95
80
|
SLOT_NAMES.all? { |slot| slot_empty?(public_send(slot)) }
|
|
96
81
|
end
|
|
@@ -101,10 +86,9 @@ module Rigor
|
|
|
101
86
|
end
|
|
102
87
|
end
|
|
103
88
|
|
|
104
|
-
# Flattens this bundle into a tagged element list keyed by
|
|
105
|
-
#
|
|
106
|
-
#
|
|
107
|
-
# back through the merger produces an equivalent bundle.
|
|
89
|
+
# Flattens this bundle into a tagged element list keyed by `(target, edge, kind)`. The flattening is
|
|
90
|
+
# mechanical and round-trippable through {Merger.merge}: feeding the result back through the merger
|
|
91
|
+
# produces an equivalent bundle.
|
|
108
92
|
#
|
|
109
93
|
# Layout:
|
|
110
94
|
#
|
|
@@ -150,11 +134,9 @@ module Rigor
|
|
|
150
134
|
Element.new(target: target, edge: edge, kind: kind, payload: payload, provenance: provenance)
|
|
151
135
|
end
|
|
152
136
|
|
|
153
|
-
# Best-effort target extraction. Payloads that expose a
|
|
154
|
-
#
|
|
155
|
-
#
|
|
156
|
-
# payload itself as the merge key, which keeps deduplication
|
|
157
|
-
# well-defined for opaque entries.
|
|
137
|
+
# Best-effort target extraction. Payloads that expose a `#target` accessor (typed-fact carriers, mutation
|
|
138
|
+
# effects) provide their own; everything else falls through with the payload itself as the merge key,
|
|
139
|
+
# which keeps deduplication well-defined for opaque entries.
|
|
158
140
|
def fact_target(payload)
|
|
159
141
|
return payload.target if payload.respond_to?(:target)
|
|
160
142
|
|