rigortype 0.2.7 → 0.2.9
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/data/core_overlay/csv.rbs +28 -0
- data/data/core_overlay/psych.rbs +22 -0
- data/docs/handbook/01-getting-started.md +9 -1
- data/docs/handbook/02-everyday-types.md +4 -1
- data/docs/handbook/08-understanding-errors.md +3 -3
- data/docs/manual/01-installation.md +1 -0
- data/docs/manual/02-cli-reference.md +16 -7
- data/docs/manual/04-diagnostics.md +7 -4
- data/docs/manual/06-baseline.md +5 -2
- data/docs/manual/07-plugins.md +1 -1
- data/docs/manual/14-rails-quickstart.md +4 -2
- data/docs/manual/15-type-protection-coverage.md +27 -4
- data/docs/manual/plugins/rigor-actionpack.md +1 -1
- data/docs/manual/plugins/rigor-activerecord.md +12 -5
- data/docs/manual/plugins/rigor-rails-routes.md +11 -0
- 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 +248 -186
- 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 +62 -48
- 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 +46 -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_fork_scan.rb +55 -0
- data/lib/rigor/cli/protection_renderer.rb +5 -7
- data/lib/rigor/cli/protection_report.rb +34 -18
- 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/missing_gem_constant_index.rb +128 -0
- 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 +225 -304
- 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 +794 -1154
- 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/fork_map.rb +87 -0
- 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 +627 -727
- data/lib/rigor/inference/origin_lookup.rb +38 -0
- data/lib/rigor/inference/parameter_inference_collector.rb +154 -109
- 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 -821
- data/lib/rigor/inference/statement_evaluator.rb +754 -1114
- 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 +141 -184
- 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 +92 -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 +40 -48
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +140 -129
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +56 -59
- 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/structure_sql_parser.rb +172 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +168 -241
- 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-activesupport-core-ext/sig/active_support/core_ext.rbs +32 -0
- 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/grape_api_discoverer.rb +189 -0
- 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 +61 -75
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +319 -505
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +91 -96
- 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/environment.rbs +1 -0
- data/sig/rigor/scope.rbs +6 -0
- metadata +9 -1
|
@@ -6,16 +6,13 @@ require "rigor/source/literals"
|
|
|
6
6
|
module Rigor
|
|
7
7
|
module Plugin
|
|
8
8
|
class DrySchema < Rigor::Plugin::Base
|
|
9
|
-
# Walks project source for `Foo = Dry::Schema.{Params,JSON,define}
|
|
10
|
-
# {
|
|
11
|
-
#
|
|
12
|
-
# table covering each schema's typed-key surface.
|
|
9
|
+
# Walks project source for `Foo = Dry::Schema.{Params,JSON,define} { ... }` shapes and emits a
|
|
10
|
+
# `{schema_const_fqn => {required: {key => underlying_class}, optional: {…}}}` table covering each
|
|
11
|
+
# schema's typed-key surface.
|
|
13
12
|
module SchemaScanner
|
|
14
|
-
# The dry-schema canonical-type symbols accepted as
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
# uses for `CANONICAL_ALIASES`, intersected with what
|
|
18
|
-
# dry-schema's predicate engine accepts).
|
|
13
|
+
# The dry-schema canonical-type symbols accepted as predicate arguments. Maps each to the
|
|
14
|
+
# underlying Ruby class name (the same vocabulary `rigor-dry-types` uses for `CANONICAL_ALIASES`,
|
|
15
|
+
# intersected with what dry-schema's predicate engine accepts).
|
|
19
16
|
CANONICAL_TYPES = {
|
|
20
17
|
string: "String",
|
|
21
18
|
integer: "Integer",
|
|
@@ -30,12 +27,10 @@ module Rigor
|
|
|
30
27
|
array: "Array"
|
|
31
28
|
}.tap { |h| h[:nil] = "NilClass" }.freeze
|
|
32
29
|
|
|
33
|
-
# The dry-schema predicate verbs that accept a type
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
# element type) but for Rigor's purposes they all
|
|
38
|
-
# contribute the same underlying class for the key.
|
|
30
|
+
# The dry-schema predicate verbs that accept a type argument. Each verb has a slightly different
|
|
31
|
+
# runtime semantic (`filled` = present + non-empty; `value` = present; `maybe` = present-or-nil;
|
|
32
|
+
# `each` = collection element type) but for Rigor's purposes they all contribute the same
|
|
33
|
+
# underlying class for the key.
|
|
39
34
|
TYPE_BEARING_PREDICATES = %i[filled value maybe each].to_set.freeze
|
|
40
35
|
private_constant :TYPE_BEARING_PREDICATES
|
|
41
36
|
|
|
@@ -45,17 +40,12 @@ module Rigor
|
|
|
45
40
|
|
|
46
41
|
module_function
|
|
47
42
|
|
|
48
|
-
# @param paths [Array<String>] absolute paths to `.rb`
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
# underlying class. Empty when the plugin isn't
|
|
55
|
-
# loaded.
|
|
56
|
-
# @return [Hash{String => Hash{Symbol => Hash{Symbol => String}}}]
|
|
57
|
-
# frozen per-schema typed-key table. Empty when no
|
|
58
|
-
# recognisable schema declaration is found.
|
|
43
|
+
# @param paths [Array<String>] absolute paths to `.rb` files the project's `paths:` resolves to.
|
|
44
|
+
# @param type_aliases [Hash{String => String}] the ADR-9 `:dry_type_aliases` fact published by
|
|
45
|
+
# `rigor-dry-types` when loaded. Used to resolve `value(Types::Email)` references to their
|
|
46
|
+
# underlying class. Empty when the plugin isn't loaded.
|
|
47
|
+
# @return [Hash{String => Hash{Symbol => Hash{Symbol => String}}}] frozen per-schema typed-key
|
|
48
|
+
# table. Empty when no recognisable schema declaration is found.
|
|
59
49
|
def scan(paths:, type_aliases: {})
|
|
60
50
|
table = {}
|
|
61
51
|
paths.each do |path|
|
|
@@ -77,11 +67,9 @@ module Rigor
|
|
|
77
67
|
end
|
|
78
68
|
private_class_method :scan_file
|
|
79
69
|
|
|
80
|
-
# Walks the AST collecting `<Const> = Dry::Schema.X { ... }`
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
# Dry::Schema.Params { ... }; end` registers as
|
|
84
|
-
# `"Foo::SCHEMA"`.
|
|
70
|
+
# Walks the AST collecting `<Const> = Dry::Schema.X { ... }` assignments at any nesting level.
|
|
71
|
+
# Tracks the enclosing constant chain so a class-level `class Foo; SCHEMA = Dry::Schema.Params
|
|
72
|
+
# { ... }; end` registers as `"Foo::SCHEMA"`.
|
|
85
73
|
def collect_schemas(node, qualified_prefix, type_aliases)
|
|
86
74
|
return {} if node.nil?
|
|
87
75
|
|
|
@@ -119,8 +107,7 @@ module Rigor
|
|
|
119
107
|
end
|
|
120
108
|
private_class_method :collect_schema_assignment
|
|
121
109
|
|
|
122
|
-
# Matches `Dry::Schema.Params { ... }` /
|
|
123
|
-
# `Dry::Schema.JSON { ... }` / `Dry::Schema.define { ... }`.
|
|
110
|
+
# Matches `Dry::Schema.Params { ... }` / `Dry::Schema.JSON { ... }` / `Dry::Schema.define { ... }`.
|
|
124
111
|
def schema_entry_call?(node)
|
|
125
112
|
return false unless node.is_a?(Prism::CallNode)
|
|
126
113
|
return false unless SCHEMA_ENTRY_NAMES.include?(node.name)
|
|
@@ -147,10 +134,9 @@ module Rigor
|
|
|
147
134
|
end
|
|
148
135
|
private_class_method :collect_schema_shape
|
|
149
136
|
|
|
150
|
-
# Walks every top-level `required(:key).<predicate>(...)` /
|
|
151
|
-
#
|
|
152
|
-
#
|
|
153
|
-
# (multi-statement) or a single expression node.
|
|
137
|
+
# Walks every top-level `required(:key).<predicate>(...)` / `optional(:key).<predicate>(...)`
|
|
138
|
+
# chain in the block body. The block's body is either a `Prism::StatementsNode` (multi-statement)
|
|
139
|
+
# or a single expression node.
|
|
154
140
|
def walk_block_body(block_node, &)
|
|
155
141
|
body = block_node.body
|
|
156
142
|
return if body.nil?
|
|
@@ -160,13 +146,10 @@ module Rigor
|
|
|
160
146
|
end
|
|
161
147
|
private_class_method :walk_block_body
|
|
162
148
|
|
|
163
|
-
# `required(:key).filled(:string)` parses as a CallNode
|
|
164
|
-
#
|
|
165
|
-
# chain
|
|
166
|
-
#
|
|
167
|
-
# `each(<Type>)` predicate yields a list-of-element
|
|
168
|
-
# type info (`{type: <T>, list: true}`); other type-bearing
|
|
169
|
-
# predicates (`filled`/`value`/`maybe`) yield scalar info
|
|
149
|
+
# `required(:key).filled(:string)` parses as a CallNode whose receiver is the `required(:key)`
|
|
150
|
+
# call. Walk the chain inward looking for the type-bearing predicate at the head; the key sits on
|
|
151
|
+
# the chain's tail. The `each(<Type>)` predicate yields a list-of-element type info (`{type: <T>,
|
|
152
|
+
# list: true}`); other type-bearing predicates (`filled`/`value`/`maybe`) yield scalar info
|
|
170
153
|
# (`{type: <T>, list: false}`).
|
|
171
154
|
def visit_chain(node, &block)
|
|
172
155
|
return unless node.is_a?(Prism::CallNode)
|
|
@@ -179,11 +162,9 @@ module Rigor
|
|
|
179
162
|
end
|
|
180
163
|
private_class_method :visit_chain
|
|
181
164
|
|
|
182
|
-
# `required(:key).filled(:string).value(...)...` — the
|
|
183
|
-
#
|
|
184
|
-
# `required
|
|
185
|
-
# `node.receiver` until we hit the `required` /
|
|
186
|
-
# `optional` call, recording the key + kind.
|
|
165
|
+
# `required(:key).filled(:string).value(...)...` — the OUTERMOST call's receiver chain ends in
|
|
166
|
+
# the `required(:key)` / `optional(:key)` call. Recurse on `node.receiver` until we hit the
|
|
167
|
+
# `required` / `optional` call, recording the key + kind.
|
|
187
168
|
def extract_key_and_kind(node)
|
|
188
169
|
current = node
|
|
189
170
|
while current.is_a?(Prism::CallNode)
|
|
@@ -199,11 +180,9 @@ module Rigor
|
|
|
199
180
|
end
|
|
200
181
|
private_class_method :extract_key_and_kind
|
|
201
182
|
|
|
202
|
-
# Walks the call chain finding the first type-bearing
|
|
203
|
-
#
|
|
204
|
-
#
|
|
205
|
-
# tuple (`each` is the only verb that produces a list)
|
|
206
|
-
# or nil when no recognisable type sits on the chain.
|
|
183
|
+
# Walks the call chain finding the first type-bearing predicate (`filled` / `value` / `maybe` /
|
|
184
|
+
# `each`) and extracts its argument type. Returns a `{type:, list:}` tuple (`each` is the only
|
|
185
|
+
# verb that produces a list) or nil when no recognisable type sits on the chain.
|
|
207
186
|
def walk_predicate_chain(node)
|
|
208
187
|
current = node
|
|
209
188
|
while current.is_a?(Prism::CallNode)
|
|
@@ -217,12 +196,10 @@ module Rigor
|
|
|
217
196
|
end
|
|
218
197
|
private_class_method :walk_predicate_chain
|
|
219
198
|
|
|
220
|
-
# Reads the first positional argument of a `filled(:string)`
|
|
221
|
-
#
|
|
222
|
-
#
|
|
223
|
-
#
|
|
224
|
-
# name for downstream type-alias resolution. Returns nil
|
|
225
|
-
# for anything else.
|
|
199
|
+
# Reads the first positional argument of a `filled(:string)` / `value(:integer)` /
|
|
200
|
+
# `maybe(Types::Email)` call. Returns either the canonical-type-symbol's underlying class
|
|
201
|
+
# ("String" / "Integer" / …), or the constant's qualified name for downstream type-alias
|
|
202
|
+
# resolution. Returns nil for anything else.
|
|
226
203
|
def extract_type_from_predicate(call_node)
|
|
227
204
|
arg = call_node.arguments&.arguments&.first
|
|
228
205
|
case arg
|
|
@@ -236,12 +213,10 @@ module Rigor
|
|
|
236
213
|
end
|
|
237
214
|
private_class_method :extract_type_from_predicate
|
|
238
215
|
|
|
239
|
-
# In-place: any value's `type:` slot in `bucket` that
|
|
240
|
-
#
|
|
241
|
-
#
|
|
242
|
-
#
|
|
243
|
-
# bucket (no fact contribution rather than misleading
|
|
244
|
-
# data). The `list:` slot rides along unchanged.
|
|
216
|
+
# In-place: any value's `type:` slot in `bucket` that doesn't already match a canonical class
|
|
217
|
+
# (e.g. `"Types::Email"`) gets resolved through the type_aliases fact. Unresolvable values drop
|
|
218
|
+
# from the bucket (no fact contribution rather than misleading data). The `list:` slot rides along
|
|
219
|
+
# unchanged.
|
|
245
220
|
def remap_aliases!(bucket, type_aliases)
|
|
246
221
|
canonical_set = CANONICAL_TYPES.values.to_set
|
|
247
222
|
bucket.each_pair.to_a.each do |key, info|
|
|
@@ -258,9 +233,8 @@ module Rigor
|
|
|
258
233
|
end
|
|
259
234
|
private_class_method :remap_aliases!
|
|
260
235
|
|
|
261
|
-
# Constant-path serialiser: `Dry::Schema` -> "Dry::Schema",
|
|
262
|
-
#
|
|
263
|
-
# doesn't expose as ConstantRead/PathNode.
|
|
236
|
+
# Constant-path serialiser: `Dry::Schema` -> "Dry::Schema", bare `Foo` -> "Foo". Returns nil for
|
|
237
|
+
# shapes Prism doesn't expose as ConstantRead/PathNode.
|
|
264
238
|
def constant_name_for(node)
|
|
265
239
|
return nil if node.nil?
|
|
266
240
|
|
|
@@ -10,7 +10,8 @@ module Rigor
|
|
|
10
10
|
module Plugin
|
|
11
11
|
# rigor-dry-schema — Tier A per
|
|
12
12
|
# [ADR-12](../../../../../docs/adr/12-dry-rb-packaging.md) and the
|
|
13
|
-
# slicing plan in
|
|
13
|
+
# slicing plan in
|
|
14
|
+
# [docs/design/20260517-dry-validation-slicing.md](../../../../../docs/design/20260517-dry-validation-slicing.md).
|
|
14
15
|
#
|
|
15
16
|
# Recognises the canonical dry-schema declaration shapes:
|
|
16
17
|
#
|
|
@@ -28,51 +29,42 @@ module Rigor
|
|
|
28
29
|
# required(:foo).value(:string)
|
|
29
30
|
# end
|
|
30
31
|
#
|
|
31
|
-
# and publishes the resulting
|
|
32
|
-
# `
|
|
33
|
-
#
|
|
34
|
-
# Downstream `rigor-dry-validation` consumes the fact for
|
|
35
|
-
# per-Contract typed-payload synthesis.
|
|
32
|
+
# and publishes the resulting `{schema_const_fqn => {required: {key => underlying_class}, optional:
|
|
33
|
+
# {…}}}` table as the `:dry_schema_table` cross-plugin fact (ADR-9). Downstream `rigor-dry-validation`
|
|
34
|
+
# consumes the fact for per-Contract typed-payload synthesis.
|
|
36
35
|
#
|
|
37
36
|
# ## Predicate type recognition
|
|
38
37
|
#
|
|
39
|
-
# Each `required(:key).<predicate>(<arg>)` row maps the predicate
|
|
40
|
-
#
|
|
41
|
-
# canonical-type vocabulary:
|
|
38
|
+
# Each `required(:key).<predicate>(<arg>)` row maps the predicate argument to an underlying Ruby
|
|
39
|
+
# class via the dry-schema canonical-type vocabulary:
|
|
42
40
|
#
|
|
43
|
-
# - `:string` / `:integer` / `:float` / `:decimal` / `:symbol` /
|
|
44
|
-
# `:
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
# `filled(Types::String)`) resolve through the
|
|
52
|
-
# `:dry_type_aliases` ADR-9 fact published by `rigor-dry-types`
|
|
53
|
-
# when that plugin is loaded; without it the row degrades to
|
|
54
|
-
# "no type contribution from this key".
|
|
41
|
+
# - `:string` / `:integer` / `:float` / `:decimal` / `:symbol` / `:bool` / `:nil` / `:date` /
|
|
42
|
+
# `:date_time` / `:time` / `:hash` / `:array` map to their underlying class.
|
|
43
|
+
# - The four predicate verbs `filled` / `value` / `maybe` / `each` are accepted on the same row; their
|
|
44
|
+
# semantic difference (whether the value is nullable or coerced) does not change the underlying
|
|
45
|
+
# class for Rigor's purposes.
|
|
46
|
+
# - References to dry-types aliases (`value(Types::Email)`, `filled(Types::String)`) resolve through
|
|
47
|
+
# the `:dry_type_aliases` ADR-9 fact published by `rigor-dry-types` when that plugin is loaded;
|
|
48
|
+
# without it the row degrades to "no type contribution from this key".
|
|
55
49
|
#
|
|
56
50
|
# ## Floor / ceiling (slice 1)
|
|
57
51
|
#
|
|
58
52
|
# Slice 1 ships the **floor**:
|
|
59
53
|
#
|
|
60
|
-
# - Top-level `Foo = Dry::Schema.{Params,JSON,define} { ... }`
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
#
|
|
65
|
-
# for the canonical-type vocabulary above.
|
|
54
|
+
# - Top-level `Foo = Dry::Schema.{Params,JSON,define} { ... }` assignments. Class-level constants
|
|
55
|
+
# (`class Bar; SCHEMA = Dry::Schema.Params { ... }; end`) work too — the walker prefixes the
|
|
56
|
+
# enclosing constant chain.
|
|
57
|
+
# - `required(:key).<predicate>(:type_symbol_or_constant)` rows for the canonical-type vocabulary
|
|
58
|
+
# above.
|
|
66
59
|
# - Publishes the table; no user-facing diagnostics yet.
|
|
67
60
|
#
|
|
68
61
|
# The **ceiling** (slice 2+):
|
|
69
62
|
#
|
|
70
|
-
# - Synthesise typed `result.to_h` returns from each schema
|
|
71
|
-
#
|
|
63
|
+
# - Synthesise typed `result.to_h` returns from each schema via ADR-16 Tier C heredoc-template
|
|
64
|
+
# substrate.
|
|
72
65
|
# - Nested schemas (`schema(do ... end)` inside another row).
|
|
73
66
|
# - `predicates(:size?)` / `each { ... }` recursion.
|
|
74
|
-
# - Per-row `dry-schema.unknown-predicate` /
|
|
75
|
-
# `dry-schema.unknown-type` `:info` diagnostics when a
|
|
67
|
+
# - Per-row `dry-schema.unknown-predicate` / `dry-schema.unknown-type` `:info` diagnostics when a
|
|
76
68
|
# row's predicate or type symbol isn't recognised.
|
|
77
69
|
class DrySchema < Rigor::Plugin::Base
|
|
78
70
|
manifest(
|
|
@@ -84,10 +76,9 @@ module Rigor
|
|
|
84
76
|
consumes: [{ plugin_id: "dry-types", name: :dry_type_aliases, optional: true }]
|
|
85
77
|
)
|
|
86
78
|
|
|
87
|
-
# Walks every project file once during `prepare(services)` to
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
# walk is bounded by `paths:`, parse errors degrade silently.
|
|
79
|
+
# Walks every project file once during `prepare(services)` to build the schema table, then publishes
|
|
80
|
+
# via the ADR-9 fact store. Mirrors the rigor-dry-types `#prepare` shape — the walk is bounded by
|
|
81
|
+
# `paths:`, parse errors degrade silently.
|
|
91
82
|
def prepare(services)
|
|
92
83
|
type_aliases = services.fact_store.read(plugin_id: "dry-types", name: :dry_type_aliases) || {}
|
|
93
84
|
table = SchemaScanner.scan(paths: scannable_paths(services), type_aliases: type_aliases)
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Gem entry point. Required by Rigor's plugin loader when
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
# `Rigor::Plugin.register`, which the body of
|
|
7
|
-
# `lib/rigor/plugin/dry_schema.rb` performs at load time.
|
|
3
|
+
# Gem entry point. Required by Rigor's plugin loader when `.rigor.yml` lists `rigor-dry-schema` under
|
|
4
|
+
# `plugins:`. The loader expects this `require` to side-effect a call to `Rigor::Plugin.register`,
|
|
5
|
+
# which the body of `lib/rigor/plugin/dry_schema.rb` performs at load time.
|
|
8
6
|
require_relative "rigor/plugin/dry_schema"
|
|
@@ -4,16 +4,13 @@ require "rigor/plugin"
|
|
|
4
4
|
|
|
5
5
|
module Rigor
|
|
6
6
|
module Plugin
|
|
7
|
-
# ADR-16 Tier C worked plugin: recognises dry-struct's class-
|
|
8
|
-
#
|
|
9
|
-
# the enclosing `Dry::Struct` subclass.
|
|
7
|
+
# ADR-16 Tier C worked plugin: recognises dry-struct's class-level `attribute :name, T` DSL and
|
|
8
|
+
# synthesises a reader on the enclosing `Dry::Struct` subclass.
|
|
10
9
|
#
|
|
11
|
-
# dry-struct's `Dry::Struct::ClassInterface#attribute` (per the
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# `class_interface.rb:452-464` `class_eval`s a heredoc
|
|
16
|
-
# interpolating that Symbol into a getter:
|
|
10
|
+
# dry-struct's `Dry::Struct::ClassInterface#attribute` (per the per-library survey,
|
|
11
|
+
# `lib/dry/struct/class_interface.rb:86-88` in the upstream gem) is the textbook Tier C target — a
|
|
12
|
+
# class-level DSL call enumerates a literal Symbol argument, and `class_interface.rb:452-464`
|
|
13
|
+
# `class_eval`s a heredoc interpolating that Symbol into a getter:
|
|
17
14
|
#
|
|
18
15
|
# class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
19
16
|
# def #{key} # def city
|
|
@@ -21,44 +18,36 @@ module Rigor
|
|
|
21
18
|
# end
|
|
22
19
|
# RUBY
|
|
23
20
|
#
|
|
24
|
-
# The substrate replays the same contract statically. For
|
|
25
|
-
# source like:
|
|
21
|
+
# The substrate replays the same contract statically. For source like:
|
|
26
22
|
#
|
|
27
23
|
# class Address < Dry::Struct
|
|
28
24
|
# attribute :city, Types::String
|
|
29
25
|
# attribute :country, Types::String
|
|
30
26
|
# end
|
|
31
27
|
#
|
|
32
|
-
# the pre-pass scans the file, sees `attribute :city, ...`, and
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
# than falling through to `call.undefined-method`.
|
|
28
|
+
# the pre-pass scans the file, sees `attribute :city, ...`, and synthesises `Address#city` as a
|
|
29
|
+
# SyntheticMethod the dispatcher surfaces below RBS dispatch. Bare `address.city` calls in other
|
|
30
|
+
# files then dispatch through the synthetic record rather than falling through to
|
|
31
|
+
# `call.undefined-method`.
|
|
37
32
|
#
|
|
38
33
|
# ## Precision model (ADR-16 WD13 + ADR-18)
|
|
39
34
|
#
|
|
40
|
-
# The synthetic reader's return type is resolved via ADR-18's
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
# for common cases. When the lookup misses (e.g. inline method-chain
|
|
45
|
-
# argument whose chain-head isn't currently extracted), the row
|
|
35
|
+
# The synthetic reader's return type is resolved via ADR-18's `returns_from_arg:` fact lookup: the
|
|
36
|
+
# call-site's second argument (`Types::String` etc.) is looked up through the `:dry_type_aliases`
|
|
37
|
+
# fact published by `rigor-dry-types`, yielding `Nominal[String]` for common cases. When the lookup
|
|
38
|
+
# misses (e.g. inline method-chain argument whose chain-head isn't currently extracted), the row
|
|
46
39
|
# falls back to `Dynamic[Top]` silently.
|
|
47
40
|
#
|
|
48
41
|
# ## Scope (slice 2c minimum)
|
|
49
42
|
#
|
|
50
43
|
# - Recognises `attribute :name, T` at class body top level.
|
|
51
|
-
# - Recognises `attribute? :name, T` via a separate template
|
|
52
|
-
#
|
|
53
|
-
# - Synthesises **only the reader** — the other survey-listed
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
# - Nested-block form (`attribute :details do ... end` minting
|
|
59
|
-
# `Address::Details`) is out of scope for slice 2c; that
|
|
60
|
-
# pattern needs Tier A + Tier C composition + const_set
|
|
61
|
-
# emission. Deferred.
|
|
44
|
+
# - Recognises `attribute? :name, T` via a separate template entry (omittable attribute; same reader
|
|
45
|
+
# name, `?` stripped).
|
|
46
|
+
# - Synthesises **only the reader** — the other survey-listed emit rows (`schema` key, `to_h` row,
|
|
47
|
+
# `[:key]` access, `.new` kwarg) are not yet wired by the substrate (they require either RBS-level
|
|
48
|
+
# shape synthesis or additional substrate primitives). Slice 2c stops at the reader.
|
|
49
|
+
# - Nested-block form (`attribute :details do ... end` minting `Address::Details`) is out of scope
|
|
50
|
+
# for slice 2c; that pattern needs Tier A + Tier C composition + const_set emission. Deferred.
|
|
62
51
|
class DryStruct < Rigor::Plugin::Base
|
|
63
52
|
manifest(
|
|
64
53
|
id: "dry-struct",
|
|
@@ -66,26 +55,20 @@ module Rigor
|
|
|
66
55
|
description: "Recognises dry-struct `attribute :name, T` DSL via ADR-16 Tier C; " \
|
|
67
56
|
"promotes the reader's return type through ADR-18's `returns_from_arg:` " \
|
|
68
57
|
"by consuming `rigor-dry-types`'s `:dry_type_aliases` fact.",
|
|
69
|
-
# ADR-9 consumption — the precision-promotion path
|
|
70
|
-
#
|
|
71
|
-
# `
|
|
72
|
-
#
|
|
73
|
-
# `returns_from_arg:` lookup misses and the synthetic
|
|
74
|
-
# readers fall back to `Dynamic[Top]` (the pre-ADR-18
|
|
75
|
-
# floor).
|
|
58
|
+
# ADR-9 consumption — the precision-promotion path below uses `:dry_type_aliases` published by
|
|
59
|
+
# `rigor-dry-types`. The fact is optional: when the `rigor-dry-types` plugin isn't loaded, the
|
|
60
|
+
# `returns_from_arg:` lookup misses and the synthetic readers fall back to `Dynamic[Top]` (the
|
|
61
|
+
# pre-ADR-18 floor).
|
|
76
62
|
consumes: [{ plugin_id: "dry-types", name: :dry_type_aliases, optional: true }],
|
|
77
63
|
heredoc_templates: [
|
|
78
64
|
Rigor::Plugin::Macro::HeredocTemplate.new(
|
|
79
65
|
receiver_constraint: "Dry::Struct",
|
|
80
66
|
method_name: :attribute,
|
|
81
67
|
symbol_arg_position: 0,
|
|
82
|
-
# ADR-18 — the synthetic reader's return type comes
|
|
83
|
-
#
|
|
84
|
-
# (`Types::String
|
|
85
|
-
#
|
|
86
|
-
# (e.g. inline `attribute :tag, Types::String.constrained(...)`,
|
|
87
|
-
# whose receiver chain head isn't currently
|
|
88
|
-
# extracted), the row falls back to Dynamic[Top].
|
|
68
|
+
# ADR-18 — the synthetic reader's return type comes from the call site's second argument
|
|
69
|
+
# (`Types::String` etc.), resolved through the `:dry_type_aliases` fact. When the lookup
|
|
70
|
+
# misses (e.g. inline `attribute :tag, Types::String.constrained(...)`, whose receiver chain
|
|
71
|
+
# head isn't currently extracted), the row falls back to Dynamic[Top].
|
|
89
72
|
emit: [{
|
|
90
73
|
name: "\#{name}",
|
|
91
74
|
returns_from_arg: {
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Gem entry point. Required by Rigor's plugin loader when
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
# `Rigor::Plugin.register`, which the body of
|
|
7
|
-
# `lib/rigor/plugin/dry_struct.rb` performs at load time.
|
|
3
|
+
# Gem entry point. Required by Rigor's plugin loader when `.rigor.yml` lists `rigor-dry-struct` under
|
|
4
|
+
# `plugins:`. The loader expects this `require` to side-effect a call to `Rigor::Plugin.register`,
|
|
5
|
+
# which the body of `lib/rigor/plugin/dry_struct.rb` performs at load time.
|
|
8
6
|
require_relative "rigor/plugin/dry_struct"
|