rigortype 0.3.9 → 0.4.0
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 +2 -2
- data/data/core_overlay/enumerable.rbs +51 -0
- data/data/core_overlay/enumerator.rbs +84 -0
- data/data/core_overlay/hash_rbs3.rbs +41 -0
- data/data/core_overlay/process.rbs +40 -0
- data/data/core_overlay/string_io.rbs +33 -0
- data/data/effects/core.yml +3 -3
- data/data/gem_overlay/activesupport/core_ext.rbs +127 -4
- data/docs/handbook/03-narrowing.md +95 -10
- data/docs/handbook/04-tuples-and-shapes.md +8 -6
- data/docs/handbook/07-rbs-and-extended.md +16 -11
- data/docs/handbook/10-sorbet.md +9 -10
- data/docs/handbook/11-sig-gen.md +454 -13
- data/docs/manual/02-cli-reference.md +63 -2
- data/docs/manual/03-configuration.md +7 -0
- data/docs/manual/04-diagnostics.md +4 -0
- data/docs/manual/07-plugins.md +1 -1
- data/docs/manual/10-mcp-server.md +3 -2
- data/docs/manual/16-rbs-extended-annotations.md +40 -7
- data/docs/manual/19-effect-labels.md +10 -0
- data/docs/manual/plugins/README.md +7 -0
- data/docs/manual/plugins/rigor-actioncable.md +8 -1
- data/docs/manual/plugins/rigor-actionmailer.md +7 -0
- data/docs/manual/plugins/rigor-actionpack.md +243 -0
- data/docs/manual/plugins/rigor-active-model-serializers.md +153 -0
- data/docs/manual/plugins/rigor-activejob.md +7 -0
- data/docs/manual/plugins/rigor-activerecord.md +110 -4
- data/docs/manual/plugins/rigor-activestorage.md +8 -1
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +11 -5
- data/docs/manual/plugins/rigor-grape.md +106 -0
- data/docs/manual/plugins/rigor-graphql.md +23 -2
- data/docs/manual/plugins/rigor-pundit.md +8 -1
- data/docs/manual/plugins/rigor-rails-i18n.md +10 -5
- data/docs/manual/plugins/rigor-rails-routes.md +7 -0
- data/docs/manual/plugins/rigor-rbs-inline.md +212 -25
- data/docs/manual/plugins/rigor-sidekiq.md +8 -1
- data/docs/manual/plugins/rigor-sorbet.md +21 -5
- data/exe/rigor +19 -4
- data/lib/rigor/analysis/baseline.rb +1 -1
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +167 -2
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +189 -0
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +5 -3
- data/lib/rigor/analysis/check_rules/rule_ids.rb +20 -5
- data/lib/rigor/analysis/check_rules/rule_walk.rb +2 -1
- data/lib/rigor/analysis/check_rules/source_arity.rb +323 -0
- data/lib/rigor/analysis/check_rules/special_global_setters.rb +146 -0
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +36 -2
- data/lib/rigor/analysis/check_rules.rb +520 -49
- data/lib/rigor/analysis/dependency_recorder.rb +23 -0
- data/lib/rigor/analysis/fact_store.rb +9 -0
- data/lib/rigor/analysis/incremental.rb +26 -0
- data/lib/rigor/analysis/incremental_session.rb +36 -4
- data/lib/rigor/analysis/project_scan.rb +11 -1
- data/lib/rigor/analysis/reachability/plugin_roots.rb +0 -1
- data/lib/rigor/analysis/reachability/scan_cache.rb +1 -0
- data/lib/rigor/analysis/rule_catalog.rb +127 -0
- data/lib/rigor/analysis/run_cache_key.rb +20 -11
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +167 -11
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +9 -4
- data/lib/rigor/analysis/runner/pool_coordinator.rb +107 -15
- data/lib/rigor/analysis/runner/project_pre_passes.rb +26 -7
- data/lib/rigor/analysis/runner.rb +278 -20
- data/lib/rigor/analysis/template_unit_collector.rb +303 -0
- data/lib/rigor/analysis/template_unit_paths.rb +91 -0
- data/lib/rigor/analysis/template_unit_positions.rb +293 -0
- data/lib/rigor/analysis/template_units.rb +399 -0
- data/lib/rigor/analysis/worker_session.rb +53 -10
- data/lib/rigor/bleeding_edge.rb +0 -2
- data/lib/rigor/builtins/hkt_builtins.rb +1 -0
- data/lib/rigor/builtins/imported_refinements.rb +4 -0
- data/lib/rigor/builtins/regex_refinement.rb +17 -9
- data/lib/rigor/builtins/static_return_refinements.rb +2 -0
- data/lib/rigor/cache/descriptor.rb +6 -1
- data/lib/rigor/cache/engine_source.rb +29 -1
- data/lib/rigor/cache/incremental_snapshot.rb +33 -1
- data/lib/rigor/cache/rbs_cache_producer.rb +4 -0
- data/lib/rigor/cache/rbs_descriptor.rb +37 -7
- data/lib/rigor/cache/store.rb +0 -1
- data/lib/rigor/ci_detector.rb +1 -0
- data/lib/rigor/cli/doc_links.rb +1 -1
- data/lib/rigor/cli/docs_command.rb +4 -4
- data/lib/rigor/cli/plugin_command.rb +3 -3
- data/lib/rigor/cli/prism_colorizer.rb +0 -1
- data/lib/rigor/cli/sig_gen_command.rb +210 -29
- data/lib/rigor/cli/skill_command.rb +1 -1
- data/lib/rigor/cli/skill_describe.rb +0 -1
- data/lib/rigor/cli/type_of_command.rb +19 -5
- data/lib/rigor/cli/type_of_renderer.rb +20 -9
- data/lib/rigor/cli/type_of_template_probe.rb +189 -0
- data/lib/rigor/cli.rb +21 -3
- data/lib/rigor/configuration/severity_profile.rb +19 -3
- data/lib/rigor/configuration.rb +66 -3
- data/lib/rigor/effects/ancestry_recorder.rb +191 -0
- data/lib/rigor/effects/attribution.rb +11 -2
- data/lib/rigor/effects/callee_rule.rb +368 -0
- data/lib/rigor/effects/catalog.rb +7 -4
- data/lib/rigor/effects/collector.rb +11 -5
- data/lib/rigor/effects/config_envelopes.rb +9 -2
- data/lib/rigor/effects/definition_context.rb +179 -0
- data/lib/rigor/effects/effect_table.rb +11 -3
- data/lib/rigor/effects/envelope_check.rb +1 -1
- data/lib/rigor/effects/envelope_index.rb +15 -0
- data/lib/rigor/effects/file_collection.rb +59 -5
- data/lib/rigor/effects/framework_units.rb +1 -1
- data/lib/rigor/effects/identity.rb +16 -0
- data/lib/rigor/effects/local_ownership.rb +38 -12
- data/lib/rigor/effects/method_key.rb +21 -0
- data/lib/rigor/effects/mutation_classifier.rb +23 -12
- data/lib/rigor/effects/plugin_facts.rb +43 -31
- data/lib/rigor/effects/propagator.rb +295 -16
- data/lib/rigor/effects/registry.rb +1 -1
- data/lib/rigor/effects/scanner.rb +121 -72
- data/lib/rigor/effects/signature_sources.rb +1 -1
- data/lib/rigor/effects/snapshot.rb +2 -1
- data/lib/rigor/effects/summary.rb +27 -4
- data/lib/rigor/effects/unit_scan.rb +385 -30
- data/lib/rigor/effects/visibility.rb +101 -0
- data/lib/rigor/environment/lockfile_resolver.rb +17 -0
- data/lib/rigor/environment/member_consistency/comparator.rb +708 -0
- data/lib/rigor/environment/member_consistency.rb +298 -0
- data/lib/rigor/environment/rbs_loader.rb +399 -133
- data/lib/rigor/environment.rb +103 -38
- data/lib/rigor/hashing/xxh3.rb +264 -0
- data/lib/rigor/inference/acceptance.rb +139 -9
- data/lib/rigor/inference/block_auto_splat.rb +216 -0
- data/lib/rigor/inference/block_call_timing.rb +338 -0
- data/lib/rigor/inference/block_parameter_binder.rb +73 -27
- data/lib/rigor/inference/block_repetition.rb +71 -0
- data/lib/rigor/inference/body_fixpoint.rb +2 -1
- data/lib/rigor/inference/budget_trace.rb +2 -1
- data/lib/rigor/inference/builtins/method_catalog.rb +2 -1
- data/lib/rigor/inference/builtins/string_catalog.rb +1 -1
- data/lib/rigor/inference/captured_locals.rb +387 -15
- data/lib/rigor/inference/closure_escape_analyzer.rb +157 -13
- data/lib/rigor/inference/content_join.rb +200 -27
- data/lib/rigor/inference/def_return_typer.rb +11 -7
- data/lib/rigor/inference/define_method_block_self.rb +64 -0
- data/lib/rigor/inference/element_read_widening.rb +22 -10
- data/lib/rigor/inference/error_info.rb +196 -0
- data/lib/rigor/inference/expression_typer.rb +1532 -496
- data/lib/rigor/inference/external_ancestor_resolution.rb +267 -0
- data/lib/rigor/inference/fresh_frame_blocks.rb +127 -0
- data/lib/rigor/inference/global_write_census.rb +239 -0
- data/lib/rigor/inference/guard_rebinding.rb +447 -0
- data/lib/rigor/inference/hash_lookup_mutation.rb +88 -0
- data/lib/rigor/inference/index_write_widening.rb +16 -3
- data/lib/rigor/inference/indexed_narrowing.rb +61 -9
- data/lib/rigor/inference/jump_targets.rb +82 -0
- data/lib/rigor/inference/last_line/implicit_self.rb +210 -0
- data/lib/rigor/inference/last_line/self_evidence.rb +329 -0
- data/lib/rigor/inference/last_line.rb +340 -0
- data/lib/rigor/inference/last_status.rb +144 -0
- data/lib/rigor/inference/macro_block_self_type.rb +167 -17
- data/lib/rigor/inference/match_rebinding/calls.rb +281 -0
- data/lib/rigor/inference/match_rebinding/frame.rb +148 -0
- data/lib/rigor/inference/match_rebinding/operands.rb +236 -0
- data/lib/rigor/inference/match_rebinding/self_calls.rb +83 -0
- data/lib/rigor/inference/match_rebinding.rb +392 -0
- data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +36 -0
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +85 -24
- data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +147 -0
- data/lib/rigor/inference/method_dispatcher/hash_transform_keys_folding.rb +191 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +4 -0
- data/lib/rigor/inference/method_dispatcher/match_data_folding.rb +159 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +113 -73
- data/lib/rigor/inference/method_dispatcher/process_folding.rb +56 -0
- data/lib/rigor/inference/method_dispatcher/proven_overload.rb +72 -0
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +881 -38
- data/lib/rigor/inference/method_dispatcher/self_substitute.rb +142 -0
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +128 -53
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher.rb +214 -13
- data/lib/rigor/inference/method_parameter_binder.rb +8 -3
- data/lib/rigor/inference/multi_target_binder.rb +340 -52
- data/lib/rigor/inference/mutation_rejoin.rb +4 -1
- data/lib/rigor/inference/mutation_widening.rb +70 -48
- data/lib/rigor/inference/narrowing.rb +540 -120
- data/lib/rigor/inference/operand_effects.rb +167 -0
- data/lib/rigor/inference/operand_walk.rb +88 -0
- data/lib/rigor/inference/optimistic_origin.rb +152 -9
- data/lib/rigor/inference/parameter_inference_collector.rb +3 -2
- data/lib/rigor/inference/project_method_ownership.rb +136 -0
- data/lib/rigor/inference/project_patched_methods.rb +7 -2
- data/lib/rigor/inference/project_patched_scanner.rb +7 -3
- data/lib/rigor/inference/receiver_alias.rb +90 -1
- data/lib/rigor/inference/receiver_blind_block.rb +219 -0
- data/lib/rigor/inference/refinement_mutation.rb +15 -11
- data/lib/rigor/inference/repeated_or_writes.rb +463 -0
- data/lib/rigor/inference/return_barrier.rb +54 -0
- data/lib/rigor/inference/rewrite_mutation.rb +120 -0
- data/lib/rigor/inference/scope_indexer.rb +4615 -551
- data/lib/rigor/inference/statement_evaluator.rb +3176 -490
- data/lib/rigor/inference/stored_block_call.rb +54 -0
- data/lib/rigor/inference/string_mutation.rb +44 -7
- data/lib/rigor/inference/unknown_store_widening.rb +200 -0
- data/lib/rigor/inference/unthreaded_rebinds.rb +282 -0
- data/lib/rigor/language_server/debouncer.rb +0 -1
- data/lib/rigor/language_server/diagnostic_publisher.rb +3 -2
- data/lib/rigor/language_server/hover_renderer.rb +3 -3
- data/lib/rigor/language_server/project_context.rb +5 -3
- data/lib/rigor/mcp/server.rb +2 -1
- data/lib/rigor/plugin/base.rb +168 -5
- data/lib/rigor/plugin/box_probe.rb +91 -0
- data/lib/rigor/plugin/bundled_catalog.rb +1 -1
- data/lib/rigor/plugin/effect_attribution.rb +58 -4
- data/lib/rigor/plugin/loader.rb +2 -1
- data/lib/rigor/plugin/macro/block_as_method.rb +45 -6
- data/lib/rigor/plugin/manifest.rb +71 -10
- data/lib/rigor/plugin/registry.rb +35 -1
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +9 -3
- data/lib/rigor/plugin/template_unit.rb +196 -0
- data/lib/rigor/plugin.rb +1 -0
- data/lib/rigor/protection/discovery_seed.rb +3 -1
- data/lib/rigor/protection/kill_signature.rb +0 -1
- data/lib/rigor/protection/mutation_cache.rb +1 -2
- data/lib/rigor/rbs_extended.rb +27 -0
- data/lib/rigor/reflection/constant_ancestors.rb +97 -0
- data/lib/rigor/reflection/constant_path.rb +19 -6
- data/lib/rigor/reflection.rb +72 -105
- data/lib/rigor/scope/discovery_index.rb +135 -2
- data/lib/rigor/scope.rb +859 -49
- data/lib/rigor/sig_gen/alias_index.rb +289 -0
- data/lib/rigor/sig_gen/classification.rb +22 -5
- data/lib/rigor/sig_gen/declaration_equivalence.rb +127 -0
- data/lib/rigor/sig_gen/effect_annotation.rb +202 -0
- data/lib/rigor/sig_gen/generator.rb +558 -31
- data/lib/rigor/sig_gen/inline_declarations.rb +184 -0
- data/lib/rigor/sig_gen/method_candidate.rb +47 -3
- data/lib/rigor/sig_gen/observation_collector.rb +1 -1
- data/lib/rigor/sig_gen/renderer.rb +124 -9
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +44 -1
- data/lib/rigor/sig_gen/write_result.rb +19 -3
- data/lib/rigor/sig_gen/writer.rb +166 -35
- data/lib/rigor/sig_gen.rb +3 -0
- data/lib/rigor/signature_path_audit.rb +1 -1
- data/lib/rigor/source/node_walker.rb +0 -3
- data/lib/rigor/source/parameter_envelope.rb +72 -0
- data/lib/rigor/source.rb +1 -0
- data/lib/rigor/type/combinator.rb +88 -12
- data/lib/rigor/type/difference.rb +1 -0
- data/lib/rigor/type/hash_shape.rb +1 -1
- data/lib/rigor/type/refined.rb +1 -0
- data/lib/rigor/version.rb +1 -1
- data/lib/rigor.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/effects.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +9 -5
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +13 -4
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +0 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +96 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/effects.rb +65 -8
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +270 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/render_locals.rb +402 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +370 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_units.rb +132 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +239 -4
- data/plugins/rigor-actionpack/sig/action_view.rbs +43 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_discoverer.rb +220 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_index.rb +56 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +263 -0
- data/plugins/rigor-active-model-serializers/lib/rigor-active-model-serializers.rb +7 -0
- data/plugins/rigor-active-model-serializers/sig/active_model_serializers.rbs +45 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +9 -5
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +35 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +72 -12
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +380 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +14 -6
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +281 -35
- data/plugins/rigor-activerecord/sig/active_record/relation.rbs +206 -31
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +25 -14
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +9 -2
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +171 -5
- data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +2 -0
- data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +1 -0
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/types.rb +1 -1
- data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +141 -0
- data/plugins/rigor-grape/lib/rigor-grape.rb +6 -0
- data/plugins/rigor-grape/sig/grape.rbs +263 -0
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +72 -2
- data/plugins/rigor-graphql/sig/graphql.rbs +485 -0
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +2 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +11 -7
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +35 -37
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +0 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +2 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +1 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +9 -17
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline/same_line_annotations.rb +149 -0
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +217 -36
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/schedule_scan.rb +1 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +9 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +0 -1
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +46 -1
- data/plugins/rigor-sorbet/sig/sorbet.rbs +277 -0
- data/sig/rigor/analysis/baseline.rbs +69 -7
- data/sig/rigor/analysis/fact_store.rbs +1 -1
- data/sig/rigor/analysis/project_scan.rbs +74 -0
- data/sig/rigor/effects/config_envelopes.rbs +100 -0
- data/sig/rigor/effects/effect_table.rbs +60 -0
- data/sig/rigor/effects/envelope.rbs +97 -0
- data/sig/rigor/effects/envelope_index.rbs +33 -0
- data/sig/rigor/effects/file_collection.rbs +81 -0
- data/sig/rigor/effects/label.rbs +26 -0
- data/sig/rigor/effects/label_set.rbs +46 -0
- data/sig/rigor/effects/method_key.rbs +24 -0
- data/sig/rigor/effects/origin.rbs +50 -0
- data/sig/rigor/effects/plugin_facts.rbs +141 -0
- data/sig/rigor/effects/registry.rbs +68 -0
- data/sig/rigor/effects/summary.rbs +50 -0
- data/sig/rigor/effects/taint_cause.rbs +12 -0
- data/sig/rigor/environment.rbs +12 -10
- data/sig/rigor/inference/optimistic_origin.rbs +10 -0
- data/sig/rigor/inference.rbs +6 -4
- data/sig/rigor/plugin/additional_initializer.rbs +36 -0
- data/sig/rigor/plugin/base.rbs +30 -7
- data/sig/rigor/plugin/effect_ancestry.rbs +27 -0
- data/sig/rigor/plugin/effect_attribution.rbs +66 -0
- data/sig/rigor/plugin/effect_edge.rbs +33 -0
- data/sig/rigor/plugin/effect_entry_points.rbs +25 -0
- data/sig/rigor/plugin/io_boundary.rbs +1 -1
- data/sig/rigor/plugin/loader.rbs +3 -3
- data/sig/rigor/plugin/manifest.rbs +50 -11
- data/sig/rigor/plugin/protocol_contract.rbs +68 -0
- data/sig/rigor/plugin/registry.rbs +62 -1
- data/sig/rigor/plugin.rbs +1 -1
- data/sig/rigor/rbs_extended.rbs +1 -1
- data/sig/rigor/reflection.rbs +7 -6
- data/sig/rigor/scope.rbs +135 -20
- data/sig/rigor/sig_gen/skip_reason_catalog.rbs +14 -7
- data/sig/rigor/source.rbs +4 -4
- data/sig/rigor/testing.rbs +10 -4
- data/sig/rigor/type.rbs +6 -0
- data/sig/rigor.rbs +38 -20
- data/skills/rigor-ask/SKILL.md +8 -5
- data/skills/rigor-baseline-reduce/SKILL.md +4 -6
- data/skills/rigor-ci-setup/SKILL.md +17 -21
- data/skills/rigor-doctor/SKILL.md +24 -22
- data/skills/rigor-doctor/references/01-checks.md +97 -33
- data/skills/rigor-editor-setup/SKILL.md +6 -4
- data/skills/rigor-mcp-setup/SKILL.md +5 -4
- data/skills/rigor-monkeypatch-resolve/SKILL.md +5 -3
- data/skills/rigor-next-steps/SKILL.md +4 -2
- data/skills/rigor-plugin-author/SKILL.md +19 -23
- data/skills/rigor-plugin-author/references/01-plan-and-scaffold.md +9 -8
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +12 -25
- data/skills/rigor-plugin-author/references/03-test-and-ship.md +6 -8
- data/skills/rigor-plugin-review/SKILL.md +6 -4
- data/skills/rigor-plugin-review/references/01-best-practices-checklist.md +2 -1
- data/skills/rigor-plugin-tune/SKILL.md +4 -2
- data/skills/rigor-project-init/SKILL.md +9 -7
- data/skills/rigor-project-init/references/01-detect.md +13 -9
- data/skills/rigor-project-init/references/02-configure.md +33 -8
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +14 -14
- data/skills/rigor-project-init/references/04-sig-uplift.md +27 -14
- data/skills/rigor-protection-uplift/SKILL.md +4 -6
- data/skills/rigor-rbs-setup/SKILL.md +4 -2
- data/skills/rigor-type-oracle/SKILL.md +4 -6
- data/skills/rigor-type-oracle/references/01-oracle-commands.md +12 -8
- data/skills/rigor-type-oracle/references/03-gap-protocol.md +0 -3
- data/skills/rigor-unused-adjudicate/SKILL.md +4 -2
- data/skills/rigor-upgrade/SKILL.md +13 -8
- metadata +108 -1
|
@@ -30,6 +30,7 @@ module Rigor
|
|
|
30
30
|
source_path: __FILE__,
|
|
31
31
|
source_line: __LINE__
|
|
32
32
|
)
|
|
33
|
+
Ractor.make_shareable(RESULT_DEFINITION)
|
|
33
34
|
|
|
34
35
|
MAYBE_DEFINITION = Inference::HktRegistry.definition_with_body_tree(
|
|
35
36
|
uri: :"dry_monads::maybe",
|
|
@@ -38,6 +39,7 @@ module Rigor
|
|
|
38
39
|
source_path: __FILE__,
|
|
39
40
|
source_line: __LINE__
|
|
40
41
|
)
|
|
42
|
+
Ractor.make_shareable(MAYBE_DEFINITION)
|
|
41
43
|
|
|
42
44
|
CONSTRUCTOR_METHODS = %i[Success Failure Some None].freeze
|
|
43
45
|
UNWRAP_METHODS = %i[value! failure value_or].freeze
|
|
@@ -23,6 +23,7 @@ module Rigor
|
|
|
23
23
|
response_body: -> { Rigor::Type::Combinator.nominal_of("String") },
|
|
24
24
|
response_headers: -> { Rigor::Type::Combinator.nominal_of("String") }
|
|
25
25
|
}.freeze
|
|
26
|
+
Ractor.make_shareable(EASY_RETURN_TYPES)
|
|
26
27
|
|
|
27
28
|
dynamic_return receivers: ["Ethon::Easy"], methods: EASY_RETURN_TYPES.keys do |call_node, _scope|
|
|
28
29
|
builder = EASY_RETURN_TYPES[call_node.name]
|
|
@@ -20,7 +20,7 @@ module Rigor
|
|
|
20
20
|
].to_set.freeze
|
|
21
21
|
|
|
22
22
|
# Regex anchor must match end of string \z
|
|
23
|
-
NOMINAL_OPAQUE_REGEX = Regexp.new("(_ptr|_handle|Ptr|Handle)\\z")
|
|
23
|
+
NOMINAL_OPAQUE_REGEX = Regexp.new("(_ptr|_handle|Ptr|Handle)\\z").freeze
|
|
24
24
|
|
|
25
25
|
BOOL_TYPE = Rigor::Type::Combinator.union(
|
|
26
26
|
Rigor::Type::Combinator.constant_of(true),
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rigor/plugin"
|
|
4
|
+
|
|
5
|
+
module Rigor
|
|
6
|
+
module Plugin
|
|
7
|
+
# rigor-grape — recognises the Grape endpoint-declaration DSL (`class API < Grape::API`) and the
|
|
8
|
+
# grape-entity exposure DSL (`class E < Grape::Entity`) so the calls stop reading `Dynamic[top]`
|
|
9
|
+
# (issue #1099; gitlab's `lib/api` accounted for ~10k opaque implicit-self sends in the
|
|
10
|
+
# 2026-09-19 survey — `expose` ~3.9k, `optional` ~2.2k, `route_setting` ~1.5k, `desc` ~1.4k,
|
|
11
|
+
# `requires` ~1.4k).
|
|
12
|
+
#
|
|
13
|
+
# Grape is more dynamic than the frameworks the ADR-16 substrate was built for:
|
|
14
|
+
#
|
|
15
|
+
# - `Grape::API` subclasses have NO static class methods — every declaration call is forwarded
|
|
16
|
+
# to the base `Grape::API::Instance` class object at runtime (`delegate_missing_to` +
|
|
17
|
+
# `override_all_methods!`, `lib/grape/api.rb`). The bundled sig declares the shared surface
|
|
18
|
+
# once in `Grape::DSL::ClassMethods` and `extend`s it onto both `Grape::API` (reached from
|
|
19
|
+
# source subclasses via `rbs_complete_ancestors`, ADR-43 WD4) and `Grape::API::Instance`
|
|
20
|
+
# (reached inside `namespace` bodies, whose `self` is the Instance class object).
|
|
21
|
+
# - Block `self` bindings differ per macro family — `params` bodies `instance_eval` on a
|
|
22
|
+
# `Grape::Validations::ParamsScope` instance, `namespace`/`route_param`/`version`/`given`/
|
|
23
|
+
# `mounted` bodies on the Instance class object, and verb bodies run as `Grape::Endpoint`
|
|
24
|
+
# instance methods. `block_as_methods` entries carry a named `self_type` ("Foo" /
|
|
25
|
+
# "singleton(Foo)") so each body binds the object Grape actually evaluates it on.
|
|
26
|
+
# - `Grape::Entity`'s `expose` bodies run via `block.call` — `self` stays the Entity class
|
|
27
|
+
# object — so nested `expose` calls need no entry; the `def self.` declarations cover them.
|
|
28
|
+
#
|
|
29
|
+
# ## Deferred (documented in README)
|
|
30
|
+
#
|
|
31
|
+
# - `helpers do ... end` bodies (`class_eval` on an anonymous Module — unnamed self).
|
|
32
|
+
# - Typing `present`/`declared` results against the declared entity/params (runtime shape).
|
|
33
|
+
class Grape < Rigor::Plugin::Base
|
|
34
|
+
# `namespace`-family bodies evaluate as instance methods of the Instance *class object*
|
|
35
|
+
# (`Instance.nest` / `evaluate_as_instance_with_configuration` do `instance_eval(&block)`).
|
|
36
|
+
# `scope` belongs here too: `Grape::DSL::Routing#scope` is `within_namespace { nest(block) }`,
|
|
37
|
+
# so its body `instance_eval`s on the same Instance class object as `namespace`.
|
|
38
|
+
NAMESPACE_METHODS = %i[
|
|
39
|
+
namespace group resource resources segment scope route_param version given mounted
|
|
40
|
+
].freeze
|
|
41
|
+
# HTTP verb macros are generated over `Grape::HTTP_SUPPORTED_METHODS` and delegate to `route`;
|
|
42
|
+
# their bodies run inside `Grape::Endpoint` instances.
|
|
43
|
+
VERB_METHODS = %i[get put post delete head patch options route].freeze
|
|
44
|
+
# `params` bodies evaluate on a `ParamsScope` instance; the block-carrying scope macros re-enter
|
|
45
|
+
# a child scope the same way.
|
|
46
|
+
PARAMS_SCOPE_METHODS = %i[requires optional given with].freeze
|
|
47
|
+
|
|
48
|
+
manifest(
|
|
49
|
+
id: "grape",
|
|
50
|
+
target_gems: %w[grape grape-entity],
|
|
51
|
+
version: "0.1.0",
|
|
52
|
+
description: "Types the Grape endpoint-declaration DSL (`Grape::API` subclasses: `params`, " \
|
|
53
|
+
"`namespace`, HTTP verb macros, `desc`, `route_setting`, `helpers`) and the " \
|
|
54
|
+
"grape-entity exposure DSL (`Grape::Entity` subclasses: `expose`), including " \
|
|
55
|
+
"the `instance_eval`'d block `self` bindings.",
|
|
56
|
+
signature_paths: ["sig"],
|
|
57
|
+
# ADR-43 WD4 — `Grape::API`/`Grape::Entity` subclasses bridge their class-level DSL calls to
|
|
58
|
+
# the bundled sig's `def self.` declarations. Justified because the bundled sig IS the
|
|
59
|
+
# authority (neither gem ships RBS) and the declared surface is what the DSL exposes.
|
|
60
|
+
rbs_complete_ancestors: %w[
|
|
61
|
+
Grape::API
|
|
62
|
+
Grape::Entity
|
|
63
|
+
],
|
|
64
|
+
# All five classes have genuinely open runtime surfaces (`override_all_methods!` generates
|
|
65
|
+
# and forwards methods on API subclasses; ParamsScope/Endpoint pick up DSL modules) — calls
|
|
66
|
+
# we don't declare must stay opaque, not diagnosed.
|
|
67
|
+
open_receivers: %w[
|
|
68
|
+
Grape::API
|
|
69
|
+
Grape::API::Instance
|
|
70
|
+
Grape::Entity
|
|
71
|
+
Grape::Validations::ParamsScope
|
|
72
|
+
Grape::Endpoint
|
|
73
|
+
],
|
|
74
|
+
block_as_methods: [
|
|
75
|
+
# Class-body context: `class API < Grape::API; namespace :x do ... end`.
|
|
76
|
+
Rigor::Plugin::Macro::BlockAsMethod.new(
|
|
77
|
+
receiver_constraint: "Grape::API",
|
|
78
|
+
method_names: NAMESPACE_METHODS,
|
|
79
|
+
self_type: "singleton(Grape::API::Instance)"
|
|
80
|
+
),
|
|
81
|
+
# Inside an already-narrowed namespace body (self is the Instance class object), nested
|
|
82
|
+
# `namespace`/`version`/`given` calls re-enter the same context.
|
|
83
|
+
Rigor::Plugin::Macro::BlockAsMethod.new(
|
|
84
|
+
receiver_constraint: "Grape::API::Instance",
|
|
85
|
+
method_names: NAMESPACE_METHODS,
|
|
86
|
+
self_type: "singleton(Grape::API::Instance)"
|
|
87
|
+
),
|
|
88
|
+
# `params do ... end` — body `instance_eval`s on a `ParamsScope` instance.
|
|
89
|
+
Rigor::Plugin::Macro::BlockAsMethod.new(
|
|
90
|
+
receiver_constraint: "Grape::API",
|
|
91
|
+
method_names: %i[params],
|
|
92
|
+
self_type: "Grape::Validations::ParamsScope"
|
|
93
|
+
),
|
|
94
|
+
Rigor::Plugin::Macro::BlockAsMethod.new(
|
|
95
|
+
receiver_constraint: "Grape::API::Instance",
|
|
96
|
+
method_names: %i[params],
|
|
97
|
+
self_type: "Grape::Validations::ParamsScope"
|
|
98
|
+
),
|
|
99
|
+
# `requires :x, type: Hash do ... end` inside a params body re-enters a child ParamsScope —
|
|
100
|
+
# the receiver is already the `Nominal[ParamsScope]` `self` of the enclosing body, which is
|
|
101
|
+
# what named-instance `self_type` entries additionally match.
|
|
102
|
+
Rigor::Plugin::Macro::BlockAsMethod.new(
|
|
103
|
+
receiver_constraint: "Grape::Validations::ParamsScope",
|
|
104
|
+
method_names: PARAMS_SCOPE_METHODS,
|
|
105
|
+
self_type: "Grape::Validations::ParamsScope"
|
|
106
|
+
),
|
|
107
|
+
# `desc 'x' do ... end` — the config block `instance_exec`s on a generated
|
|
108
|
+
# `SettingsContainer` subclass (`StrictHashConfiguration.config_class(*Desc::
|
|
109
|
+
# ROUTE_ATTRIBUTES)` in dsl/desc.rb): `detail`, `success`, `failure`, `tags`, `entity`,
|
|
110
|
+
# `hidden`, `is_array`, `consumes`, `headers`, … each take one value and return it.
|
|
111
|
+
# Modelled as the `Grape::DSL::Desc::ConfigContext` sig carrier — a closed surface, so a
|
|
112
|
+
# misspelt or invented setter still reads `call.undefined-method`, matching the runtime
|
|
113
|
+
# NoMethodError.
|
|
114
|
+
Rigor::Plugin::Macro::BlockAsMethod.new(
|
|
115
|
+
receiver_constraint: "Grape::API",
|
|
116
|
+
method_names: %i[desc],
|
|
117
|
+
self_type: "Grape::DSL::Desc::ConfigContext"
|
|
118
|
+
),
|
|
119
|
+
Rigor::Plugin::Macro::BlockAsMethod.new(
|
|
120
|
+
receiver_constraint: "Grape::API::Instance",
|
|
121
|
+
method_names: %i[desc],
|
|
122
|
+
self_type: "Grape::DSL::Desc::ConfigContext"
|
|
123
|
+
),
|
|
124
|
+
# Verb bodies run inside `Grape::Endpoint` instances.
|
|
125
|
+
Rigor::Plugin::Macro::BlockAsMethod.new(
|
|
126
|
+
receiver_constraint: "Grape::API",
|
|
127
|
+
method_names: VERB_METHODS,
|
|
128
|
+
self_type: "Grape::Endpoint"
|
|
129
|
+
),
|
|
130
|
+
Rigor::Plugin::Macro::BlockAsMethod.new(
|
|
131
|
+
receiver_constraint: "Grape::API::Instance",
|
|
132
|
+
method_names: VERB_METHODS,
|
|
133
|
+
self_type: "Grape::Endpoint"
|
|
134
|
+
)
|
|
135
|
+
]
|
|
136
|
+
)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
Rigor::Plugin.register(Grape)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Gem entry point. Required by Rigor's plugin loader when `.rigor.yml` lists `rigor-grape` 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/grape.rb` performs at load time.
|
|
6
|
+
require_relative "rigor/plugin/grape"
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# Bundled RBS for the Grape / grape-entity declaration DSL (issue #1099).
|
|
2
|
+
#
|
|
3
|
+
# Grape's class-level endpoint DSL is dynamic at runtime: `Grape::API` subclasses forward every
|
|
4
|
+
# declaration call to the base `Grape::API::Instance` class object via `delegate_missing_to` /
|
|
5
|
+
# `override_all_methods!` (`lib/grape/api.rb`), and the Instance class gets the real definitions
|
|
6
|
+
# from the `included do ... end` bodies of `Grape::DSL::{Routing,Validations,Configuration,
|
|
7
|
+
# Helpers,Callbacks,Middleware,RequestResponse}`. Both sides answer the same singleton surface, so
|
|
8
|
+
# the signatures live once in `Grape::DSL::ClassMethods` and are `extend`ed onto both classes.
|
|
9
|
+
#
|
|
10
|
+
# Return carriers follow the runtime implementation (grape 2.4.0, grape-entity 1.0): setup-style
|
|
11
|
+
# declarations return the bookkeeping collection or the stored setting value, so `::Object?` /
|
|
12
|
+
# `::Array[untyped]` is the honest reading — `void` would be dishonest AND is collapsed to
|
|
13
|
+
# `Dynamic[top]` by the engine's void-value-use recovery, which is exactly what this plugin exists
|
|
14
|
+
# to prevent.
|
|
15
|
+
#
|
|
16
|
+
# Provenance (docs/agents/type-authoring.md): `rigor sig-gen` cannot produce this file — the DSL
|
|
17
|
+
# methods it declares have no `def` in the gems' source (they are generated through
|
|
18
|
+
# `override_all_methods!` / `delegate_missing_to` / `StrictHashConfiguration`), so every entry was
|
|
19
|
+
# hand-derived by reading the grape 2.4.x / grape-entity 1.0 source. Members that do not exist at
|
|
20
|
+
# that version's runtime location are deliberately absent — declaring them would let a genuinely
|
|
21
|
+
# failing call resolve silently.
|
|
22
|
+
#
|
|
23
|
+
# Block `self` bindings are NOT modelled here — they come from the manifest's `block_as_methods`
|
|
24
|
+
# entries (`params` bodies on `Grape::Validations::ParamsScope`, `namespace` bodies on the
|
|
25
|
+
# `Grape::API::Instance` class object, verb bodies on `Grape::Endpoint`).
|
|
26
|
+
|
|
27
|
+
module Grape
|
|
28
|
+
module DSL
|
|
29
|
+
# Class-level declaration surface shared by `Grape::API` subclasses and `Grape::API::Instance`.
|
|
30
|
+
module ClassMethods
|
|
31
|
+
# Validations — `params` opens a `Grape::Validations::ParamsScope` and `instance_eval`s the
|
|
32
|
+
# block on it; returns the new scope (dsl/validations.rb).
|
|
33
|
+
def params: () ?{ () -> untyped } -> Grape::Validations::ParamsScope
|
|
34
|
+
def contract: (?untyped) ?{ () -> untyped } -> ::Object?
|
|
35
|
+
|
|
36
|
+
# Routing — the HTTP verbs are generated over `Grape::HTTP_SUPPORTED_METHODS` and delegate to
|
|
37
|
+
# `route` (`def route(methods, paths = ['/'], route_options = {}, &block)`).
|
|
38
|
+
def get: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
39
|
+
def put: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
40
|
+
def post: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
41
|
+
def delete: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
42
|
+
def head: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
43
|
+
def patch: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
44
|
+
def options: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
45
|
+
def route: (untyped, ?untyped, ?untyped) ?{ () -> untyped } -> ::Object?
|
|
46
|
+
|
|
47
|
+
# Namespace family — `namespace`/`scope`/`route_param`/`version`/`given`/`mounted`
|
|
48
|
+
# `instance_eval` their block on the Instance class object and return the block's value.
|
|
49
|
+
# `group`/`resource`/`resources`/`segment` are aliases of `namespace`; `scope` routes
|
|
50
|
+
# through `within_namespace { nest(block) }` (dsl/routing.rb).
|
|
51
|
+
def namespace: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
52
|
+
def route_param: (untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
53
|
+
def group: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
54
|
+
def resource: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
55
|
+
def resources: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
56
|
+
def segment: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
57
|
+
def version: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
58
|
+
def given: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
59
|
+
def mounted: () { () -> untyped } -> ::Object?
|
|
60
|
+
def mount: (untyped, *untyped) -> ::Object?
|
|
61
|
+
def scope: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
62
|
+
def prefix: (?untyped) -> ::Object?
|
|
63
|
+
|
|
64
|
+
# Settings / configuration (dsl/settings.rb, dsl/configuration.rb).
|
|
65
|
+
def route_setting: (untyped, ?untyped) -> ::Object?
|
|
66
|
+
def unset_route_setting: (untyped) -> ::Object?
|
|
67
|
+
def global_setting: (untyped, ?untyped) -> ::Object?
|
|
68
|
+
def unset_global_setting: (untyped) -> ::Object?
|
|
69
|
+
# `description` / `entity` / `detail` / `failure` / `success` and friends are NOT API-level
|
|
70
|
+
# methods — they belong to the anonymous `config_context` a `desc` block `instance_exec`s on
|
|
71
|
+
# (`Grape::Util::StrictHashConfiguration`). That surface is deferred (README); declaring the
|
|
72
|
+
# names here would silently resolve calls that fail at runtime.
|
|
73
|
+
def desc: (untyped, ?untyped) ?{ () -> untyped } -> ::Object?
|
|
74
|
+
def content_type: (untyped, untyped) -> ::Object?
|
|
75
|
+
def default_format: (?untyped) -> ::Object?
|
|
76
|
+
def format: (?untyped) -> ::Object?
|
|
77
|
+
def formatter: (untyped, untyped) -> ::Object?
|
|
78
|
+
def parser: (untyped, untyped) -> ::Object?
|
|
79
|
+
def default_error_formatter: (?untyped) -> ::Object?
|
|
80
|
+
def default_error_status: (?untyped) -> ::Object?
|
|
81
|
+
def error_formatter: (untyped, untyped) -> ::Object?
|
|
82
|
+
def cascade: (?untyped) -> ::Object?
|
|
83
|
+
def do_not_route_head!: () -> ::Object?
|
|
84
|
+
def do_not_route_options!: () -> ::Object?
|
|
85
|
+
def do_not_document!: () -> ::Object?
|
|
86
|
+
def http_basic: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
87
|
+
def auth: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
88
|
+
def http_digest: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
89
|
+
def rescue_from: (*untyped, **untyped) ?{ (*untyped) -> untyped } -> ::Object?
|
|
90
|
+
# `represent` forwards to `Entity.represent`, whose result is an entity, an array of
|
|
91
|
+
# entities, or a `{root => inner}` Hash depending on the call — untyped is the honest
|
|
92
|
+
# carrier (a `::Object` return invents `undefined method` findings on every chained call).
|
|
93
|
+
# Runtime arity is `represent(model_class, options)` (dsl/request_response.rb).
|
|
94
|
+
def represent: (untyped, untyped) -> untyped
|
|
95
|
+
|
|
96
|
+
# Helpers / middleware / callbacks.
|
|
97
|
+
def helpers: (*untyped) ?{ () -> untyped } -> ::Object?
|
|
98
|
+
def use: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
99
|
+
def middleware: () -> ::Object?
|
|
100
|
+
def insert_before: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
101
|
+
def insert_after: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
102
|
+
def before: () { () -> untyped } -> ::Object?
|
|
103
|
+
def before_validation: () { () -> untyped } -> ::Object?
|
|
104
|
+
def after_validation: () { () -> untyped } -> ::Object?
|
|
105
|
+
def after: () { () -> untyped } -> ::Object?
|
|
106
|
+
def finally: () { () -> untyped } -> ::Object?
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
module Desc
|
|
110
|
+
# The `instance_exec` target of a `desc 'x' do ... end` config block. At runtime this is an
|
|
111
|
+
# anonymous class built by `StrictHashConfiguration.config_class(*Desc::ROUTE_ATTRIBUTES)`
|
|
112
|
+
# (`dsl/desc.rb` `desc_container`) — a CLOSED surface of one-argument setters that store and
|
|
113
|
+
# return the assigned value (`@settings[name] = new_value`), plus the `success`/`failure`
|
|
114
|
+
# aliases singleton-defined on the context. Names outside `ROUTE_ATTRIBUTES` raise
|
|
115
|
+
# `NoMethodError` at runtime, so this receiver stays out of `open_receivers`: an undeclared
|
|
116
|
+
# call inside a `desc` block genuinely fails.
|
|
117
|
+
class ConfigContext
|
|
118
|
+
def body_name: (untyped) -> ::Object?
|
|
119
|
+
def consumes: (untyped) -> ::Object?
|
|
120
|
+
def default: (untyped) -> ::Object?
|
|
121
|
+
def deprecated: (untyped) -> ::Object?
|
|
122
|
+
def description: (untyped) -> ::Object?
|
|
123
|
+
def detail: (untyped) -> ::Object?
|
|
124
|
+
def entity: (untyped) -> ::Object?
|
|
125
|
+
def headers: (untyped) -> ::Object?
|
|
126
|
+
def hidden: (untyped) -> ::Object?
|
|
127
|
+
def http_codes: (untyped) -> ::Object?
|
|
128
|
+
def is_array: (untyped) -> ::Object?
|
|
129
|
+
def named: (untyped) -> ::Object?
|
|
130
|
+
def nickname: (untyped) -> ::Object?
|
|
131
|
+
def params: (untyped) -> ::Object?
|
|
132
|
+
def produces: (untyped) -> ::Object?
|
|
133
|
+
def security: (untyped) -> ::Object?
|
|
134
|
+
def summary: (untyped) -> ::Object?
|
|
135
|
+
def tags: (untyped) -> ::Object?
|
|
136
|
+
def success: (*untyped) -> ::Object?
|
|
137
|
+
def failure: (*untyped) -> ::Object?
|
|
138
|
+
def configuration: () -> untyped
|
|
139
|
+
def to_hash: () -> ::Hash[untyped, untyped]
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
class API
|
|
145
|
+
extend DSL::ClassMethods
|
|
146
|
+
|
|
147
|
+
# The class object a `Grape::API` subclass's declaration calls are forwarded to. `namespace`
|
|
148
|
+
# bodies `instance_eval` on this class object, so the same `extend`ed surface covers calls made
|
|
149
|
+
# inside them.
|
|
150
|
+
class Instance
|
|
151
|
+
extend DSL::ClassMethods
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
module Validations
|
|
156
|
+
# The receiver `params`/`requires`/`optional`/`given`/`with` blocks `instance_eval` on. Its
|
|
157
|
+
# DSL lives in `Grape::DSL::Parameters`; the declarations here cover the block-relevant and
|
|
158
|
+
# commonly-called subset.
|
|
159
|
+
class ParamsScope
|
|
160
|
+
def requires: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
161
|
+
def optional: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
162
|
+
def given: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
163
|
+
def with: (*untyped, **untyped) ?{ () -> untyped } -> ::Object?
|
|
164
|
+
def use: (*untyped) -> ::Object?
|
|
165
|
+
def mutually_exclusive: (*untyped) -> ::Object?
|
|
166
|
+
def exactly_one_of: (*untyped) -> ::Object?
|
|
167
|
+
def at_least_one_of: (*untyped) -> ::Object?
|
|
168
|
+
def all_or_none_of: (*untyped) -> ::Object?
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Runtime route context — verb bodies execute as `Grape::Endpoint` instance methods
|
|
173
|
+
# (`Grape::Endpoint#run` evaluates the stored block inside the endpoint instance). The methods
|
|
174
|
+
# here are `Grape::DSL::InsideRoute`, `Grape::DSL::Headers`, `Grape::DSL::Settings`, and the
|
|
175
|
+
# `def_delegators :request` surface (`params`/`headers`/`cookies`).
|
|
176
|
+
class Endpoint
|
|
177
|
+
def params: () -> ::Hash[untyped, untyped]
|
|
178
|
+
def headers: () -> ::Hash[untyped, untyped]
|
|
179
|
+
# `Endpoint#cookies` delegates to `Grape::Request#cookies`, which builds a `Grape::Cookies`
|
|
180
|
+
# wrapper — not a Hash (`lib/grape/cookies.rb`, `lib/grape/request.rb`).
|
|
181
|
+
def cookies: () -> Grape::Cookies
|
|
182
|
+
def env: () -> ::Hash[untyped, untyped]
|
|
183
|
+
# `request` is a `Grape::Request` (Rack::Request subclass) at runtime — untyped rather than
|
|
184
|
+
# `::Object` so `request.params`/`request.GET` chains don't read as undefined-method findings.
|
|
185
|
+
def request: () -> untyped
|
|
186
|
+
def declared: (*untyped, **untyped) -> ::Hash[untyped, untyped]
|
|
187
|
+
def version: () -> ::Object?
|
|
188
|
+
def error!: (*untyped, **untyped) -> bot
|
|
189
|
+
def redirect: (untyped url, ?permanent: untyped, ?body: untyped) -> ::Object?
|
|
190
|
+
def status: (?untyped) -> ::Object?
|
|
191
|
+
def content_type: (?untyped) -> ::Object?
|
|
192
|
+
def body: (?untyped) -> ::Object?
|
|
193
|
+
# `present` returns the representation (entity, Hash, or the bare object) — untyped.
|
|
194
|
+
def present: (*untyped, **untyped) -> untyped
|
|
195
|
+
# `route` is the `Grape::Router::Route` for the current endpoint — untyped.
|
|
196
|
+
def route: () -> untyped
|
|
197
|
+
def header: (?untyped, ?untyped) -> ::Object?
|
|
198
|
+
def route_setting: (untyped, ?untyped) -> ::Object?
|
|
199
|
+
def stream: (?untyped) -> ::Object?
|
|
200
|
+
def sendfile: (?untyped) -> ::Object?
|
|
201
|
+
# `error_response` lives on `Grape::Middleware::Error`, not on the endpoint — not declared here.
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# The Rack-cookie wrapper `Grape::Request#cookies` returns (`def_delegators :cookies` for `[]`
|
|
205
|
+
# and `each`, plus its own `[]=` / `delete` / `response_cookies`). Not a Hash.
|
|
206
|
+
class Cookies
|
|
207
|
+
def []: (untyped) -> untyped
|
|
208
|
+
def []=: (untyped, untyped) -> untyped
|
|
209
|
+
def each: (*untyped) ?{ (*untyped) -> untyped } -> untyped
|
|
210
|
+
def response_cookies: () { (untyped, untyped) -> untyped } -> untyped
|
|
211
|
+
def delete: (untyped, **untyped) -> untyped
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# grape-entity's declaration target (`class Foo < Grape::Entity`). `expose` bodies run via
|
|
215
|
+
# `block.call` — `self` stays the Entity subclass's class object — so nested `expose` calls
|
|
216
|
+
# resolve through the same singleton surface without a `block_as_methods` entry.
|
|
217
|
+
class Entity
|
|
218
|
+
def self.expose: (*untyped, **untyped) ?{ () -> untyped } -> ::Array[untyped]
|
|
219
|
+
def self.unexpose: (*untyped) -> ::Object?
|
|
220
|
+
def self.unexpose_all: () -> ::Object?
|
|
221
|
+
def self.with_options: (untyped) { () -> untyped } -> ::Object?
|
|
222
|
+
def self.documentation: () -> ::Hash[untyped, untyped]
|
|
223
|
+
# Returns `formatters[name.to_sym] = block` — the registered Proc.
|
|
224
|
+
def self.format_with: (untyped) { (untyped) -> untyped } -> ::Proc
|
|
225
|
+
def self.root: (untyped, ?untyped) -> ::Object?
|
|
226
|
+
def self.root_element: (untyped) -> ::Object?
|
|
227
|
+
# Result is an Entity instance, an Array of them, or a `{root => inner}` Hash
|
|
228
|
+
# (`lib/grape_entity/entity.rb` `self.represent`) — untyped, not `::Object`, so chained
|
|
229
|
+
# `serializable_hash` / `map` / exposed-attribute reads stay quiet.
|
|
230
|
+
def self.represent: (*untyped, **untyped) -> untyped
|
|
231
|
+
def self.present_collection: (?untyped, ?untyped) -> ::Object?
|
|
232
|
+
# Runtime returns `Exposure::NestingExposure::NestedExposures` — an `Enumerable` wrapper with
|
|
233
|
+
# `find_by` / `select_by` / `delete_by` that Array does not have.
|
|
234
|
+
def self.root_exposures: () -> Exposure::NestingExposure::NestedExposures
|
|
235
|
+
|
|
236
|
+
# The instance-side output surface — `serializable_hash` is the primary representation
|
|
237
|
+
# output (`nil` when the wrapped object is nil); `as_json`/`to_json` delegate to it.
|
|
238
|
+
def serializable_hash: (?untyped) -> ::Hash[untyped, untyped]?
|
|
239
|
+
def as_json: (*untyped, **untyped) -> untyped
|
|
240
|
+
|
|
241
|
+
module Exposure
|
|
242
|
+
class NestingExposure
|
|
243
|
+
# `Enumerable` wrapper over the exposure list (grape-entity `nested_exposures.rb`):
|
|
244
|
+
# `each`/`to_ary`/`to_a`/`[]`/`size`/`empty?`/`==` delegate to the inner Array, and
|
|
245
|
+
# `find_by`/`select_by`/`delete_by`/`<<`/`clear` are its own API.
|
|
246
|
+
class NestedExposures
|
|
247
|
+
include Enumerable[untyped]
|
|
248
|
+
def find_by: (untyped) -> untyped
|
|
249
|
+
def select_by: (untyped) -> untyped
|
|
250
|
+
def <<: (untyped) -> untyped
|
|
251
|
+
def delete_by: (*untyped) -> untyped
|
|
252
|
+
def clear: () -> untyped
|
|
253
|
+
def to_ary: () -> ::Array[untyped]
|
|
254
|
+
def to_a: () -> ::Array[untyped]
|
|
255
|
+
def []: (*untyped) -> untyped
|
|
256
|
+
def ==: (untyped) -> bool
|
|
257
|
+
def size: () -> ::Integer
|
|
258
|
+
def empty?: () -> bool
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
|
@@ -40,6 +40,21 @@ module Rigor
|
|
|
40
40
|
# required: ...` declarations.
|
|
41
41
|
# - No user-facing diagnostics yet.
|
|
42
42
|
#
|
|
43
|
+
# ## Shipped DSL signature (`sig/graphql.rbs`)
|
|
44
|
+
#
|
|
45
|
+
# Since graphql-ruby ships no RBS, the manifest's `signature_paths:` contributes the class-level
|
|
46
|
+
# DSL surface — `field`/`argument`/`value`/`implements`/`description`/`graphql_name` and friends —
|
|
47
|
+
# following graphql-ruby's real `Member`-rooted ancestry so subclass bodies stop reading every
|
|
48
|
+
# DSL call as `Dynamic[top]`. Return types are the real carriers (`field` → `Schema::Field`,
|
|
49
|
+
# `Enum.value` → `Schema::EnumValue`, setter/getter macros → their configured value) rather than
|
|
50
|
+
# `void`, which the engine recovers as `top`. Scope and deferrals are documented at the top of
|
|
51
|
+
# the sig file.
|
|
52
|
+
#
|
|
53
|
+
# The declared classes stay in `open_receivers:` because graphql-ruby's real surface is open:
|
|
54
|
+
# schema plugins (`use`-able extensions) and user base classes add class-level DSL methods this
|
|
55
|
+
# signature does not enumerate, so `call.undefined-method` must not read these classes as
|
|
56
|
+
# closed.
|
|
57
|
+
#
|
|
43
58
|
# ## Deferred (demand-driven)
|
|
44
59
|
#
|
|
45
60
|
# - **`resolver:` / `mutation:` reroute** recognition.
|
|
@@ -51,11 +66,66 @@ module Rigor
|
|
|
51
66
|
manifest(
|
|
52
67
|
id: "graphql",
|
|
53
68
|
target_gems: ["graphql"],
|
|
54
|
-
|
|
69
|
+
# 0.2.0, 2026-09-20 (#1100) — `signature_paths:` contributes the graphql-ruby class-level DSL
|
|
70
|
+
# surface (`field`/`argument`/`value`/…), typed with the real carriers (`Field`/`Argument`/
|
|
71
|
+
# `EnumValue`/…) so DSL calls stop reading `Dynamic[top]` inside recognised subclasses.
|
|
72
|
+
version: "0.2.0",
|
|
55
73
|
description: "Recognises `class T < GraphQL::Schema::{Object,Enum,InputObject,Mutation}` " \
|
|
56
74
|
"subclasses; publishes the per-type field-type table, the per-enum value " \
|
|
57
75
|
"list, the per-input-object argument table, and the per-mutation arguments+fields " \
|
|
58
|
-
"table.",
|
|
76
|
+
"table; ships the graphql-ruby class-level DSL signature surface.",
|
|
77
|
+
signature_paths: ["sig"],
|
|
78
|
+
# ADR-43 WD4 — the classes the bundled sig covers completely enough that a Ruby-source subclass
|
|
79
|
+
# (`class PostType < GraphQL::Schema::Object`) may bridge inherited calls to the RBS ancestor.
|
|
80
|
+
# Listing one turns on `call.undefined-method`/arity checks for inherited DSL calls on every
|
|
81
|
+
# subclass — justified here because the sig IS the authority (graphql-ruby ships none).
|
|
82
|
+
rbs_complete_ancestors: %w[
|
|
83
|
+
GraphQL::Schema
|
|
84
|
+
GraphQL::Schema::Member
|
|
85
|
+
GraphQL::Schema::Object
|
|
86
|
+
GraphQL::Schema::Resolver
|
|
87
|
+
GraphQL::Schema::Mutation
|
|
88
|
+
GraphQL::Schema::RelayClassicMutation
|
|
89
|
+
GraphQL::Schema::Subscription
|
|
90
|
+
GraphQL::Schema::InputObject
|
|
91
|
+
GraphQL::Schema::Enum
|
|
92
|
+
GraphQL::Schema::EnumValue
|
|
93
|
+
GraphQL::Schema::Union
|
|
94
|
+
GraphQL::Schema::Scalar
|
|
95
|
+
GraphQL::Schema::Directive
|
|
96
|
+
GraphQL::Schema::Field
|
|
97
|
+
GraphQL::Schema::Argument
|
|
98
|
+
GraphQL::Dataloader::Source
|
|
99
|
+
GraphQL::Types::Relay::BaseConnection
|
|
100
|
+
GraphQL::Types::Relay::BaseEdge
|
|
101
|
+
GraphQL::Types::Relay::PageInfo
|
|
102
|
+
GraphQL::Types::Relay::BaseField
|
|
103
|
+
],
|
|
104
|
+
open_receivers: %w[
|
|
105
|
+
GraphQL::Schema
|
|
106
|
+
GraphQL::Schema::Member
|
|
107
|
+
GraphQL::Schema::Object
|
|
108
|
+
GraphQL::Schema::Resolver
|
|
109
|
+
GraphQL::Schema::Mutation
|
|
110
|
+
GraphQL::Schema::RelayClassicMutation
|
|
111
|
+
GraphQL::Schema::Subscription
|
|
112
|
+
GraphQL::Schema::InputObject
|
|
113
|
+
GraphQL::Schema::Enum
|
|
114
|
+
GraphQL::Schema::EnumValue
|
|
115
|
+
GraphQL::Schema::Union
|
|
116
|
+
GraphQL::Schema::Scalar
|
|
117
|
+
GraphQL::Schema::Directive
|
|
118
|
+
GraphQL::Schema::Field
|
|
119
|
+
GraphQL::Schema::Argument
|
|
120
|
+
GraphQL::Schema::Interface
|
|
121
|
+
GraphQL::Query
|
|
122
|
+
GraphQL::Query::Context
|
|
123
|
+
GraphQL::Dataloader
|
|
124
|
+
GraphQL::Dataloader::Source
|
|
125
|
+
GraphQL::Types::Relay::BaseConnection
|
|
126
|
+
GraphQL::Types::Relay::BaseEdge
|
|
127
|
+
GraphQL::Types::Relay::BaseField
|
|
128
|
+
],
|
|
59
129
|
produces: %i[graphql_type_table graphql_enum_table graphql_input_object_table graphql_mutation_table]
|
|
60
130
|
)
|
|
61
131
|
|