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
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
# graphql-ruby class-level DSL surface — bundled by rigor-graphql via
|
|
2
|
+
# the manifest's `signature_paths:` (ADR-25).
|
|
3
|
+
#
|
|
4
|
+
# graphql-ruby ships no RBS of its own, so without this file every
|
|
5
|
+
# `field`/`argument`/`value`/`implements`/`description` call inside a
|
|
6
|
+
# `GraphQL::Schema::*` subclass reads Dynamic[top] — ~5k implicit-self
|
|
7
|
+
# sites on the GitLab checkout alone
|
|
8
|
+
# (docs/notes/20260919-survey-typing-holes.md).
|
|
9
|
+
#
|
|
10
|
+
# Return types follow graphql-ruby's real implementations: `field`
|
|
11
|
+
# returns the created `Schema::Field`, `argument` the created
|
|
12
|
+
# `Schema::Argument`, `Enum.value` the `Schema::EnumValue`, the
|
|
13
|
+
# registration macros on `Schema` return the collection or object they
|
|
14
|
+
# registered, and the setter/getter pairs (`description`,
|
|
15
|
+
# `graphql_name`, `type`, `null`, …) return their configured value.
|
|
16
|
+
# `void` is deliberately avoided — these expressions are ordinary API
|
|
17
|
+
# (a stored `field` result is a real `Field`), and the engine recovers
|
|
18
|
+
# a `void` return as `top`, which would keep every DSL call in the
|
|
19
|
+
# Dynamic census this signature exists to drain.
|
|
20
|
+
#
|
|
21
|
+
# The ancestry follows graphql-ruby's real hierarchy:
|
|
22
|
+
# `Mutation`/`Subscription`/`RelayClassicMutation < Resolver`,
|
|
23
|
+
# `Object`/`InputObject`/`Enum`/`Union`/`Scalar`/`EnumValue <
|
|
24
|
+
# Member`, and `Field`/`Argument` standalone (each `include`s
|
|
25
|
+
# `Member::HasArguments` for their own `argument` DSL). The shared
|
|
26
|
+
# class-level DSL lives on the `Member::*` mixin modules exactly as
|
|
27
|
+
# graphql-ruby arranges it, so user subclasses pick it up by RBS
|
|
28
|
+
# ancestry rather than per-class duplication.
|
|
29
|
+
#
|
|
30
|
+
# Deferred, deliberately:
|
|
31
|
+
#
|
|
32
|
+
# - `include GraphQL::Schema::Interface` — graphql-ruby wires the DSL
|
|
33
|
+
# onto the includer through `Interface.included` →
|
|
34
|
+
# `base.extend(DefinitionMethods)`, an include-time effect RBS
|
|
35
|
+
# cannot express, so `field` inside interface modules stays opaque.
|
|
36
|
+
# `Interface::DefinitionMethods` is still declared so an `extend`
|
|
37
|
+
# of it resolves.
|
|
38
|
+
# - `field ... do ... end` / `argument ... do ... end` block bodies —
|
|
39
|
+
# graphql-ruby `instance_eval`s a zero-arity definition block on the
|
|
40
|
+
# new Field/Argument, and no engine mechanism currently rebinds a
|
|
41
|
+
# block's `self` to a declared block `self:` type. The one-parameter
|
|
42
|
+
# form (`field(:x) { |f| f.argument }`) types through the declared
|
|
43
|
+
# block parameter.
|
|
44
|
+
# - `Schema.execute` / `Schema.multiplex` result typing and
|
|
45
|
+
# resolver-method return checking — tracked by issue #136; they are
|
|
46
|
+
# declared `-> untyped` here so dispatch resolves, but the honestly
|
|
47
|
+
# opaque return is unchanged.
|
|
48
|
+
|
|
49
|
+
module GraphQL
|
|
50
|
+
class Error < ::StandardError
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class ExecutionError < GraphQL::Error
|
|
54
|
+
def initialize: (untyped message, **untyped opts) -> void
|
|
55
|
+
def extensions: () -> ::Hash[untyped, untyped]
|
|
56
|
+
def to_h: () -> ::Hash[untyped, untyped]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class AnalysisError < GraphQL::Error
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
class RequiredImplementationMissingError < GraphQL::Error
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class UnauthorizedError < GraphQL::Error
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class Dataloader
|
|
69
|
+
def with: (untyped source_class, *untyped batch_args) -> untyped
|
|
70
|
+
def load: (untyped source_class, untyped id) -> untyped
|
|
71
|
+
def load_all: (untyped source_class, untyped ids) -> ::Array[untyped]
|
|
72
|
+
def append: (untyped job) -> untyped
|
|
73
|
+
def run: () -> untyped
|
|
74
|
+
def run_all: () -> untyped
|
|
75
|
+
def merge!: (untyped) -> untyped
|
|
76
|
+
|
|
77
|
+
class Source
|
|
78
|
+
def load: (untyped input) -> untyped
|
|
79
|
+
def fetch: (untyped inputs) -> ::Array[untyped]
|
|
80
|
+
def result_key_for: (untyped input) -> untyped
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
class Query
|
|
85
|
+
def context: () -> GraphQL::Query::Context
|
|
86
|
+
|
|
87
|
+
class Context
|
|
88
|
+
def []: (untyped key) -> untyped
|
|
89
|
+
def []=: (untyped key, untyped value) -> untyped
|
|
90
|
+
def fetch: (untyped key, ?untyped default) -> untyped
|
|
91
|
+
def key?: (untyped key) -> bool
|
|
92
|
+
def dig: (untyped key, *untyped rest) -> untyped
|
|
93
|
+
def namespace: (untyped ns) -> untyped
|
|
94
|
+
def scoped_set!: (untyped key, untyped value) -> untyped
|
|
95
|
+
def to_h: () -> ::Hash[untyped, untyped]
|
|
96
|
+
def schema: () -> singleton(GraphQL::Schema)
|
|
97
|
+
def query: () -> GraphQL::Query
|
|
98
|
+
def object: () -> untyped
|
|
99
|
+
def dataloader: () -> GraphQL::Dataloader
|
|
100
|
+
def errors: () -> ::Array[untyped]
|
|
101
|
+
def add_error: (untyped error) -> untyped
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
class Schema
|
|
106
|
+
# Schema-class registration DSL (`class AppSchema < GraphQL::Schema`).
|
|
107
|
+
# Setter/getter pairs return the configured value; the `<<`-style
|
|
108
|
+
# registrars return the collection they pushed onto.
|
|
109
|
+
def self.use: (untyped plugin, **untyped kwargs) -> ::Array[untyped]
|
|
110
|
+
def self.plugins: () -> ::Array[untyped]
|
|
111
|
+
def self.query: (?Class? new_query_object) ?{ () -> untyped } -> Class?
|
|
112
|
+
def self.mutation: (?Class? new_mutation_object) ?{ () -> untyped } -> Class?
|
|
113
|
+
def self.subscription: (?Class? new_subscription_object) ?{ () -> untyped } -> Class?
|
|
114
|
+
# Runtime returns the stored Class under a visibility profile, otherwise the
|
|
115
|
+
# `add_type_and_traverse` result — the union is untyped (schema.rb `directive`).
|
|
116
|
+
def self.directive: (untyped new_directive) -> untyped
|
|
117
|
+
def self.directives: (*untyped) -> ::Hash[untyped, untyped]
|
|
118
|
+
def self.orphan_types: (*untyped new_orphan_types) -> ::Array[untyped]
|
|
119
|
+
# `mode:` as an Array re-enters once per element and returns that Array; the
|
|
120
|
+
# default path ends in `add_trace_options_for`, which returns nil.
|
|
121
|
+
def self.trace_with: (untyped trace_mod, **untyped options) -> ::Array[untyped]?
|
|
122
|
+
def self.instrument: (untyped instrument_step, untyped instrumenter, ?untyped options) -> ::Array[untyped]
|
|
123
|
+
# Returns `err_classes.each`'s receiver — the exception-class Array, not the
|
|
124
|
+
# handlers Hash (schema.rb `rescue_from`).
|
|
125
|
+
def self.rescue_from: (*untyped err_classes) ?{ (untyped err) -> void } -> ::Array[untyped]
|
|
126
|
+
def self.error_handlers: () -> ::Hash[untyped, untyped]
|
|
127
|
+
def self.max_depth: (?Integer? new_max_depth, ?count_introspection_fields: bool) -> Integer?
|
|
128
|
+
def self.max_complexity: (?untyped new_max_complexity, ?count_introspection_fields: bool) -> untyped
|
|
129
|
+
def self.max_query_string_tokens: (?Integer? new_max_tokens) -> Integer?
|
|
130
|
+
def self.validate_max_errors: (?Integer? new_validate_max_errors) -> Integer?
|
|
131
|
+
|
|
132
|
+
def self.error_bubbling: (?bool? new_error_bubbling) -> bool
|
|
133
|
+
def self.default_max_page_size: (?Integer? new_default_max_page_size) -> Integer?
|
|
134
|
+
def self.default_page_size: (?Integer? new_default_page_size) -> Integer?
|
|
135
|
+
|
|
136
|
+
def self.cursor_encoder: (?Class? new_encoder) -> Class?
|
|
137
|
+
def self.context_class: (?Class? new_context_class) -> Class?
|
|
138
|
+
def self.connections: (?untyped new_connections) -> untyped
|
|
139
|
+
def self.introspection: (?Module? new_introspection_namespace) -> Module?
|
|
140
|
+
def self.query_analyzer: (untyped new_analyzer) -> ::Array[untyped]
|
|
141
|
+
def self.multiplex_analyzer: (untyped new_analyzer) -> ::Array[untyped]
|
|
142
|
+
def self.query_analyzers: () -> ::Array[untyped]
|
|
143
|
+
def self.multiplex_analyzers: () -> ::Array[untyped]
|
|
144
|
+
def self.visible?: (untyped member, untyped ctx) -> bool
|
|
145
|
+
def self.id_from_object: (untyped application_object, untyped graphql_type, untyped context) -> String?
|
|
146
|
+
def self.object_from_id: (untyped object_id, untyped context) -> untyped
|
|
147
|
+
def self.resolve_type: (untyped abstract_type, untyped obj, untyped ctx) -> untyped
|
|
148
|
+
def self.type_error: (untyped type_error, untyped ctx) -> untyped
|
|
149
|
+
def self.types: (?untyped context) -> ::Hash[untyped, untyped]
|
|
150
|
+
def self.execute: (*untyped) -> untyped
|
|
151
|
+
def self.multiplex: (*untyped) -> untyped
|
|
152
|
+
|
|
153
|
+
# Shared class-level DSL inherited by every schema member class.
|
|
154
|
+
class Member
|
|
155
|
+
module BaseDSLMethods
|
|
156
|
+
def description: (?String? new_description) -> String?
|
|
157
|
+
def graphql_name: (?String? new_name) -> String
|
|
158
|
+
def comment: (?String? new_comment) -> String?
|
|
159
|
+
def introspection: (?untyped new_introspection) -> bool
|
|
160
|
+
def introspection?: () -> bool
|
|
161
|
+
def visible?: (untyped context) -> bool
|
|
162
|
+
def authorized?: (untyped object, untyped context) -> bool
|
|
163
|
+
def mutation: (?Class? mutation_class) -> Class?
|
|
164
|
+
def to_graphql: () -> untyped
|
|
165
|
+
def kind: () -> untyped
|
|
166
|
+
def path: () -> String
|
|
167
|
+
end
|
|
168
|
+
extend BaseDSLMethods
|
|
169
|
+
|
|
170
|
+
module HasArguments
|
|
171
|
+
def argument: ( ?untyped arg_name
|
|
172
|
+
, ?untyped type_expr
|
|
173
|
+
, ?untyped desc
|
|
174
|
+
, **untyped kwargs
|
|
175
|
+
) ?{ (GraphQL::Schema::Argument) -> void } -> GraphQL::Schema::Argument
|
|
176
|
+
def add_argument: (GraphQL::Schema::Argument arg_defn) -> GraphQL::Schema::Argument
|
|
177
|
+
def arguments: (?untyped context) -> ::Hash[untyped, untyped]
|
|
178
|
+
def get_argument: (untyped argument_name, ?untyped context) -> GraphQL::Schema::Argument?
|
|
179
|
+
def any_arguments?: () -> bool
|
|
180
|
+
def all_argument_definitions: () -> ::Array[untyped]
|
|
181
|
+
def argument_class: (?Class? new_arg_class) -> Class
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
module HasFields
|
|
185
|
+
def field: ( ?untyped name_positional
|
|
186
|
+
, ?untyped type_positional
|
|
187
|
+
, ?untyped desc_positional
|
|
188
|
+
, **untyped kwargs
|
|
189
|
+
) ?{ (GraphQL::Schema::Field) -> void } -> GraphQL::Schema::Field
|
|
190
|
+
# Runtime ends in a bare `nil` after mutating `own_fields` (has_fields.rb).
|
|
191
|
+
def add_field: (GraphQL::Schema::Field field_defn, **untyped kwargs) -> nil
|
|
192
|
+
def field_class: (?Class? new_field_class) -> Class
|
|
193
|
+
# Ends in `define_singleton_method(field_name)`, which returns the Symbol.
|
|
194
|
+
def global_id_field: (untyped field_name, **untyped kwargs) -> ::Symbol
|
|
195
|
+
def fields: (?untyped context) -> ::Hash[untyped, untyped]
|
|
196
|
+
def get_field: (untyped field_name, ?untyped context) -> GraphQL::Schema::Field?
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
module HasInterfaces
|
|
200
|
+
def implements: (*untyped new_interfaces, **untyped options) -> ::Array[untyped]
|
|
201
|
+
def interfaces: (?untyped context) -> ::Array[untyped]
|
|
202
|
+
def interface_type_memberships: () -> ::Array[untyped]
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
module RelayShortcuts
|
|
206
|
+
def connection_type: () -> Class
|
|
207
|
+
def edge_type: () -> Class
|
|
208
|
+
def connection_type_class: (?Class? new_connection_type_class) -> Class
|
|
209
|
+
def edge_type_class: (?Class? new_edge_type_class) -> Class
|
|
210
|
+
def node_field: (**untyped kwargs) -> GraphQL::Schema::Field
|
|
211
|
+
def nodes_field: (**untyped kwargs) -> GraphQL::Schema::Field
|
|
212
|
+
end
|
|
213
|
+
extend RelayShortcuts
|
|
214
|
+
|
|
215
|
+
module TypeSystemHelpers
|
|
216
|
+
def to_graphql: () -> untyped
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
class Object < Member
|
|
221
|
+
extend Member::HasFields
|
|
222
|
+
extend Member::HasInterfaces
|
|
223
|
+
attr_reader object: untyped
|
|
224
|
+
attr_reader context: GraphQL::Query::Context
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
class Resolver
|
|
228
|
+
module HasPayloadType
|
|
229
|
+
def payload_type: (?Class? new_payload_type) -> Class
|
|
230
|
+
def type: ( ?untyped new_type
|
|
231
|
+
, ?null: bool? null
|
|
232
|
+
) -> untyped
|
|
233
|
+
def type_expr: () -> untyped
|
|
234
|
+
def null: (?bool? allow_null) -> bool
|
|
235
|
+
def field_class: (?Class? new_class) -> Class
|
|
236
|
+
def object_class: (?Class? new_class) -> Class
|
|
237
|
+
end
|
|
238
|
+
extend Member::BaseDSLMethods
|
|
239
|
+
extend Member::HasArguments
|
|
240
|
+
extend HasPayloadType
|
|
241
|
+
|
|
242
|
+
def self.resolve_method: (?Symbol? new_method) -> Symbol
|
|
243
|
+
def self.resolver_method: (?Symbol? new_method_name) -> Symbol
|
|
244
|
+
def self.extras: (?::Array[untyped]? new_extras) -> ::Array[untyped]
|
|
245
|
+
def self.complexity: (?untyped new_complexity) -> untyped
|
|
246
|
+
def self.broadcastable: (untyped new_broadcastable) -> untyped
|
|
247
|
+
def self.broadcastable?: () -> bool?
|
|
248
|
+
def self.max_page_size: (?Integer? new_max_page_size) -> Integer?
|
|
249
|
+
def self.default_page_size: (?Integer? new_default_page_size) -> Integer?
|
|
250
|
+
def self.has_max_page_size?: () -> bool
|
|
251
|
+
def self.has_default_page_size?: () -> bool
|
|
252
|
+
def self.has_scope: (?untyped new_has_scope) -> bool
|
|
253
|
+
def self.field_arguments: (?untyped context) -> ::Hash[untyped, untyped]
|
|
254
|
+
def self.extension: (untyped extension, **untyped options) -> untyped
|
|
255
|
+
def self.extensions: () -> ::Array[untyped]
|
|
256
|
+
def self.authorizes?: (untyped context) -> bool
|
|
257
|
+
|
|
258
|
+
attr_reader object: untyped
|
|
259
|
+
attr_reader context: GraphQL::Query::Context
|
|
260
|
+
attr_reader field: GraphQL::Schema::Field
|
|
261
|
+
def arguments: () -> ::Hash[untyped, untyped]
|
|
262
|
+
def dataloader: () -> GraphQL::Dataloader
|
|
263
|
+
def resolve: (**untyped args) -> untyped
|
|
264
|
+
def ready?: (**untyped args) -> bool
|
|
265
|
+
def authorized?: (**untyped inputs) -> bool
|
|
266
|
+
def load_application_object: (untyped type, untyped id) -> untyped
|
|
267
|
+
def load_application_object_failed!: (untyped err) -> void
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
class Mutation < Resolver
|
|
271
|
+
extend Member::HasFields
|
|
272
|
+
def self.ready?: (**untyped inputs) -> bool
|
|
273
|
+
def self.authorized?: (**untyped inputs) -> bool
|
|
274
|
+
def self.load_application_object: (untyped type, untyped id) -> untyped
|
|
275
|
+
def object: () -> untyped
|
|
276
|
+
def ready?: (**untyped inputs) -> bool
|
|
277
|
+
def authorized?: (**untyped inputs) -> bool
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
class RelayClassicMutation < Mutation
|
|
281
|
+
def self.input_object_class: (?Class? new_class) -> Class
|
|
282
|
+
def self.return_field: () -> untyped
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
class Subscription < Resolver
|
|
286
|
+
extend Member::HasFields
|
|
287
|
+
def self.topic: (?untyped new_topic) -> untyped
|
|
288
|
+
def self.subscription_scope: (?untyped new_scope) -> untyped
|
|
289
|
+
def subscribe: (**untyped args) -> untyped
|
|
290
|
+
def update: (**untyped args) -> untyped
|
|
291
|
+
def unsubscribe: (**untyped args) -> untyped
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
class InputObject < Member
|
|
295
|
+
extend Member::HasArguments
|
|
296
|
+
def self.prepare: (*untyped) -> untyped
|
|
297
|
+
def self.one_of: () -> bool
|
|
298
|
+
def prepare: () -> untyped
|
|
299
|
+
def arguments: () -> untyped
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
class Union < Member
|
|
303
|
+
def self.possible_types: (*untyped new_types, ?context: untyped, **untyped) -> ::Array[untyped]
|
|
304
|
+
def self.get_possible_type: (untyped type_expr, untyped obj, untyped ctx) -> untyped
|
|
305
|
+
def self.resolve_type: (untyped type_expr, untyped obj, untyped ctx) -> untyped
|
|
306
|
+
def self.type_error: (untyped type_error, untyped ctx) -> untyped
|
|
307
|
+
def self.orphan_types: (*untyped new_orphan_types) -> ::Array[untyped]
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
class Enum < Member
|
|
311
|
+
def self.value: (*untyped args, **untyped kwargs) ?{ (EnumValue) -> void } -> EnumValue
|
|
312
|
+
def self.values: (?untyped context) -> ::Hash[untyped, untyped]
|
|
313
|
+
def self.enum_values: (?untyped context) -> ::Array[untyped]
|
|
314
|
+
def self.enum_value_for: (untyped value_name, ?untyped context) -> EnumValue?
|
|
315
|
+
def self.value_from_ruby: (untyped val, ?untyped ctx) -> untyped
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
class EnumValue < Member
|
|
319
|
+
def value: (?untyped new_val) -> untyped
|
|
320
|
+
def deprecation_reason: (?String? new_reason) -> String?
|
|
321
|
+
attr_reader owner: untyped
|
|
322
|
+
attr_reader graphql_name: String
|
|
323
|
+
attr_reader description: String?
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
class Scalar < Member
|
|
327
|
+
def self.coerce_input: (untyped val, untyped ctx) -> untyped
|
|
328
|
+
def self.coerce_result: (untyped val, untyped ctx) -> untyped
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
class Directive < Member
|
|
332
|
+
extend Member::HasArguments
|
|
333
|
+
def self.locations: (*untyped new_locations) -> ::Array[untyped]
|
|
334
|
+
def self.repeatable: (?bool? new_repeatable) -> bool
|
|
335
|
+
def self.on: (*untyped new_locations) -> ::Array[untyped]
|
|
336
|
+
# Runtime takes the runtime object, argument values, and query context
|
|
337
|
+
# (directive.rb `include?` delegates to `static_include?`).
|
|
338
|
+
def self.include?: (untyped object, untyped arguments, untyped context) -> bool
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# `Field`/`Argument` are definition objects, not schema members —
|
|
342
|
+
# they `include HasArguments` so `argument` inside a definition
|
|
343
|
+
# block's one-parameter form (`field(:x) { |f| f.argument }`)
|
|
344
|
+
# resolves on the yielded object.
|
|
345
|
+
class Field
|
|
346
|
+
include Member::HasArguments
|
|
347
|
+
def name: () -> String
|
|
348
|
+
def graphql_name: () -> String
|
|
349
|
+
def type: () -> untyped
|
|
350
|
+
def description: (?String? new_description) -> String?
|
|
351
|
+
def deprecation_reason: (?String? new_reason) -> String?
|
|
352
|
+
def extension: (untyped extension, **untyped options) -> untyped
|
|
353
|
+
def extensions: () -> untyped
|
|
354
|
+
def complexity: (?untyped new_complexity) -> untyped
|
|
355
|
+
def scope: (?untyped new_scope) -> untyped
|
|
356
|
+
def null: (?bool? new_null) -> bool
|
|
357
|
+
def null?: () -> bool
|
|
358
|
+
def method_sym: () -> Symbol
|
|
359
|
+
def method_str: () -> String
|
|
360
|
+
def resolver_method: () -> Symbol
|
|
361
|
+
def owner: () -> untyped
|
|
362
|
+
def connection?: () -> bool
|
|
363
|
+
def max_page_size: () -> Integer?
|
|
364
|
+
def default_page_size: () -> Integer?
|
|
365
|
+
def subscription_scope: (?untyped) -> untyped
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
class Argument
|
|
369
|
+
def keyword: () -> Symbol
|
|
370
|
+
def name: () -> String
|
|
371
|
+
def graphql_name: () -> String
|
|
372
|
+
def type: () -> untyped
|
|
373
|
+
def description: (?String? new_description) -> String?
|
|
374
|
+
def deprecation_reason: (?String? new_reason) -> String?
|
|
375
|
+
def default_value: (?untyped new_default_value) -> untyped
|
|
376
|
+
def default_value?: () -> bool
|
|
377
|
+
def required?: () -> bool
|
|
378
|
+
def loads: () -> untyped
|
|
379
|
+
def as: () -> Symbol
|
|
380
|
+
def prepare: () -> untyped
|
|
381
|
+
def owner: () -> untyped
|
|
382
|
+
def validates: () -> untyped
|
|
383
|
+
def replace_null_with_default?: () -> bool
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
class LateBoundType
|
|
387
|
+
def initialize: (untyped name, ?untyped type_defn) -> void
|
|
388
|
+
def graphql_name: () -> String
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
# The include-time `extend DefinitionMethods` is not modelled —
|
|
392
|
+
# see the file header. `DefinitionMethods` is declared so code that
|
|
393
|
+
# extends it directly resolves the same surface class bodies get.
|
|
394
|
+
module Interface
|
|
395
|
+
module DefinitionMethods
|
|
396
|
+
include Member::BaseDSLMethods
|
|
397
|
+
include Member::HasFields
|
|
398
|
+
include Member::HasInterfaces
|
|
399
|
+
include Member::RelayShortcuts
|
|
400
|
+
def orphan_types: (*untyped new_orphan_types) -> ::Array[untyped]
|
|
401
|
+
def resolve_type: (untyped type_expr, untyped obj, untyped ctx) -> untyped
|
|
402
|
+
def definition_methods: (?Module? other_module) -> untyped
|
|
403
|
+
end
|
|
404
|
+
extend DefinitionMethods
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# graphql-ruby's own scalar / Relay wrapper types, referenced as
|
|
409
|
+
# `field`/`argument` arguments (`field :x, GraphQL::Types::ISO8601DateTime`).
|
|
410
|
+
module Types
|
|
411
|
+
class Boolean < Schema::Scalar
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
class ID < Schema::Scalar
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
class Int < Schema::Scalar
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
class Float < Schema::Scalar
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
class String < Schema::Scalar
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
class BigInt < Schema::Scalar
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
class Decimal < Schema::Scalar
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
class ISO8601Date < Schema::Scalar
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
class ISO8601DateTime < Schema::Scalar
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
class ISO8601DateTimePrecise < Schema::Scalar
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
class JSON < Schema::Scalar
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
class JSONString < Schema::Scalar
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
class Base64Binary < Schema::Scalar
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
module Relay
|
|
451
|
+
class BaseConnection < Schema::Object
|
|
452
|
+
def self.edge_type: (untyped edge_class, **untyped kwargs) -> Class?
|
|
453
|
+
def self.node_type: () -> Class?
|
|
454
|
+
def self.edges_field: (**untyped) -> GraphQL::Schema::Field
|
|
455
|
+
def self.nodes_field: (**untyped) -> GraphQL::Schema::Field
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
class BaseEdge < Schema::Object
|
|
459
|
+
def self.node_type: () -> Class?
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
class PageInfo < Schema::Object
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
class BaseField < Schema::Field
|
|
466
|
+
def self.connection_extension: () -> untyped
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
module Node
|
|
470
|
+
include GraphQL::Schema::Interface
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
module NodeBehaviors
|
|
474
|
+
def object_from_id: (untyped object_id, untyped ctx) -> untyped
|
|
475
|
+
def type_from_object: (untyped obj) -> untyped
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
module HasNodeField
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
module HasNodesField
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
end
|
|
@@ -93,6 +93,7 @@ module Rigor
|
|
|
93
93
|
assert_not_equal: [:literal_then_local, true],
|
|
94
94
|
assert_match: [:regex_then_local, false]
|
|
95
95
|
}.freeze
|
|
96
|
+
Ractor.make_shareable(ASSERT_FORM)
|
|
96
97
|
private_constant :ASSERT_FORM
|
|
97
98
|
|
|
98
99
|
def assert_form_fact(call_node, environment:)
|
|
@@ -126,6 +127,7 @@ module Rigor
|
|
|
126
127
|
wont_equal: [:literal_arg, true],
|
|
127
128
|
must_match: [:regex_arg, false]
|
|
128
129
|
}.freeze
|
|
130
|
+
Ractor.make_shareable(SPEC_MATCHER_FORM)
|
|
129
131
|
private_constant :SPEC_MATCHER_FORM
|
|
130
132
|
|
|
131
133
|
# ADR-37 slice 2 — the method names this analyzer narrows on, for the plugin's
|
|
@@ -109,12 +109,12 @@ module Rigor
|
|
|
109
109
|
services.fact_store.publish(plugin_id: manifest.id, name: :reachability_roots, value: roots)
|
|
110
110
|
end
|
|
111
111
|
|
|
112
|
-
# File-level only: the load-error
|
|
113
|
-
# walk via the node_rule below (ADR-37). The index is lazily loaded + memoised by
|
|
114
|
-
# so both surfaces share one load.
|
|
112
|
+
# File-level only: the load-error disclosure. The per-call policy validation runs over the
|
|
113
|
+
# engine-owned walk via the node_rule below (ADR-37). The index is lazily loaded + memoised by
|
|
114
|
+
# `producer_value`, so both surfaces share one load.
|
|
115
115
|
def diagnostics_for_file(path:, scope:, root:) # rubocop:disable Lint/UnusedMethodArgument
|
|
116
116
|
index = producer_value(:policy_index)
|
|
117
|
-
|
|
117
|
+
disclose_load_error if index.nil? && producer_error(:policy_index)
|
|
118
118
|
|
|
119
119
|
[]
|
|
120
120
|
end
|
|
@@ -130,10 +130,14 @@ module Rigor
|
|
|
130
130
|
|
|
131
131
|
private
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
# Issue #1056 — "the policy index did not load" is a fact about the run's INPUTS, not about the file being
|
|
134
|
+
# analysed, so it is registered rather than returned: see {Plugin::Base#disclose_once} for the
|
|
135
|
+
# channel, the `(plugin id, key)` de-duplication and why the engine positions it at `.rigor.yml:1:1`.
|
|
136
|
+
# Returned from the per-file hook it carried no once-guard at all and repeated on every file.
|
|
137
|
+
def disclose_load_error
|
|
134
138
|
error = producer_error(:policy_index)
|
|
135
|
-
|
|
136
|
-
|
|
139
|
+
disclose_once(
|
|
140
|
+
:policy_index_load_failed,
|
|
137
141
|
message: "rigor-pundit: failed to discover policies: #{error.class}: #{error.message}",
|
|
138
142
|
severity: :warning,
|
|
139
143
|
rule: "load-error"
|
|
@@ -46,10 +46,7 @@ module Rigor
|
|
|
46
46
|
# skipped — the controller/action scope cannot be statically determined there.
|
|
47
47
|
# - View template lazy keys (`t('.key')` inside ERB / Haml / Slim) are validated for key existence and
|
|
48
48
|
# per-locale coverage. Interpolation variable validation is skipped for view templates (the hash may
|
|
49
|
-
# come from controller instance variables not visible in the template).
|
|
50
|
-
# project-wide pass surfaced through the per-file diagnostic hook, so under `--workers` each fork-pool
|
|
51
|
-
# worker re-emits the full set (the same once-per-run limitation the `load-error` path carries);
|
|
52
|
-
# sequential `rigor check` is unaffected.
|
|
49
|
+
# come from controller instance variables not visible in the template).
|
|
53
50
|
# - Pluralization (`t('errors.messages.too_short', count: n)`) is recognised at the call site but the
|
|
54
51
|
# `count` key is not used to validate the locale's pluralization branches.
|
|
55
52
|
# - YAML aliases / merges are accepted (Psych's standard `aliases: true`) but custom Ruby classes
|
|
@@ -106,29 +103,26 @@ module Rigor
|
|
|
106
103
|
@view_search_paths = Array(config.fetch("view_search_paths")).map(&:to_s)
|
|
107
104
|
@configured_locales = Array(config.fetch("configured_locales")).map(&:to_s)
|
|
108
105
|
@load_errors = []
|
|
109
|
-
@load_errors_emitted = false
|
|
110
|
-
@view_diagnostics_emitted = false
|
|
111
106
|
end
|
|
112
107
|
|
|
113
|
-
#
|
|
114
|
-
#
|
|
115
|
-
#
|
|
116
|
-
#
|
|
108
|
+
# Returns no rows of its own: every file-level outcome here is run-scoped. The YAML load errors and the
|
|
109
|
+
# runtime (cache-load) errors are disclosures (#1051); the view-template scan is a positioned batch
|
|
110
|
+
# registered through `#emit_once` (#1060) — its rows name view files that are usually not analysed
|
|
111
|
+
# targets, so no per-file return could own them, and returning them from whichever file an instance
|
|
112
|
+
# saw first repeated the whole batch once per fork-pool worker. Per-call `t('key')` validation runs
|
|
113
|
+
# over the engine-owned walk via the node_rule below (ADR-37). The locale index and view diagnostics
|
|
114
|
+
# are lazily loaded + memoised by `producer_value`, so the repeat registrations are no-ops.
|
|
117
115
|
def diagnostics_for_file(path:, scope:, root:) # rubocop:disable Lint/UnusedMethodArgument
|
|
118
116
|
index = producer_value(:locale_index)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
else
|
|
127
|
-
diagnostics.concat(view_diags)
|
|
128
|
-
end
|
|
129
|
-
@view_diagnostics_emitted = true
|
|
117
|
+
disclose_load_errors unless @load_errors.empty?
|
|
118
|
+
disclose_locale_runtime_error if index.nil? && producer_error(:locale_index)
|
|
119
|
+
view_diags = producer_value(:view_diagnostics) || []
|
|
120
|
+
if (view_err = producer_error(:view_diagnostics))
|
|
121
|
+
disclose_view_runtime_error(view_err)
|
|
122
|
+
else
|
|
123
|
+
emit_once(:view_diagnostics, view_diags)
|
|
130
124
|
end
|
|
131
|
-
|
|
125
|
+
[]
|
|
132
126
|
end
|
|
133
127
|
|
|
134
128
|
# The lazy-key (`t('.key')`) expansion needs the enclosing method (the controller action), supplied
|
|
@@ -211,35 +205,39 @@ module Rigor
|
|
|
211
205
|
end
|
|
212
206
|
|
|
213
207
|
# The runner only invokes `diagnostics_for_file` for Ruby files (`paths:` is filtered to `.rb`). YAML
|
|
214
|
-
# parse errors therefore can't be anchored on the offending locale file directly
|
|
215
|
-
#
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
@
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
path: path, line: 1, column: 1,
|
|
208
|
+
# parse errors therefore can't be anchored on the offending locale file directly, and the row used to
|
|
209
|
+
# be pinned to the first analysed Ruby file — once per plugin INSTANCE, so once per fork-pool worker
|
|
210
|
+
# (#1051). They go through the run-scoped channel instead: keyed by the locale path that failed, so a
|
|
211
|
+
# project with two broken YAML files still discloses both, each exactly once, at `.rigor.yml:1:1`.
|
|
212
|
+
def disclose_load_errors
|
|
213
|
+
@load_errors.each do |err|
|
|
214
|
+
disclose_once(
|
|
215
|
+
"locale-parse:#{err.path}",
|
|
223
216
|
message: "rigor-rails-i18n: failed to parse `#{err.path}`: #{err.message}",
|
|
224
217
|
severity: :warning,
|
|
225
218
|
rule: "load-error"
|
|
226
219
|
)
|
|
227
220
|
end
|
|
221
|
+
nil
|
|
228
222
|
end
|
|
229
223
|
|
|
230
|
-
|
|
224
|
+
# #1051 — both of these say the plugin could not READ something the project configured, which is a
|
|
225
|
+
# run-level fact with no source position; they were repeated on every analysed file (the locale one)
|
|
226
|
+
# or on each instance's first (the view one). A key distinct from the `:view_diagnostics` batch's:
|
|
227
|
+
# the two channels share one registration table per plugin.
|
|
228
|
+
def disclose_locale_runtime_error
|
|
231
229
|
error = producer_error(:locale_index)
|
|
232
|
-
|
|
233
|
-
|
|
230
|
+
disclose_once(
|
|
231
|
+
:locale_index_failed,
|
|
234
232
|
message: "rigor-rails-i18n: failed to load locales: #{error.class}: #{error.message}",
|
|
235
233
|
severity: :warning,
|
|
236
234
|
rule: "load-error"
|
|
237
235
|
)
|
|
238
236
|
end
|
|
239
237
|
|
|
240
|
-
def
|
|
241
|
-
|
|
242
|
-
|
|
238
|
+
def disclose_view_runtime_error(error)
|
|
239
|
+
disclose_once(
|
|
240
|
+
:view_scan_failed,
|
|
243
241
|
message: "rigor-rails-i18n: failed to scan view templates: #{error.class}: #{error.message}",
|
|
244
242
|
severity: :warning,
|
|
245
243
|
rule: "load-error"
|
|
@@ -61,7 +61,6 @@ module Rigor
|
|
|
61
61
|
%r{(?:\A|/)config/}
|
|
62
62
|
].freeze
|
|
63
63
|
|
|
64
|
-
# @param path — file being analysed
|
|
65
64
|
# The route-helper violations for a single call node (0..2), or `[]` when the node is not an
|
|
66
65
|
# implicit `*_path` / `*_url` helper call, is shadowed by a same-file binding, or is in a
|
|
67
66
|
# suppressed directory. ADR-37: the engine owns the walk; the same-file `shadowing` set is built
|
|
@@ -58,6 +58,7 @@ module Rigor
|
|
|
58
58
|
[nil, "registration", :get, :show]
|
|
59
59
|
]
|
|
60
60
|
}.freeze
|
|
61
|
+
Ractor.make_shareable(CONTROLLER_HELPERS)
|
|
61
62
|
|
|
62
63
|
# Dynamic-provider helper patterns. `_omniauth_authorize_path` and `_omniauth_callback_path` are
|
|
63
64
|
# generated per configured provider (Facebook, GitHub, …) by an initializer this parser does not
|
|
@@ -135,6 +136,7 @@ module Rigor
|
|
|
135
136
|
unlocks: %w[new_unlock_path unlock_path],
|
|
136
137
|
registrations: %w[cancel_registration_path new_registration_path edit_registration_path registration_path]
|
|
137
138
|
}.freeze
|
|
139
|
+
Ractor.make_shareable(SCOPED_HELPERS)
|
|
138
140
|
private_constant :SCOPED_HELPERS
|
|
139
141
|
|
|
140
142
|
def scoped_helpers(skip_set)
|