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/rbs_extended.rb
CHANGED
|
@@ -7,12 +7,10 @@ require_relative "rbs_extended/reporter"
|
|
|
7
7
|
require_relative "rbs_extended/hkt_directives"
|
|
8
8
|
|
|
9
9
|
module Rigor
|
|
10
|
-
# Reader for the `RBS::Extended` annotation surface described in
|
|
11
|
-
# `docs/type-specification/rbs-extended.md`.
|
|
10
|
+
# Reader for the `RBS::Extended` annotation surface described in `docs/type-specification/rbs-extended.md`.
|
|
12
11
|
#
|
|
13
|
-
# Reads `%a{rigor:v1:<directive> <payload>}` annotations off RBS
|
|
14
|
-
#
|
|
15
|
-
# inference engine can consume. Implemented directives:
|
|
12
|
+
# Reads `%a{rigor:v1:<directive> <payload>}` annotations off RBS method definitions and returns well-typed
|
|
13
|
+
# effect objects the inference engine can consume. Implemented directives:
|
|
16
14
|
#
|
|
17
15
|
# - `rigor:v1:predicate-if-true <target> is <ClassName|refinement>`
|
|
18
16
|
# - `rigor:v1:predicate-if-false <target> is <ClassName|refinement>`
|
|
@@ -23,45 +21,33 @@ module Rigor
|
|
|
23
21
|
# - `rigor:v1:return <type-expr>` — per-call return override
|
|
24
22
|
# - `rigor:v1:conforms-to <InterfaceName>` — structural conformance
|
|
25
23
|
#
|
|
26
|
-
# `predicate-if-*` fires when the call is used as an `if` / `unless`
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
# right-hand sides. Parameterised refinements (`non-empty-array[T]`)
|
|
32
|
-
# are also recognised. Annotations whose directive is unrecognised
|
|
33
|
-
# are silently ignored per the spec's "unsupported metadata" guidance.
|
|
24
|
+
# `predicate-if-*` fires when the call is used as an `if` / `unless` condition; `assert` fires unconditionally
|
|
25
|
+
# at the call's post-scope; `assert-if-true` / `assert-if-false` fire at the post-scope only when the call's
|
|
26
|
+
# return value can be observed as truthy / falsey. Negation (`~T`) is supported for both class-name and
|
|
27
|
+
# refinement right-hand sides. Parameterised refinements (`non-empty-array[T]`) are also recognised. Annotations
|
|
28
|
+
# whose directive is unrecognised are silently ignored per the spec's "unsupported metadata" guidance.
|
|
34
29
|
module RbsExtended # rubocop:disable Metrics/ModuleLength
|
|
35
30
|
DIRECTIVE_PREFIX = "rigor:v1:"
|
|
36
31
|
|
|
37
|
-
# Returned for `predicate-if-true` / `predicate-if-false`.
|
|
38
|
-
# `
|
|
39
|
-
#
|
|
40
|
-
# when the directive uses the `~ClassName` form, in
|
|
41
|
-
# which case the engine narrows AWAY from `class_name`
|
|
42
|
-
# (`Narrowing.narrow_not_class`) instead of toward it.
|
|
32
|
+
# Returned for `predicate-if-true` / `predicate-if-false`. `target_kind` is `:parameter` (with `target_name`
|
|
33
|
+
# the Ruby parameter symbol) or `:self`. `negative` is true when the directive uses the `~ClassName` form, in
|
|
34
|
+
# which case the engine narrows AWAY from `class_name` (`Narrowing.narrow_not_class`) instead of toward it.
|
|
43
35
|
#
|
|
44
|
-
# `refinement_type` is non-nil when the right-hand side is
|
|
45
|
-
# a
|
|
46
|
-
# `
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
# may be true for refinement-form directives — `~T` negation
|
|
50
|
-
# is supported; the narrowing tier computes the complement
|
|
51
|
-
# decomposition (see `AssertEffect` docs below).
|
|
36
|
+
# `refinement_type` is non-nil when the right-hand side is a kebab-case refinement name (`non-empty-string`,
|
|
37
|
+
# `lowercase-string`, …) instead of a Capitalised class name. The narrowing tier substitutes the carrier for
|
|
38
|
+
# the current local type; `class_name` is then nil. `negative` may be true for refinement-form directives —
|
|
39
|
+
# `~T` negation is supported; the narrowing tier computes the complement decomposition (see `AssertEffect`
|
|
40
|
+
# docs below).
|
|
52
41
|
class PredicateEffect < Data.define(:edge, :target_kind, :target_name, :class_name, :negative, :refinement_type)
|
|
53
42
|
def truthy_only? = edge == :truthy_only
|
|
54
43
|
def falsey_only? = edge == :falsey_only
|
|
55
44
|
def negative? = negative == true
|
|
56
45
|
def refinement? = !refinement_type.nil?
|
|
57
46
|
|
|
58
|
-
# ADR-7 § "Slice 4-A" canonical translation. Lifts the
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
# `refinement_type` is already a `Rigor::Type` and passes
|
|
63
|
-
# through. The `edge` field doesn't survive the conversion —
|
|
64
|
-
# the slot it lands in (truthy_facts / falsey_facts / ...)
|
|
47
|
+
# ADR-7 § "Slice 4-A" canonical translation. Lifts the parser-side carrier into a
|
|
48
|
+
# `Rigor::FlowContribution::Fact` that the merger and plugin contribution stream consume uniformly.
|
|
49
|
+
# `class_name` lifts to `Nominal[<class>]`; `refinement_type` is already a `Rigor::Type` and passes through.
|
|
50
|
+
# The `edge` field doesn't survive the conversion — the slot it lands in (truthy_facts / falsey_facts / ...)
|
|
65
51
|
# encodes that.
|
|
66
52
|
def to_fact
|
|
67
53
|
FlowContribution::Fact.new(
|
|
@@ -73,21 +59,14 @@ module Rigor
|
|
|
73
59
|
end
|
|
74
60
|
end
|
|
75
61
|
|
|
76
|
-
# Returned for `assert` / `assert-if-true` /
|
|
77
|
-
# `assert-if-false`. `condition` is one of:
|
|
62
|
+
# Returned for `assert` / `assert-if-true` / `assert-if-false`. `condition` is one of:
|
|
78
63
|
#
|
|
79
|
-
# - `:always` — refines `target` at the call's
|
|
80
|
-
#
|
|
81
|
-
#
|
|
82
|
-
# - `:if_truthy_return` — refines `target` only when the
|
|
83
|
-
# call's return value is observed
|
|
84
|
-
# as truthy (currently: as the
|
|
85
|
-
# predicate of a subsequent
|
|
86
|
-
# `if` / `unless`).
|
|
64
|
+
# - `:always` — refines `target` at the call's post-scope unconditionally (`assert`).
|
|
65
|
+
# - `:if_truthy_return` — refines `target` only when the call's return value is observed as truthy
|
|
66
|
+
# (currently: as the predicate of a subsequent `if` / `unless`).
|
|
87
67
|
# - `:if_falsey_return` — symmetric for falsey.
|
|
88
68
|
#
|
|
89
|
-
# `negative` mirrors `PredicateEffect`: true when the
|
|
90
|
-
# directive uses `~ClassName` syntax.
|
|
69
|
+
# `negative` mirrors `PredicateEffect`: true when the directive uses `~ClassName` syntax.
|
|
91
70
|
class AssertEffect < Data.define(:condition, :target_kind, :target_name, :class_name, :negative, :refinement_type)
|
|
92
71
|
def always? = condition == :always
|
|
93
72
|
def if_truthy_return? = condition == :if_truthy_return
|
|
@@ -95,12 +74,9 @@ module Rigor
|
|
|
95
74
|
def negative? = negative == true
|
|
96
75
|
def refinement? = !refinement_type.nil?
|
|
97
76
|
|
|
98
|
-
# ADR-7 § "Slice 4-A" canonical translation. Same shape as
|
|
99
|
-
# `
|
|
100
|
-
#
|
|
101
|
-
# routes which slot the resulting fact lands in at the
|
|
102
|
-
# `read_flow_contribution` boundary, but does not surface
|
|
103
|
-
# on the Fact itself.
|
|
77
|
+
# ADR-7 § "Slice 4-A" canonical translation. Same shape as `PredicateEffect#to_fact`; the `condition` field
|
|
78
|
+
# (`:always` / `:if_truthy_return` / `:if_falsey_return`) routes which slot the resulting fact lands in at
|
|
79
|
+
# the `read_flow_contribution` boundary, but does not surface on the Fact itself.
|
|
104
80
|
def to_fact
|
|
105
81
|
FlowContribution::Fact.new(
|
|
106
82
|
target_kind: target_kind,
|
|
@@ -113,12 +89,9 @@ module Rigor
|
|
|
113
89
|
|
|
114
90
|
module_function
|
|
115
91
|
|
|
116
|
-
# Reads RBS::Extended predicate effects off
|
|
117
|
-
# `
|
|
118
|
-
#
|
|
119
|
-
# `rigor:v1:` directives are dropped. Returns an empty
|
|
120
|
-
# array (NEVER `nil`) for a method with no recognised
|
|
121
|
-
# annotations so callers can iterate unconditionally.
|
|
92
|
+
# Reads RBS::Extended predicate effects off `RBS::Definition::Method#annotations`. Returns the effects in
|
|
93
|
+
# source order; duplicates and unrecognised `rigor:v1:` directives are dropped. Returns an empty array (NEVER
|
|
94
|
+
# `nil`) for a method with no recognised annotations so callers can iterate unconditionally.
|
|
122
95
|
#
|
|
123
96
|
# @param environment [Rigor::Environment, nil] ADR-13 slice
|
|
124
97
|
# 3b. When provided, threads the plugin-supplied
|
|
@@ -148,14 +121,11 @@ module Rigor
|
|
|
148
121
|
effects.uniq
|
|
149
122
|
end
|
|
150
123
|
|
|
151
|
-
# The right-hand side accepts either a Capitalised class
|
|
152
|
-
#
|
|
153
|
-
#
|
|
154
|
-
#
|
|
155
|
-
#
|
|
156
|
-
# share the same overall directive shape; the parser
|
|
157
|
-
# detects which form matched by looking at the `class_name`
|
|
158
|
-
# vs `refinement` capture groups.
|
|
124
|
+
# The right-hand side accepts either a Capitalised class name (with optional `~` negation, optional `::`
|
|
125
|
+
# prefix, qualified names) OR a kebab-case refinement payload routed through
|
|
126
|
+
# `Builtins::ImportedRefinements::Parser` (bare names, `name[T]`, `name<min, max>`). The two arms share the
|
|
127
|
+
# same overall directive shape; the parser detects which form matched by looking at the `class_name` vs
|
|
128
|
+
# `refinement` capture groups.
|
|
159
129
|
PREDICATE_DIRECTIVE_PATTERN = /
|
|
160
130
|
\A
|
|
161
131
|
rigor:v1:(?<directive>predicate-if-(?:true|false))
|
|
@@ -202,14 +172,11 @@ module Rigor
|
|
|
202
172
|
)
|
|
203
173
|
end
|
|
204
174
|
|
|
205
|
-
# Reads RBS::Extended assertion effects (`assert`,
|
|
206
|
-
# `
|
|
207
|
-
# `RBS::Definition::Method#annotations`. Returns an empty
|
|
208
|
-
# array when no recognised assertion directives are
|
|
175
|
+
# Reads RBS::Extended assertion effects (`assert`, `assert-if-true`, `assert-if-false`) off
|
|
176
|
+
# `RBS::Definition::Method#annotations`. Returns an empty array when no recognised assertion directives are
|
|
209
177
|
# attached to the method.
|
|
210
178
|
#
|
|
211
|
-
# See {.read_predicate_effects} for the `environment:`
|
|
212
|
-
# keyword contract.
|
|
179
|
+
# See {.read_predicate_effects} for the `environment:` keyword contract.
|
|
213
180
|
def read_assert_effects(method_def, environment: nil)
|
|
214
181
|
return [] if method_def.nil?
|
|
215
182
|
|
|
@@ -332,16 +299,11 @@ module Rigor
|
|
|
332
299
|
end
|
|
333
300
|
end
|
|
334
301
|
|
|
335
|
-
# Reads the `rigor:v1:return: <kebab-name>` directive off
|
|
336
|
-
#
|
|
337
|
-
#
|
|
338
|
-
#
|
|
339
|
-
#
|
|
340
|
-
# primary integration path for refinement carriers
|
|
341
|
-
# (`non-empty-string`, `positive-int`, `non-empty-array`, …)
|
|
342
|
-
# in v0.0 — annotation-driven, opt-in per method, and never
|
|
343
|
-
# silently rewrites a hand-authored RBS signature outside the
|
|
344
|
-
# annotation.
|
|
302
|
+
# Reads the `rigor:v1:return: <kebab-name>` directive off `RBS::Definition::Method#annotations`. The
|
|
303
|
+
# directive overrides a method's RBS-declared return type with one of the imported-built-in refinements
|
|
304
|
+
# registered in `Rigor::Builtins::ImportedRefinements`. The override is the primary integration path for
|
|
305
|
+
# refinement carriers (`non-empty-string`, `positive-int`, `non-empty-array`, …) in v0.0 — annotation-driven,
|
|
306
|
+
# opt-in per method, and never silently rewrites a hand-authored RBS signature outside the annotation.
|
|
345
307
|
#
|
|
346
308
|
# Example annotation in an RBS file:
|
|
347
309
|
#
|
|
@@ -350,22 +312,16 @@ module Rigor
|
|
|
350
312
|
# def name: () -> String
|
|
351
313
|
# end
|
|
352
314
|
#
|
|
353
|
-
# The RBS-declared return is `String`. The override
|
|
354
|
-
#
|
|
355
|
-
#
|
|
356
|
-
# tightened return goes back to `String` so the round-trip
|
|
357
|
-
# to ordinary RBS is unaffected.
|
|
315
|
+
# The RBS-declared return is `String`. The override tightens it to `non-empty-string` (i.e.
|
|
316
|
+
# `Difference[String, ""]`) for callers; RBS erasure of the tightened return goes back to `String` so the
|
|
317
|
+
# round-trip to ordinary RBS is unaffected.
|
|
358
318
|
#
|
|
359
319
|
# Returns the resolved `Rigor::Type` value, or `nil` when:
|
|
360
320
|
# - the method has no annotations,
|
|
361
|
-
# - none of the annotations match the `rigor:v1:return:`
|
|
362
|
-
#
|
|
363
|
-
#
|
|
364
|
-
#
|
|
365
|
-
# (the analyzer prefers a silent miss over crashing on a
|
|
366
|
-
# typo; ADR-13 slice 3b surfaces the miss as a
|
|
367
|
-
# `dynamic.rbs-extended.unresolved` `:info` diagnostic when
|
|
368
|
-
# an `environment:` is supplied).
|
|
321
|
+
# - none of the annotations match the `rigor:v1:return:` directive,
|
|
322
|
+
# - the directive's payload names a refinement not registered in `Rigor::Builtins::ImportedRefinements` (the
|
|
323
|
+
# analyzer prefers a silent miss over crashing on a typo; ADR-13 slice 3b surfaces the miss as a
|
|
324
|
+
# `dynamic.rbs-extended.unresolved` `:info` diagnostic when an `environment:` is supplied).
|
|
369
325
|
def read_return_type_override(method_def, environment: nil)
|
|
370
326
|
return nil if method_def.nil?
|
|
371
327
|
|
|
@@ -389,14 +345,10 @@ module Rigor
|
|
|
389
345
|
nil
|
|
390
346
|
end
|
|
391
347
|
|
|
392
|
-
# The trailing payload supports the full refinement
|
|
393
|
-
#
|
|
394
|
-
#
|
|
395
|
-
#
|
|
396
|
-
# Integer]`, and `int<5, 10>`. The directive head is
|
|
397
|
-
# consumed by the regex; the rest is forwarded to the
|
|
398
|
-
# refinement parser. Anything the parser cannot resolve
|
|
399
|
-
# falls back to nil so the call site keeps the
|
|
348
|
+
# The trailing payload supports the full refinement grammar in `Builtins::ImportedRefinements::Parser` — bare
|
|
349
|
+
# kebab-case names plus parameterised forms like `non-empty-array[Integer]`, `non-empty-hash[Symbol,
|
|
350
|
+
# Integer]`, and `int<5, 10>`. The directive head is consumed by the regex; the rest is forwarded to the
|
|
351
|
+
# refinement parser. Anything the parser cannot resolve falls back to nil so the call site keeps the
|
|
400
352
|
# RBS-declared return type.
|
|
401
353
|
RETURN_DIRECTIVE_PATTERN = /
|
|
402
354
|
\A
|
|
@@ -408,15 +360,11 @@ module Rigor
|
|
|
408
360
|
/x
|
|
409
361
|
private_constant :RETURN_DIRECTIVE_PATTERN
|
|
410
362
|
|
|
411
|
-
# ADR-20 slice 2d — recognises `App[<uri>, <ClassName>, ...]`
|
|
412
|
-
#
|
|
413
|
-
#
|
|
414
|
-
#
|
|
415
|
-
#
|
|
416
|
-
# Slice 2d keeps the arg vocabulary intentionally narrow;
|
|
417
|
-
# parameterised forms (`Array[T]`, `Hash[K, V]`), unions,
|
|
418
|
-
# and refinements inside `App[...]` wait for a follow-up
|
|
419
|
-
# slice's expression parser.
|
|
363
|
+
# ADR-20 slice 2d — recognises `App[<uri>, <ClassName>, ...]` syntax in a `rigor:v1:return:` payload before
|
|
364
|
+
# falling through to the refinement-name parser. The match captures the namespaced URI (`json::value`) plus a
|
|
365
|
+
# comma-separated list of bare class names (`String`, `Symbol`, `Integer`). Slice 2d keeps the arg vocabulary
|
|
366
|
+
# intentionally narrow; parameterised forms (`Array[T]`, `Hash[K, V]`), unions, and refinements inside
|
|
367
|
+
# `App[...]` wait for a follow-up slice's expression parser.
|
|
420
368
|
APP_PAYLOAD_PATTERN = /
|
|
421
369
|
\A
|
|
422
370
|
App\[
|
|
@@ -452,17 +400,12 @@ module Rigor
|
|
|
452
400
|
type
|
|
453
401
|
end
|
|
454
402
|
|
|
455
|
-
# ADR-20 slice 2d. Parses `App[<uri>, <ClassName>, ...]`
|
|
456
|
-
#
|
|
457
|
-
#
|
|
458
|
-
# `
|
|
459
|
-
#
|
|
460
|
-
# `
|
|
461
|
-
# String]], Hash[String, App[json::value, String]]]`)
|
|
462
|
-
# rather than the opaque carrier. When the registry is
|
|
463
|
-
# absent or the URI is unregistered, the carrier with its
|
|
464
|
-
# registry-supplied bound (or `untyped` as a last-resort
|
|
465
|
-
# fallback) is returned as-is.
|
|
403
|
+
# ADR-20 slice 2d. Parses `App[<uri>, <ClassName>, ...]` syntax into a `Rigor::Type::App`. When
|
|
404
|
+
# `hkt_registry` is supplied and the URI is registered with a body_tree, the `App` is reduced eagerly via
|
|
405
|
+
# {Inference::HktRegistry#reduce} so call sites observe the unfolded form (e.g.
|
|
406
|
+
# `Union[nil, true, false, ..., Array[App[json::value, String]], Hash[String, App[json::value, String]]]`)
|
|
407
|
+
# rather than the opaque carrier. When the registry is absent or the URI is unregistered, the carrier with
|
|
408
|
+
# its registry-supplied bound (or `untyped` as a last-resort fallback) is returned as-is.
|
|
466
409
|
def parse_app_payload(payload, name_scope: nil, reporter: nil, source_location: nil, hkt_registry: nil)
|
|
467
410
|
match = APP_PAYLOAD_PATTERN.match(payload)
|
|
468
411
|
return nil if match.nil?
|
|
@@ -499,22 +442,15 @@ module Rigor
|
|
|
499
442
|
Type::Nominal.new(normalized)
|
|
500
443
|
end
|
|
501
444
|
|
|
502
|
-
# Returned for `rigor:v1:param: <name> <refinement>`. The
|
|
503
|
-
#
|
|
504
|
-
#
|
|
505
|
-
# (bare kebab-case name, parameterised form, or `int<...>`
|
|
506
|
-
# range — the same grammar the `return:` directive
|
|
507
|
-
# accepts).
|
|
445
|
+
# Returned for `rigor:v1:param: <name> <refinement>`. The parameter name is a Ruby identifier (Symbol); the
|
|
446
|
+
# type is any `Rigor::Type` the refinement parser resolves (bare kebab-case name, parameterised form, or
|
|
447
|
+
# `int<...>` range — the same grammar the `return:` directive accepts).
|
|
508
448
|
ParamOverride = Data.define(:param_name, :type)
|
|
509
449
|
|
|
510
|
-
# Reads every `rigor:v1:param: <name> <refinement>`
|
|
511
|
-
#
|
|
512
|
-
#
|
|
513
|
-
#
|
|
514
|
-
# `param:` directive at all) are silently dropped — the
|
|
515
|
-
# call site keeps the RBS-declared parameter type for
|
|
516
|
-
# those parameters. The reader accepts a nil method
|
|
517
|
-
# definition so call sites can pass through optional
|
|
450
|
+
# Reads every `rigor:v1:param: <name> <refinement>` directive off `RBS::Definition::Method#annotations` and
|
|
451
|
+
# returns the resolved `ParamOverride` list. Annotations the parser cannot resolve (typo, unknown refinement,
|
|
452
|
+
# no `param:` directive at all) are silently dropped — the call site keeps the RBS-declared parameter type
|
|
453
|
+
# for those parameters. The reader accepts a nil method definition so call sites can pass through optional
|
|
518
454
|
# method lookups without a guard.
|
|
519
455
|
#
|
|
520
456
|
# Example annotation in an RBS file:
|
|
@@ -524,11 +460,9 @@ module Rigor
|
|
|
524
460
|
# def normalise: (::String id) -> String
|
|
525
461
|
# end
|
|
526
462
|
#
|
|
527
|
-
# The RBS-declared type of `id` is `String`. The override
|
|
528
|
-
#
|
|
529
|
-
#
|
|
530
|
-
# is flagged as an argument-type mismatch at the call
|
|
531
|
-
# site.
|
|
463
|
+
# The RBS-declared type of `id` is `String`. The override tightens it to `non-empty-string` for
|
|
464
|
+
# argument-check purposes; passing a too-wide `Nominal[String]` argument is flagged as an argument-type
|
|
465
|
+
# mismatch at the call site.
|
|
532
466
|
def read_param_type_overrides(method_def, environment: nil)
|
|
533
467
|
return [] if method_def.nil?
|
|
534
468
|
|
|
@@ -548,23 +482,18 @@ module Rigor
|
|
|
548
482
|
end
|
|
549
483
|
end
|
|
550
484
|
|
|
551
|
-
# Convenience reader for call sites that want to look up
|
|
552
|
-
#
|
|
553
|
-
#
|
|
554
|
-
# RBS-declared type". Callers MUST treat the hash as
|
|
555
|
-
# read-only.
|
|
485
|
+
# Convenience reader for call sites that want to look up a single override by parameter name. Returns a
|
|
486
|
+
# frozen Hash<Symbol, Rigor::Type>; missing keys mean "use the RBS-declared type". Callers MUST treat the
|
|
487
|
+
# hash as read-only.
|
|
556
488
|
def param_type_override_map(method_def, environment: nil)
|
|
557
489
|
read_param_type_overrides(method_def, environment: environment)
|
|
558
490
|
.to_h { |o| [o.param_name, o.type] }
|
|
559
491
|
.freeze
|
|
560
492
|
end
|
|
561
493
|
|
|
562
|
-
# The `is` glue word is optional so authors can write
|
|
563
|
-
#
|
|
564
|
-
# the
|
|
565
|
-
# the terser `param: id non-empty-string`. The trailing
|
|
566
|
-
# payload accepts the full refinement grammar in
|
|
567
|
-
# `Builtins::ImportedRefinements::Parser`.
|
|
494
|
+
# The `is` glue word is optional so authors can write either `param: id is non-empty-string` (consistent with
|
|
495
|
+
# the existing `assert` / `predicate-if-*` directives) or the terser `param: id non-empty-string`. The
|
|
496
|
+
# trailing payload accepts the full refinement grammar in `Builtins::ImportedRefinements::Parser`.
|
|
568
497
|
PARAM_DIRECTIVE_PATTERN = /
|
|
569
498
|
\A
|
|
570
499
|
rigor:v1:param:
|
|
@@ -596,20 +525,14 @@ module Rigor
|
|
|
596
525
|
ParamOverride.new(param_name: match[:param].to_sym, type: type)
|
|
597
526
|
end
|
|
598
527
|
|
|
599
|
-
# A class- / module-level directive declaring that the
|
|
600
|
-
#
|
|
601
|
-
#
|
|
602
|
-
# `
|
|
603
|
-
#
|
|
604
|
-
# above, this attaches to a `class` / `module` declaration and
|
|
605
|
-
# names a single RBS interface (`_RewindableStream`); the
|
|
606
|
-
# right-hand side is therefore an interface name (its last
|
|
607
|
-
# segment begins with `_`), never a refinement payload.
|
|
528
|
+
# A class- / module-level directive declaring that the annotated class satisfies a named structural interface
|
|
529
|
+
# as part of its public contract (spec: `docs/type-specification/rbs-extended.md` § "Explicit conformance
|
|
530
|
+
# directive"). Unlike the per-method directives above, this attaches to a `class` / `module` declaration and
|
|
531
|
+
# names a single RBS interface (`_RewindableStream`); the right-hand side is therefore an interface name (its
|
|
532
|
+
# last segment begins with `_`), never a refinement payload.
|
|
608
533
|
#
|
|
609
|
-
# This parser only extracts the interface name; the
|
|
610
|
-
#
|
|
611
|
-
# {Rigor::RbsExtended::ConformanceChecker}, which the
|
|
612
|
-
# {Rigor::Analysis::Runner} runs once per project run.
|
|
534
|
+
# This parser only extracts the interface name; the conformance check itself lives in
|
|
535
|
+
# {Rigor::RbsExtended::ConformanceChecker}, which the {Rigor::Analysis::Runner} runs once per project run.
|
|
613
536
|
CONFORMS_TO_DIRECTIVE_PATTERN = /
|
|
614
537
|
\A
|
|
615
538
|
rigor:v1:conforms-to
|
|
@@ -620,12 +543,10 @@ module Rigor
|
|
|
620
543
|
/x
|
|
621
544
|
private_constant :CONFORMS_TO_DIRECTIVE_PATTERN
|
|
622
545
|
|
|
623
|
-
# Returns the interface name (leading `::` stripped) for a
|
|
624
|
-
# `
|
|
625
|
-
#
|
|
626
|
-
#
|
|
627
|
-
# returned verbatim otherwise — namespace resolution happens at
|
|
628
|
-
# the loader boundary when the interface is built.
|
|
546
|
+
# Returns the interface name (leading `::` stripped) for a `rigor:v1:conforms-to <Interface>` annotation, or
|
|
547
|
+
# `nil` when the string is not a conforms-to directive (so callers can walk an annotation list without
|
|
548
|
+
# pre-filtering). The name is returned verbatim otherwise — namespace resolution happens at the loader
|
|
549
|
+
# boundary when the interface is built.
|
|
629
550
|
def parse_conforms_to_annotation(string)
|
|
630
551
|
return nil if string.nil?
|
|
631
552
|
|
|
@@ -635,11 +556,9 @@ module Rigor
|
|
|
635
556
|
match[:interface].to_s.sub(/\A::/, "")
|
|
636
557
|
end
|
|
637
558
|
|
|
638
|
-
# The shared {Rigor::FlowContribution::Provenance} for every
|
|
639
|
-
#
|
|
640
|
-
#
|
|
641
|
-
# plugin contribution merger) can attribute facts back to the
|
|
642
|
-
# RBS::Extended layer.
|
|
559
|
+
# The shared {Rigor::FlowContribution::Provenance} for every bundle this module produces.
|
|
560
|
+
# `source_family: :rbs_extended` so consumers (today the documentation surface; v0.1.0 the plugin contribution
|
|
561
|
+
# merger) can attribute facts back to the RBS::Extended layer.
|
|
643
562
|
RBS_EXTENDED_PROVENANCE = FlowContribution::Provenance.new(
|
|
644
563
|
source_family: :rbs_extended,
|
|
645
564
|
plugin_id: nil,
|
|
@@ -647,10 +566,8 @@ module Rigor
|
|
|
647
566
|
descriptor: nil
|
|
648
567
|
).freeze
|
|
649
568
|
|
|
650
|
-
# Rolls up every recognised RBS::Extended directive on
|
|
651
|
-
#
|
|
652
|
-
# the canonical {Rigor::FlowContribution::Fact} payload (see
|
|
653
|
-
# ADR-7 § "Slice 4-A"):
|
|
569
|
+
# Rolls up every recognised RBS::Extended directive on `method_def` into a single {Rigor::FlowContribution}
|
|
570
|
+
# with the canonical {Rigor::FlowContribution::Fact} payload (see ADR-7 § "Slice 4-A"):
|
|
654
571
|
#
|
|
655
572
|
# - `predicate-if-true` → `truthy_facts`
|
|
656
573
|
# - `predicate-if-false` → `falsey_facts`
|
|
@@ -659,18 +576,14 @@ module Rigor
|
|
|
659
576
|
# - `assert-if-false` → `falsey_facts`
|
|
660
577
|
# - `return:` override → `return_type` (`Rigor::Type`)
|
|
661
578
|
#
|
|
662
|
-
# Param overrides are intentionally NOT included — they refine
|
|
663
|
-
#
|
|
664
|
-
#
|
|
665
|
-
# Callers that care about parameter contracts keep using
|
|
666
|
-
# {.read_param_type_overrides} / {.param_type_override_map}.
|
|
579
|
+
# Param overrides are intentionally NOT included — they refine the call's signature contract rather than its
|
|
580
|
+
# flow facts and do not fit ADR-2 § "Flow Contribution Bundle" slot semantics. Callers that care about
|
|
581
|
+
# parameter contracts keep using {.read_param_type_overrides} / {.param_type_override_map}.
|
|
667
582
|
#
|
|
668
|
-
# Returns `nil` when the method carries no recognised
|
|
669
|
-
#
|
|
670
|
-
# without iterating an empty bundle).
|
|
583
|
+
# Returns `nil` when the method carries no recognised contribution directives (callers can skip the merge
|
|
584
|
+
# step without iterating an empty bundle).
|
|
671
585
|
#
|
|
672
|
-
# See {.read_predicate_effects} for the `environment:`
|
|
673
|
-
# keyword contract.
|
|
586
|
+
# See {.read_predicate_effects} for the `environment:` keyword contract.
|
|
674
587
|
def read_flow_contribution(method_def, environment: nil)
|
|
675
588
|
return nil if method_def.nil?
|
|
676
589
|
|
|
@@ -708,12 +621,9 @@ module Rigor
|
|
|
708
621
|
facts.empty? ? nil : facts
|
|
709
622
|
end
|
|
710
623
|
|
|
711
|
-
# ADR-13 slice 3b — guards every reporter call so the
|
|
712
|
-
#
|
|
713
|
-
#
|
|
714
|
-
# reporter is nil (the v0.1.0 → v0.1.3 default for call
|
|
715
|
-
# sites that do not yet thread `environment:`), the call is
|
|
716
|
-
# a no-op and the parser stays fail-soft.
|
|
624
|
+
# ADR-13 slice 3b — guards every reporter call so the in-RbsExtended-module call sites can record events
|
|
625
|
+
# uniformly without nil-checking each time. When the reporter is nil (the v0.1.0 → v0.1.3 default for call
|
|
626
|
+
# sites that do not yet thread `environment:`), the call is a no-op and the parser stays fail-soft.
|
|
717
627
|
def record_unresolved(reporter, payload, source_location)
|
|
718
628
|
return if reporter.nil?
|
|
719
629
|
|