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
|
@@ -4,15 +4,12 @@ require "prism"
|
|
|
4
4
|
|
|
5
5
|
module Rigor
|
|
6
6
|
module Plugin
|
|
7
|
-
# ADR-37 slice 1d — the lexical context of a node, handed to a
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
# class / module, method, and block-DSL nesting that a per-node rule
|
|
11
|
-
# needs but that `Scope` (value/type facts) does not carry.
|
|
7
|
+
# ADR-37 slice 1d — the lexical context of a node, handed to a {Base.node_rule} block as its fifth argument.
|
|
8
|
+
# Realises the `ContextInfo` ADR-2 § "Scope Object" promised: the enclosing class / module, method, and
|
|
9
|
+
# block-DSL nesting that a per-node rule needs but that `Scope` (value/type facts) does not carry.
|
|
12
10
|
#
|
|
13
|
-
# The engine builds one per matching node from the descent stack
|
|
14
|
-
#
|
|
15
|
-
# need:
|
|
11
|
+
# The engine builds one per matching node from the descent stack (snapshotted, so it is safe to retain).
|
|
12
|
+
# Rules read the bits they need:
|
|
16
13
|
#
|
|
17
14
|
# node_rule Prism::CallNode do |node, _scope, path, _fc, context|
|
|
18
15
|
# action = context.enclosing_def&.name # rails-i18n
|
|
@@ -20,9 +17,8 @@ module Rigor
|
|
|
20
17
|
# …
|
|
21
18
|
# end
|
|
22
19
|
#
|
|
23
|
-
# `ancestors` is the full chain, outermost first, EXCLUDING the node
|
|
24
|
-
#
|
|
25
|
-
# conveniences derived from it.
|
|
20
|
+
# `ancestors` is the full chain, outermost first, EXCLUDING the node itself — the general primitive; the
|
|
21
|
+
# accessors below are conveniences derived from it.
|
|
26
22
|
class NodeContext
|
|
27
23
|
EMPTY = nil # sentinel documented for readers; rules get a real instance
|
|
28
24
|
|
|
@@ -33,25 +29,21 @@ module Rigor
|
|
|
33
29
|
freeze
|
|
34
30
|
end
|
|
35
31
|
|
|
36
|
-
# The innermost enclosing `Prism::DefNode`, or nil. Its `#name`
|
|
37
|
-
#
|
|
38
|
-
# lazy `t('.key')` against the controller action).
|
|
32
|
+
# The innermost enclosing `Prism::DefNode`, or nil. Its `#name` is the method the node sits in (rails-i18n
|
|
33
|
+
# uses it to expand a lazy `t('.key')` against the controller action).
|
|
39
34
|
def enclosing_def
|
|
40
35
|
ancestors.rfind { |n| n.is_a?(Prism::DefNode) }
|
|
41
36
|
end
|
|
42
37
|
|
|
43
|
-
# The innermost enclosing `Prism::ClassNode` / `Prism::ModuleNode`,
|
|
44
|
-
#
|
|
45
|
-
# `before_action` / `render` sits in).
|
|
38
|
+
# The innermost enclosing `Prism::ClassNode` / `Prism::ModuleNode`, or nil (actionpack uses it to resolve
|
|
39
|
+
# the controller a `before_action` / `render` sits in).
|
|
46
40
|
def enclosing_module
|
|
47
41
|
ancestors.rfind { |n| n.is_a?(Prism::ClassNode) || n.is_a?(Prism::ModuleNode) }
|
|
48
42
|
end
|
|
49
43
|
|
|
50
|
-
# The innermost enclosing `Prism::CallNode` that carries a block
|
|
51
|
-
#
|
|
52
|
-
#
|
|
53
|
-
# Returns the CallNode (so the caller can read its arguments /
|
|
54
|
-
# receiver), or nil.
|
|
44
|
+
# The innermost enclosing `Prism::CallNode` that carries a block and whose method name is `method_name` —
|
|
45
|
+
# e.g. the `RSpec.describe(Model) do … end` a shoulda matcher sits in. Returns the CallNode (so the caller
|
|
46
|
+
# can read its arguments / receiver), or nil.
|
|
55
47
|
def enclosing_block(method_name)
|
|
56
48
|
ancestors.rfind do |n|
|
|
57
49
|
n.is_a?(Prism::CallNode) && n.block && n.name == method_name
|
|
@@ -8,48 +8,36 @@ module Rigor
|
|
|
8
8
|
module Plugin
|
|
9
9
|
# ADR-52 WD4 — one engine-owned AST walk per file for node rules.
|
|
10
10
|
#
|
|
11
|
-
# Before this, every plugin that declared a {Base.node_rule} walked
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# single walk that dispatches each visited node to every matching
|
|
16
|
-
# `(plugin, rule)` pair.
|
|
11
|
+
# Before this, every plugin that declared a {Base.node_rule} walked the file's AST itself
|
|
12
|
+
# (`Base#node_rule_diagnostics` → `Source::NodeWalker.each_with_ancestors`), so a project with N node-rule
|
|
13
|
+
# plugins paid N walks per file. This folds them into a single walk that dispatches each visited node to
|
|
14
|
+
# every matching `(plugin, rule)` pair.
|
|
17
15
|
#
|
|
18
|
-
# Behaviour is preserved exactly so the diagnostics stay
|
|
19
|
-
# byte-identical (the WD6 gate):
|
|
16
|
+
# Behaviour is preserved exactly so the diagnostics stay byte-identical (the WD6 gate):
|
|
20
17
|
#
|
|
21
|
-
# * Each plugin's `node_file_context` block runs once per file,
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
# *
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
# *
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
# per-plugin rescue around the old `#node_rule_diagnostics` call.
|
|
34
|
-
# * Diagnostics are bucketed per plugin and returned in the
|
|
35
|
-
# registry order the runner already iterates, so emission order is
|
|
36
|
-
# unchanged (plugin-major, not node-major) — order preservation is
|
|
37
|
-
# what keeps the gate byte-identical in this slice.
|
|
18
|
+
# * Each plugin's `node_file_context` block runs once per file, before any of its rules fire,
|
|
19
|
+
# `instance_exec`'d on that plugin — same as the per-plugin walk.
|
|
20
|
+
# * One frozen {NodeContext} is built per node, lazily, only when at least one rule matches it. Because it
|
|
21
|
+
# wraps only the ancestors it is safe to share across plugins for the same node.
|
|
22
|
+
# * Each rule block is `instance_exec`'d on its own plugin instance with the same five arguments `(node,
|
|
23
|
+
# scope, path, file_context, context)`.
|
|
24
|
+
# * A plugin whose context block or any rule block raises has its whole node-rule contribution isolated —
|
|
25
|
+
# the walk records the error against that plugin and continues, matching the runner's per-plugin rescue
|
|
26
|
+
# around the old `#node_rule_diagnostics` call.
|
|
27
|
+
# * Diagnostics are bucketed per plugin and returned in the registry order the runner already iterates,
|
|
28
|
+
# so emission order is unchanged (plugin-major, not node-major) — order preservation is what keeps the
|
|
29
|
+
# gate byte-identical in this slice.
|
|
38
30
|
#
|
|
39
|
-
# The result is an ordered Array of {Result}, one per node-rule
|
|
40
|
-
# plugin
|
|
41
|
-
#
|
|
42
|
-
# `#diagnostics` is empty; the runner turns the error into the same
|
|
43
|
-
# per-plugin `runtime-error` envelope it produced before.
|
|
31
|
+
# The result is an ordered Array of {Result}, one per node-rule plugin (registry order). `Result#error` is
|
|
32
|
+
# non-nil iff that plugin's context or a rule block raised, in which case `#diagnostics` is empty; the
|
|
33
|
+
# runner turns the error into the same per-plugin `runtime-error` envelope it produced before.
|
|
44
34
|
class NodeRuleWalk
|
|
45
|
-
# One plugin's node-rule outcome for a single file. `error` is the
|
|
46
|
-
#
|
|
47
|
-
# (nil on success); when set, `diagnostics` is empty.
|
|
35
|
+
# One plugin's node-rule outcome for a single file. `error` is the exception raised by the plugin's
|
|
36
|
+
# context block or a rule block (nil on success); when set, `diagnostics` is empty.
|
|
48
37
|
Result = Struct.new(:plugin, :diagnostics, :error)
|
|
49
38
|
|
|
50
|
-
# Plugins that declare at least one `node_rule`, paired with their
|
|
51
|
-
#
|
|
52
|
-
# reused for every file.
|
|
39
|
+
# Plugins that declare at least one `node_rule`, paired with their frozen rule list, in registry order.
|
|
40
|
+
# Built once per run and reused for every file.
|
|
53
41
|
def initialize(plugins)
|
|
54
42
|
@entries = plugins.filter_map do |plugin|
|
|
55
43
|
rules = plugin.class.node_rules
|
|
@@ -62,28 +50,20 @@ module Rigor
|
|
|
62
50
|
@entries.empty?
|
|
63
51
|
end
|
|
64
52
|
|
|
65
|
-
# Walk `root` once, dispatching every node to each matching
|
|
66
|
-
#
|
|
67
|
-
# (registry) order. `root` nil yields one empty Result per plugin.
|
|
53
|
+
# Walk `root` once, dispatching every node to each matching `(plugin, rule)`. Returns an Array of
|
|
54
|
+
# {Result} in plugin (registry) order. `root` nil yields one empty Result per plugin.
|
|
68
55
|
#
|
|
69
|
-
# ADR-53 B4 — when `collector_driver` is given (an
|
|
70
|
-
# {
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
# rules
|
|
74
|
-
# (
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
# preserved because each side accumulates into its own bucket
|
|
81
|
-
# (per-plugin {Result}s / per-collector `results`) and the two are
|
|
82
|
-
# assembled separately by their respective diagnostic builders.
|
|
83
|
-
# A raising plugin rule isolates only that plugin (per-{State}
|
|
84
|
-
# rescue) and never aborts built-in collection, nor vice versa
|
|
85
|
-
# (the collectors' `visit` is the verbatim legacy gather logic,
|
|
86
|
-
# which does not raise on the corpora).
|
|
56
|
+
# ADR-53 B4 — when `collector_driver` is given (an {Analysis::CheckRules::RuleWalk::CollectorDriver}),
|
|
57
|
+
# the SAME single traversal also drives the built-in {CheckRules} node collectors: each visited node is
|
|
58
|
+
# dispatched both to the plugin rules (this walk's original job) and to the built-in collectors (the
|
|
59
|
+
# `CollectorDriver`), so a file is walked once for both instead of once each. The two dispatch models
|
|
60
|
+
# coexist: plugin rules keep `is_a?` matching via the per-class memo and receive a lazily-built
|
|
61
|
+
# {NodeContext} (ancestors); built-in collectors keep exact-node-class dispatch and receive the
|
|
62
|
+
# immutable {RuleWalk::Context} threaded through the descent. Order is preserved because each side
|
|
63
|
+
# accumulates into its own bucket (per-plugin {Result}s / per-collector `results`) and the two are
|
|
64
|
+
# assembled separately by their respective diagnostic builders. A raising plugin rule isolates only that
|
|
65
|
+
# plugin (per-{State} rescue) and never aborts built-in collection, nor vice versa (the collectors'
|
|
66
|
+
# `visit` is the verbatim legacy gather logic, which does not raise on the corpora).
|
|
87
67
|
def diagnostics_for_file(path:, scope:, root:, collector_driver: nil)
|
|
88
68
|
return @entries.map { |plugin, _| Result.new(plugin, [], nil) } if root.nil?
|
|
89
69
|
|
|
@@ -99,14 +79,11 @@ module Rigor
|
|
|
99
79
|
walk_node(root, [], context, path, scope, states, collector_driver)
|
|
100
80
|
end
|
|
101
81
|
|
|
102
|
-
# The single converged DFS pre-order traversal. Threads both the
|
|
103
|
-
#
|
|
104
|
-
#
|
|
105
|
-
#
|
|
106
|
-
#
|
|
107
|
-
# `compact_child_nodes` to both the legacy
|
|
108
|
-
# `Source::NodeWalker.each_with_ancestors` and `RuleWalk.walk`, so
|
|
109
|
-
# every node is visited in the same order each side saw before.
|
|
82
|
+
# The single converged DFS pre-order traversal. Threads both the live `ancestors` stack (for plugin
|
|
83
|
+
# {NodeContext}) and the immutable built-in {RuleWalk::Context} (for the collectors), derived together
|
|
84
|
+
# as the walk descends — the cheap-ancestors option from the ADR-53 B4 design note. Identical pre-order
|
|
85
|
+
# over `compact_child_nodes` to both the legacy `Source::NodeWalker.each_with_ancestors` and
|
|
86
|
+
# `RuleWalk.walk`, so every node is visited in the same order each side saw before.
|
|
110
87
|
def walk_node(node, ancestors, context, path, scope, states, collector_driver)
|
|
111
88
|
return unless node.is_a?(Prism::Node)
|
|
112
89
|
|
|
@@ -129,16 +106,15 @@ module Rigor
|
|
|
129
106
|
matched = state.rules_for(node)
|
|
130
107
|
next if matched.empty?
|
|
131
108
|
|
|
132
|
-
# One frozen NodeContext per node, built lazily and shared
|
|
133
|
-
#
|
|
109
|
+
# One frozen NodeContext per node, built lazily and shared across every plugin that matches this
|
|
110
|
+
# node.
|
|
134
111
|
node_context ||= NodeContext.new(ancestors)
|
|
135
112
|
state.run_rules(matched, node, scope, path, node_context)
|
|
136
113
|
end
|
|
137
114
|
end
|
|
138
115
|
|
|
139
|
-
# Mutable per-(plugin, file) walk state. Kept private to the walk —
|
|
140
|
-
#
|
|
141
|
-
# class match memo, and the isolation flag.
|
|
116
|
+
# Mutable per-(plugin, file) walk state. Kept private to the walk — holds the diagnostics bucket, the
|
|
117
|
+
# file context, the per-concrete-class match memo, and the isolation flag.
|
|
142
118
|
class State
|
|
143
119
|
def initialize(plugin, rules, scope, root)
|
|
144
120
|
@plugin = plugin
|
|
@@ -153,10 +129,9 @@ module Rigor
|
|
|
153
129
|
!@error.nil?
|
|
154
130
|
end
|
|
155
131
|
|
|
156
|
-
# Rules whose `node_type` this concrete node satisfies, memoised
|
|
157
|
-
#
|
|
158
|
-
#
|
|
159
|
-
# superclass of the concrete node.
|
|
132
|
+
# Rules whose `node_type` this concrete node satisfies, memoised by the node's class so the `is_a?`
|
|
133
|
+
# scan runs once per class. Preserves `is_a?` semantics when a rule's `node_type` is a superclass of
|
|
134
|
+
# the concrete node.
|
|
160
135
|
def rules_for(node)
|
|
161
136
|
@match_cache[node.class] ||=
|
|
162
137
|
@rules.select { |rule| node.is_a?(rule[:node_type]) }
|
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Rigor
|
|
4
4
|
module Plugin
|
|
5
|
-
# ADR-28 declaration: "every instance/singleton method named
|
|
6
|
-
# `
|
|
7
|
-
# is implicitly required to satisfy the declared parameter +
|
|
8
|
-
# return-type protocol."
|
|
5
|
+
# ADR-28 declaration: "every instance/singleton method named `method_name`, defined in a source file
|
|
6
|
+
# matching `path_glob`, is implicitly required to satisfy the declared parameter + return-type protocol."
|
|
9
7
|
#
|
|
10
8
|
# Authored on a plugin manifest:
|
|
11
9
|
#
|
|
@@ -22,49 +20,38 @@ module Rigor
|
|
|
22
20
|
# ]
|
|
23
21
|
# )
|
|
24
22
|
#
|
|
25
|
-
# The contract drives two distinct engine behaviours (ADR-28
|
|
26
|
-
# § "provide-and-check"):
|
|
23
|
+
# The contract drives two distinct engine behaviours (ADR-28 § "provide-and-check"):
|
|
27
24
|
#
|
|
28
|
-
# - **provide** — when the inference engine binds the parameter
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
# - **check** — the contributing plugin's `#diagnostics_for_file`
|
|
34
|
-
# hook confirms the method exists and its inferred return type
|
|
35
|
-
# conforms to `return_type_name`.
|
|
25
|
+
# - **provide** — when the inference engine binds the parameter list of a matching `def`,
|
|
26
|
+
# {Rigor::Inference::MethodParameterBinder} substitutes the declared `param_types` for the usual
|
|
27
|
+
# `Dynamic[Top]` fallback, so the method body is analysed as if the parameter carried its protocol type.
|
|
28
|
+
# - **check** — the contributing plugin's `#diagnostics_for_file` hook confirms the method exists and its
|
|
29
|
+
# inferred return type conforms to `return_type_name`.
|
|
36
30
|
#
|
|
37
31
|
# ## Fields
|
|
38
32
|
#
|
|
39
|
-
# - `path_glob` — `File.fnmatch` glob (String) selecting the
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
# - `
|
|
43
|
-
#
|
|
44
|
-
# - `
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
# environment construction order.
|
|
51
|
-
# - `return_type_name` — fully-qualified type name (String) the
|
|
52
|
-
# method's inferred return type must conform to.
|
|
53
|
-
# - `severity` — Symbol diagnostic severity for contract
|
|
54
|
-
# violations (`:error` default).
|
|
33
|
+
# - `path_glob` — `File.fnmatch` glob (String) selecting the source files the contract applies to,
|
|
34
|
+
# relative to the analysed project root (e.g. `"lib/controller/**/*.rb"`).
|
|
35
|
+
# - `method_name` — Symbol; the instance (or singleton) method the contract constrains.
|
|
36
|
+
# - `singleton` — Boolean; `true` constrains `def self.<name>`, `false` (default) constrains instance
|
|
37
|
+
# methods.
|
|
38
|
+
# - `param_types` — Array of `ParamType` (positional index → fully-qualified type name). The type names
|
|
39
|
+
# resolve against the analysed project's environment lazily, at consumption time, so the contract value
|
|
40
|
+
# object stays independent of environment construction order.
|
|
41
|
+
# - `return_type_name` — fully-qualified type name (String) the method's inferred return type must
|
|
42
|
+
# conform to.
|
|
43
|
+
# - `severity` — Symbol diagnostic severity for contract violations (`:error` default).
|
|
55
44
|
#
|
|
56
45
|
# ## Ractor-shareability
|
|
57
46
|
#
|
|
58
|
-
# Every field is frozen at construction (ADR-15 Phase 1); the
|
|
59
|
-
#
|
|
60
|
-
# returns true after `#initialize`, so the contract survives
|
|
47
|
+
# Every field is frozen at construction (ADR-15 Phase 1); the nested `ParamType` is a frozen `Data`.
|
|
48
|
+
# `Ractor.shareable?` returns true after `#initialize`, so the contract survives
|
|
61
49
|
# `Plugin::Registry.materialize` into a worker Ractor.
|
|
62
50
|
class ProtocolContract
|
|
63
51
|
VALID_SEVERITIES = %i[error warning info].freeze
|
|
64
52
|
|
|
65
|
-
# One positional-parameter provision: the zero-based index of
|
|
66
|
-
#
|
|
67
|
-
# carries under the protocol.
|
|
53
|
+
# One positional-parameter provision: the zero-based index of the parameter and the fully-qualified
|
|
54
|
+
# name of the type it carries under the protocol.
|
|
68
55
|
ParamType = Data.define(:index, :type_name)
|
|
69
56
|
|
|
70
57
|
attr_reader :path_glob, :method_name, :singleton, :param_types, :return_type_name, :severity
|
|
@@ -85,9 +72,8 @@ module Rigor
|
|
|
85
72
|
freeze
|
|
86
73
|
end
|
|
87
74
|
|
|
88
|
-
# Returns a copy with `path_glob` replaced. Plugins use this to
|
|
89
|
-
#
|
|
90
|
-
# without rebuilding the whole contract by hand.
|
|
75
|
+
# Returns a copy with `path_glob` replaced. Plugins use this to honour a per-project config override of
|
|
76
|
+
# the convention path without rebuilding the whole contract by hand.
|
|
91
77
|
def with_path_glob(glob)
|
|
92
78
|
ProtocolContract.new(
|
|
93
79
|
path_glob: glob,
|