rigortype 0.3.8 → 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/capability_roles/capability_roles.rbs +36 -0
- 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 +236 -17
- data/docs/handbook/02-everyday-types.md +17 -14
- data/docs/handbook/03-narrowing.md +132 -14
- data/docs/handbook/04-tuples-and-shapes.md +8 -6
- data/docs/handbook/05-methods-and-blocks.md +1 -1
- data/docs/handbook/06-classes.md +2 -2
- data/docs/handbook/07-rbs-and-extended.md +19 -1
- data/docs/handbook/10-sorbet.md +9 -10
- data/docs/handbook/11-sig-gen.md +525 -13
- data/docs/handbook/README.md +1 -1
- data/docs/handbook/appendix-elixir.md +2 -2
- data/docs/handbook/appendix-go.md +2 -2
- data/docs/handbook/appendix-java-csharp.md +2 -2
- data/docs/handbook/appendix-mypy.md +2 -2
- data/docs/handbook/appendix-phpstan.md +1 -1
- data/docs/handbook/appendix-rust.md +1 -1
- data/docs/handbook/appendix-type-theory.md +4 -4
- data/docs/handbook/appendix-typescript.md +1 -1
- data/docs/llms.txt +2 -0
- data/docs/manual/02-cli-reference.md +95 -6
- data/docs/manual/03-configuration.md +18 -0
- data/docs/manual/04-diagnostics.md +15 -0
- data/docs/manual/07-plugins.md +15 -5
- data/docs/manual/08-skills.md +23 -2
- data/docs/manual/10-mcp-server.md +3 -2
- data/docs/manual/11-ci.md +9 -0
- data/docs/manual/15-type-protection-coverage.md +8 -0
- data/docs/manual/16-rbs-extended-annotations.md +46 -8
- data/docs/manual/18-removing-dead-code.md +10 -8
- 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 +261 -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 +138 -4
- data/docs/manual/plugins/rigor-activestorage.md +8 -1
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +43 -7
- 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 +229 -1
- 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 +3 -3
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +1 -1
- data/lib/rigor/analysis/check_rules/dead_version_guard_arms.rb +1 -5
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +167 -2
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +10 -2
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +189 -0
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +6 -4
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +15 -6
- data/lib/rigor/analysis/check_rules/rule_ids.rb +21 -6
- data/lib/rigor/analysis/check_rules/rule_walk.rb +41 -5
- data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +1 -1
- data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +1 -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 +38 -4
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +0 -1
- data/lib/rigor/analysis/check_rules.rb +718 -79
- data/lib/rigor/analysis/crash_signature.rb +8 -24
- data/lib/rigor/analysis/dependency_recorder.rb +23 -0
- data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +1 -1
- data/lib/rigor/analysis/dependency_source_inference/builder.rb +0 -2
- data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +0 -2
- data/lib/rigor/analysis/dependency_source_inference/index.rb +5 -5
- data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +1 -2
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
- data/lib/rigor/analysis/effects_cache_probe.rb +3 -4
- data/lib/rigor/analysis/erb_template_detector.rb +1 -2
- data/lib/rigor/analysis/fact_store.rb +15 -1
- data/lib/rigor/analysis/incremental.rb +42 -0
- data/lib/rigor/analysis/incremental_session.rb +117 -26
- data/lib/rigor/analysis/plugin_fact_fingerprint.rb +0 -1
- data/lib/rigor/analysis/project_scan.rb +11 -1
- data/lib/rigor/analysis/reachability/graph.rb +3 -5
- data/lib/rigor/analysis/reachability/plugin_roots.rb +5 -5
- data/lib/rigor/analysis/reachability/project_files.rb +2 -2
- data/lib/rigor/analysis/reachability/scan.rb +5 -5
- data/lib/rigor/analysis/reachability/scan_cache.rb +3 -2
- data/lib/rigor/analysis/reachability/signature_scan.rb +2 -2
- data/lib/rigor/analysis/result.rb +1 -3
- data/lib/rigor/analysis/rule_catalog.rb +131 -1
- data/lib/rigor/analysis/run_cache_key.rb +21 -12
- data/lib/rigor/analysis/run_cache_probe.rb +3 -5
- data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +6 -8
- data/lib/rigor/analysis/runner/declaration_position.rb +1 -2
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +340 -33
- data/lib/rigor/analysis/runner/effect_annotation_residual_pass.rb +2 -3
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +18 -14
- data/lib/rigor/analysis/runner/pool_coordinator.rb +357 -97
- data/lib/rigor/analysis/runner/project_pre_passes.rb +38 -13
- data/lib/rigor/analysis/runner/run_snapshots.rb +6 -1
- data/lib/rigor/analysis/runner.rb +407 -51
- 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 +62 -20
- data/lib/rigor/bleeding_edge.rb +10 -24
- data/lib/rigor/builtins/hkt_builtins.rb +3 -2
- data/lib/rigor/builtins/imported_refinements.rb +159 -21
- data/lib/rigor/builtins/predefined_constant_refinements.rb +5 -7
- data/lib/rigor/builtins/regex_refinement.rb +21 -13
- data/lib/rigor/builtins/static_return_refinements.rb +7 -6
- data/lib/rigor/cache/annotation_location.rb +2 -4
- data/lib/rigor/cache/descriptor.rb +63 -20
- data/lib/rigor/cache/engine_source.rb +33 -5
- data/lib/rigor/cache/file_digest.rb +9 -1
- data/lib/rigor/cache/incremental_snapshot.rb +72 -6
- data/lib/rigor/cache/rbs_cache_producer.rb +4 -0
- data/lib/rigor/cache/rbs_class_ancestor_table.rb +0 -3
- data/lib/rigor/cache/rbs_class_type_param_names.rb +0 -3
- data/lib/rigor/cache/rbs_constant_table.rb +0 -3
- data/lib/rigor/cache/rbs_descriptor.rb +112 -14
- data/lib/rigor/cache/rbs_environment.rb +8 -4
- data/lib/rigor/cache/rbs_known_class_names.rb +0 -3
- data/lib/rigor/cache/store.rb +76 -32
- data/lib/rigor/ci_detector.rb +1 -0
- data/lib/rigor/cli/annotate_command.rb +5 -6
- data/lib/rigor/cli/check_command.rb +57 -10
- data/lib/rigor/cli/check_invocation.rb +6 -11
- data/lib/rigor/cli/check_runner_factory.rb +1 -5
- data/lib/rigor/cli/coverage_command.rb +1 -1
- data/lib/rigor/cli/coverage_mutation.rb +12 -3
- data/lib/rigor/cli/coverage_scan.rb +1 -5
- data/lib/rigor/cli/diff_command.rb +1 -1
- data/lib/rigor/cli/doc_links.rb +4 -4
- data/lib/rigor/cli/docs_command.rb +6 -6
- data/lib/rigor/cli/doctor_command.rb +85 -38
- data/lib/rigor/cli/effects_command.rb +2 -2
- data/lib/rigor/cli/effects_diff_renderer.rb +3 -3
- data/lib/rigor/cli/effects_snapshot_command.rb +1 -1
- data/lib/rigor/cli/explain_command.rb +34 -1
- data/lib/rigor/cli/fused_protection_report.rb +7 -1
- data/lib/rigor/cli/lsp_command.rb +1 -1
- data/lib/rigor/cli/mcp_command.rb +1 -1
- data/lib/rigor/cli/measurement_integrity_warning.rb +4 -5
- data/lib/rigor/cli/mutation_fork_scan.rb +6 -6
- data/lib/rigor/cli/mutation_protection_report.rb +7 -1
- data/lib/rigor/cli/plugin_command.rb +4 -4
- data/lib/rigor/cli/plugins_command.rb +2 -1
- data/lib/rigor/cli/prism_colorizer.rb +1 -2
- data/lib/rigor/cli/protection_fork_scan.rb +6 -6
- data/lib/rigor/cli/show_bleedingedge_command.rb +1 -1
- data/lib/rigor/cli/sig_gen_command.rb +212 -31
- data/lib/rigor/cli/skill_command.rb +2 -2
- data/lib/rigor/cli/skill_deep_probe.rb +4 -4
- data/lib/rigor/cli/skill_describe.rb +35 -35
- data/lib/rigor/cli/trace_command.rb +4 -4
- data/lib/rigor/cli/trace_renderer.rb +5 -6
- data/lib/rigor/cli/triage_command.rb +1 -1
- data/lib/rigor/cli/type_of_command.rb +29 -11
- 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/type_scan_command.rb +4 -4
- data/lib/rigor/cli/unused_command.rb +11 -3
- data/lib/rigor/cli/upgrade_command.rb +1 -1
- data/lib/rigor/cli.rb +89 -9
- data/lib/rigor/config_audit.rb +30 -5
- data/lib/rigor/configuration/severity_profile.rb +25 -9
- data/lib/rigor/configuration.rb +109 -7
- data/lib/rigor/effects/ancestry_recorder.rb +191 -0
- data/lib/rigor/effects/attribution.rb +12 -5
- 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 +15 -10
- data/lib/rigor/effects/definition_context.rb +179 -0
- data/lib/rigor/effects/definition_lines.rb +25 -6
- data/lib/rigor/effects/effect_table.rb +11 -4
- data/lib/rigor/effects/entry_points.rb +0 -2
- data/lib/rigor/effects/envelope_check.rb +9 -9
- data/lib/rigor/effects/envelope_index.rb +20 -8
- data/lib/rigor/effects/file_collection.rb +59 -5
- data/lib/rigor/effects/framework_units.rb +5 -7
- data/lib/rigor/effects/identity.rb +20 -6
- data/lib/rigor/effects/inline_anchor.rb +7 -7
- data/lib/rigor/effects/label_intent.rb +3 -4
- data/lib/rigor/effects/liskov_check.rb +8 -8
- data/lib/rigor/effects/local_ownership.rb +38 -12
- data/lib/rigor/effects/method_key.rb +22 -1
- data/lib/rigor/effects/mutation_classifier.rb +23 -12
- data/lib/rigor/effects/plugin_facts.rb +47 -37
- data/lib/rigor/effects/propagator.rb +297 -19
- data/lib/rigor/effects/registry.rb +1 -1
- data/lib/rigor/effects/scanner.rb +122 -73
- data/lib/rigor/effects/signature_sources.rb +4 -6
- data/lib/rigor/effects/snapshot.rb +12 -11
- data/lib/rigor/effects/snapshot_diff.rb +1 -1
- data/lib/rigor/effects/summary.rb +27 -4
- data/lib/rigor/effects/unit_scan.rb +393 -38
- data/lib/rigor/effects/unknown_label_check.rb +3 -8
- data/lib/rigor/effects/unknown_label_report.rb +3 -4
- data/lib/rigor/effects/visibility.rb +101 -0
- data/lib/rigor/environment/bundle_sig_discovery.rb +6 -6
- data/lib/rigor/environment/class_registry.rb +3 -1
- data/lib/rigor/environment/failure_slot.rb +2 -2
- data/lib/rigor/environment/installed_gem_set.rb +85 -0
- data/lib/rigor/environment/lockfile_resolver.rb +68 -4
- data/lib/rigor/environment/member_consistency/comparator.rb +708 -0
- data/lib/rigor/environment/member_consistency.rb +298 -0
- data/lib/rigor/environment/missing_gem_constant_index.rb +4 -4
- data/lib/rigor/environment/rbs_collection_discovery.rb +5 -5
- data/lib/rigor/environment/rbs_coverage_report.rb +5 -5
- data/lib/rigor/environment/rbs_hierarchy.rb +3 -1
- data/lib/rigor/environment/rbs_loader.rb +674 -79
- data/lib/rigor/environment.rb +174 -24
- data/lib/rigor/flow_contribution/merger.rb +0 -2
- data/lib/rigor/flow_contribution.rb +11 -13
- data/lib/rigor/hashing/xxh3.rb +264 -0
- data/lib/rigor/inference/acceptance.rb +292 -17
- 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 +75 -30
- data/lib/rigor/inference/block_repetition.rb +71 -0
- data/lib/rigor/inference/body_fixpoint.rb +7 -6
- data/lib/rigor/inference/budget_trace.rb +3 -6
- 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 +389 -18
- data/lib/rigor/inference/closure_escape_analyzer.rb +159 -17
- data/lib/rigor/inference/content_join.rb +200 -27
- data/lib/rigor/inference/coverage_scanner.rb +4 -6
- 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/dynamic_origin.rb +1 -1
- data/lib/rigor/inference/element_read_widening.rb +180 -0
- data/lib/rigor/inference/error_info.rb +196 -0
- data/lib/rigor/inference/expression_typer.rb +2124 -468
- data/lib/rigor/inference/external_ancestor_resolution.rb +267 -0
- data/lib/rigor/inference/fork_map.rb +5 -7
- 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/hkt_reducer.rb +2 -3
- data/lib/rigor/inference/hkt_registry.rb +4 -7
- data/lib/rigor/inference/index_write_widening.rb +16 -7
- 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 +168 -21
- 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 +87 -33
- data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +305 -19
- data/lib/rigor/inference/method_dispatcher/data_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +147 -0
- data/lib/rigor/inference/method_dispatcher/file_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/hash_transform_keys_folding.rb +191 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +6 -2
- data/lib/rigor/inference/method_dispatcher/json_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +7 -1
- data/lib/rigor/inference/method_dispatcher/match_data_folding.rb +159 -0
- data/lib/rigor/inference/method_dispatcher/math_folding.rb +41 -3
- data/lib/rigor/inference/method_dispatcher/method_folding.rb +2 -5
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +165 -111
- 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/random_folding.rb +82 -0
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +1046 -69
- data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +25 -4
- data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +2 -8
- data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/self_substitute.rb +142 -0
- data/lib/rigor/inference/method_dispatcher/set_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +129 -54
- data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +1 -2
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -6
- data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +85 -4
- data/lib/rigor/inference/method_dispatcher/time_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/universal_object_dispatch.rb +1 -2
- data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher.rb +225 -25
- data/lib/rigor/inference/method_parameter_binder.rb +12 -9
- data/lib/rigor/inference/multi_target_binder.rb +341 -55
- data/lib/rigor/inference/mutation_rejoin.rb +171 -0
- data/lib/rigor/inference/mutation_widening.rb +156 -85
- data/lib/rigor/inference/narrowing.rb +835 -162
- 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 +153 -16
- data/lib/rigor/inference/origin_lookup.rb +2 -3
- data/lib/rigor/inference/parameter_inference_collector.rb +7 -7
- data/lib/rigor/inference/pre_eval_constants.rb +6 -5
- data/lib/rigor/inference/precision_scanner.rb +3 -4
- data/lib/rigor/inference/project_method_ownership.rb +136 -0
- data/lib/rigor/inference/project_patched_methods.rb +9 -4
- data/lib/rigor/inference/project_patched_scanner.rb +10 -6
- data/lib/rigor/inference/protection_scanner.rb +1 -2
- data/lib/rigor/inference/range_constant.rb +57 -0
- data/lib/rigor/inference/rbs_type_translator.rb +49 -11
- data/lib/rigor/inference/receiver_alias.rb +93 -4
- data/lib/rigor/inference/receiver_blind_block.rb +219 -0
- data/lib/rigor/inference/refinement_mutation.rb +76 -0
- 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 +5228 -627
- data/lib/rigor/inference/statement_evaluator.rb +3452 -595
- data/lib/rigor/inference/stored_block_call.rb +54 -0
- data/lib/rigor/inference/string_mutation.rb +97 -0
- data/lib/rigor/inference/struct_fold_safety.rb +6 -7
- data/lib/rigor/inference/synthetic_method_index.rb +1 -2
- data/lib/rigor/inference/synthetic_method_scanner.rb +4 -6
- data/lib/rigor/inference/unknown_store_widening.rb +200 -0
- data/lib/rigor/inference/unthreaded_rebinds.rb +282 -0
- data/lib/rigor/inference/version_guard.rb +28 -21
- data/lib/rigor/inference/void_origin.rb +3 -3
- data/lib/rigor/inference/void_tail_summary.rb +2 -4
- data/lib/rigor/language_server/buffer_table.rb +4 -4
- data/lib/rigor/language_server/completion_provider.rb +1 -1
- data/lib/rigor/language_server/debouncer.rb +0 -1
- data/lib/rigor/language_server/diagnostic_publisher.rb +7 -6
- data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
- data/lib/rigor/language_server/folding_range_provider.rb +1 -1
- data/lib/rigor/language_server/hover_provider.rb +1 -1
- data/lib/rigor/language_server/hover_renderer.rb +4 -4
- data/lib/rigor/language_server/incremental_sync.rb +6 -6
- data/lib/rigor/language_server/project_context.rb +7 -8
- data/lib/rigor/language_server/publish_batcher.rb +2 -2
- data/lib/rigor/language_server/selection_range_provider.rb +2 -2
- data/lib/rigor/language_server/server.rb +9 -9
- data/lib/rigor/language_server/signature_help_provider.rb +1 -1
- data/lib/rigor/language_server/uri.rb +1 -1
- data/lib/rigor/mcp/server.rb +2 -1
- data/lib/rigor/plugin/base.rb +258 -26
- data/lib/rigor/plugin/box_probe.rb +91 -0
- data/lib/rigor/plugin/bundled_catalog.rb +167 -0
- data/lib/rigor/plugin/effect_attribution.rb +65 -11
- data/lib/rigor/plugin/effect_entry_points.rb +3 -3
- data/lib/rigor/plugin/fact_store.rb +6 -6
- data/lib/rigor/plugin/io_boundary.rb +93 -8
- data/lib/rigor/plugin/isolation.rb +29 -6
- data/lib/rigor/plugin/loader.rb +33 -13
- data/lib/rigor/plugin/macro/block_as_method.rb +45 -6
- data/lib/rigor/plugin/macro/heredoc_template.rb +1 -1
- data/lib/rigor/plugin/macro/trait_registry.rb +1 -1
- data/lib/rigor/plugin/manifest.rb +94 -11
- data/lib/rigor/plugin/registry.rb +76 -12
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +21 -4
- data/lib/rigor/plugin/template_unit.rb +196 -0
- data/lib/rigor/plugin/trust_policy.rb +2 -4
- data/lib/rigor/plugin/type_node_resolver.rb +3 -3
- data/lib/rigor/plugin.rb +1 -0
- data/lib/rigor/plugin_gap_advisory.rb +96 -0
- data/lib/rigor/project_environment.rb +138 -0
- data/lib/rigor/protection/analysis_guard.rb +93 -14
- data/lib/rigor/protection/closure_kill_oracle.rb +67 -23
- data/lib/rigor/protection/dependency_closure.rb +5 -8
- data/lib/rigor/protection/diagnostic_oracle.rb +2 -2
- data/lib/rigor/protection/discovery_seed.rb +14 -12
- data/lib/rigor/protection/kill_signature.rb +1 -4
- data/lib/rigor/protection/measurement_integrity.rb +1 -3
- data/lib/rigor/protection/mutation_cache.rb +7 -11
- data/lib/rigor/protection/mutation_scanner.rb +12 -15
- data/lib/rigor/protection/mutator.rb +2 -1
- data/lib/rigor/protection/test_suite_oracle.rb +5 -5
- data/lib/rigor/rbs_extended/conformance_checker.rb +4 -3
- data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
- data/lib/rigor/rbs_extended/reporter.rb +36 -10
- data/lib/rigor/rbs_extended.rb +88 -21
- data/lib/rigor/reflection/constant_ancestors.rb +97 -0
- data/lib/rigor/reflection/constant_path.rb +139 -0
- data/lib/rigor/reflection.rb +93 -110
- data/lib/rigor/runtime/jit.rb +6 -8
- data/lib/rigor/scope/discovery_index.rb +165 -2
- data/lib/rigor/scope.rb +1041 -32
- 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 +673 -53
- data/lib/rigor/sig_gen/inline_declarations.rb +184 -0
- data/lib/rigor/sig_gen/layout_index.rb +3 -4
- data/lib/rigor/sig_gen/meta_class_shape.rb +3 -5
- data/lib/rigor/sig_gen/method_candidate.rb +47 -3
- data/lib/rigor/sig_gen/observation_collector.rb +18 -16
- data/lib/rigor/sig_gen/path_mapper.rb +4 -6
- data/lib/rigor/sig_gen/rbs_validity.rb +4 -4
- data/lib/rigor/sig_gen/renderer.rb +128 -14
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +154 -0
- data/lib/rigor/sig_gen/superclass_spelling.rb +27 -0
- data/lib/rigor/sig_gen/type_elaborator.rb +1 -3
- data/lib/rigor/sig_gen/write_result.rb +19 -3
- data/lib/rigor/sig_gen/writer.rb +189 -41
- data/lib/rigor/sig_gen.rb +3 -0
- data/lib/rigor/signature_path_audit.rb +153 -6
- data/lib/rigor/source/literals.rb +0 -23
- data/lib/rigor/source/node_children.rb +0 -2
- data/lib/rigor/source/node_locator.rb +5 -11
- data/lib/rigor/source/node_walker.rb +0 -6
- data/lib/rigor/source/parameter_envelope.rb +72 -0
- data/lib/rigor/source.rb +1 -0
- data/lib/rigor/triage/catalogue.rb +1 -3
- data/lib/rigor/triage.rb +3 -5
- data/lib/rigor/type/accepts_result.rb +24 -6
- data/lib/rigor/type/combinator.rb +144 -5
- data/lib/rigor/type/data_class.rb +2 -2
- data/lib/rigor/type/data_instance.rb +4 -4
- data/lib/rigor/type/difference.rb +1 -0
- data/lib/rigor/type/float_range.rb +128 -0
- data/lib/rigor/type/hash_shape.rb +6 -6
- data/lib/rigor/type/integer_range.rb +13 -8
- data/lib/rigor/type/nominal.rb +8 -2
- data/lib/rigor/type/refined.rb +4 -3
- data/lib/rigor/type/struct_class.rb +3 -3
- data/lib/rigor/type/struct_instance.rb +4 -4
- data/lib/rigor/type.rb +1 -0
- data/lib/rigor/type_node/generic.rb +1 -1
- data/lib/rigor/type_node/range_literal.rb +25 -0
- data/lib/rigor/type_node/resolver_chain.rb +1 -1
- data/lib/rigor/type_node.rb +1 -0
- data/lib/rigor/version.rb +1 -1
- data/lib/rigor.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +0 -4
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +0 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +0 -2
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/effects.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +10 -5
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +0 -4
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +3 -5
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +1 -4
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +14 -4
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +32 -30
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +0 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -3
- 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 +264 -3
- data/plugins/rigor-actionpack/sig/action_controller.rbs +71 -0
- 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/analyzer.rb +0 -4
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +2 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +0 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +0 -2
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/recurring_scan.rb +1 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +10 -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 +383 -7
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +14 -6
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +1 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +1 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +322 -41
- data/plugins/rigor-activerecord/sig/active_record/framework.rbs +123 -0
- data/plugins/rigor-activerecord/sig/active_record/relation.rbs +206 -31
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +26 -14
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +9 -2
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +9 -2
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +290 -19
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +1 -0
- data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +3 -0
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +9 -7
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +7 -3
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +1 -0
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +8 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +11 -7
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -11
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +9 -4
- data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +2 -0
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +0 -5
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +0 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +0 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +8 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/types.rb +1 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +36 -4
- data/plugins/rigor-ffi-rzmq/lib/rigor/plugin/ffi_rzmq.rb +1 -0
- 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/type_scanner.rb +8 -6
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +78 -5
- data/plugins/rigor-graphql/sig/graphql.rbs +485 -0
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +1 -0
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +2 -1
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +2 -3
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +1 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +0 -5
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/authorization_scan.rb +2 -2
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +0 -1
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +0 -1
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +12 -7
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +0 -12
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +1 -3
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +0 -1
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +36 -37
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/acronyms.rb +5 -5
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +0 -10
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +5 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +3 -2
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/grape_api_discoverer.rb +2 -2
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +2 -2
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +9 -10
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +2 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +10 -17
- data/plugins/rigor-railties/lib/rigor/plugin/railties.rb +1 -0
- data/plugins/rigor-rbnacl/lib/rigor/plugin/rbnacl.rb +13 -1
- 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 +324 -18
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +0 -3
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +0 -3
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +1 -5
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +2 -3
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +1 -0
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +0 -3
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +1 -0
- data/plugins/rigor-sassc/lib/rigor/plugin/sassc.rb +1 -0
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +1 -9
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +1 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +0 -4
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/effects.rb +1 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/schedule_scan.rb +2 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +0 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +0 -2
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +10 -5
- data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +1 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +2 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +1 -4
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +3 -9
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +4 -4
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +1 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +3 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +7 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +51 -6
- data/plugins/rigor-sorbet/sig/sorbet.rbs +277 -0
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +1 -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/analysis/reachability/scan_cache.rbs +12 -0
- data/sig/rigor/cache.rbs +2 -3
- 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 +17 -10
- data/sig/rigor/inference/optimistic_origin.rbs +10 -0
- data/sig/rigor/inference.rbs +9 -14
- 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 +4 -0
- data/sig/rigor/plugin/loader.rbs +3 -3
- data/sig/rigor/plugin/manifest.rbs +51 -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 +9 -6
- data/sig/rigor/scope.rbs +148 -12
- data/sig/rigor/sig_gen/skip_reason_catalog.rbs +21 -0
- data/sig/rigor/source.rbs +4 -4
- data/sig/rigor/testing.rbs +10 -4
- data/sig/rigor/type.rbs +33 -1
- data/sig/rigor.rbs +39 -20
- data/skills/rigor-ask/SKILL.md +16 -11
- 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 +25 -27
- 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 +15 -10
- data/skills/rigor-project-init/references/01-detect.md +13 -9
- data/skills/rigor-project-init/references/02-configure.md +43 -14
- 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-project-init/references/06-agent-contract.md +67 -0
- 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 +226 -0
- data/skills/rigor-type-oracle/references/01-oracle-commands.md +265 -0
- data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +52 -0
- data/skills/rigor-type-oracle/references/03-gap-protocol.md +125 -0
- data/skills/rigor-unused-adjudicate/SKILL.md +12 -7
- data/skills/rigor-upgrade/SKILL.md +13 -8
- metadata +133 -3
- data/lib/rigor/cli/probe_environment.rb +0 -85
- data/sig/rigor/inference/builtins/numeric_catalog.rbs +0 -3
|
@@ -29,13 +29,21 @@ errors_demo.rb:24:1: error: `User.find` expects at least 1 argument, got 0 [plug
|
|
|
29
29
|
| --- | --- | --- |
|
|
30
30
|
| Recognised `Model.find` / `Model.find_by` / `Model.where` call | `:info` | `plugin.activerecord.model-call` |
|
|
31
31
|
| `Model.find_by(unknown: ...)` / `Model.where(unknown: ...)` | `:error` | `plugin.activerecord.unknown-column` |
|
|
32
|
-
| `Model.find` with 0 args | `:error` | `plugin.activerecord.wrong-arity` |
|
|
32
|
+
| `Model.find` with 0 args and no block (unless the model defines `self.find`) | `:error` | `plugin.activerecord.wrong-arity` |
|
|
33
33
|
| No schema source (`db/schema.rb` or `db/structure.sql`) present — reduced mode | `:info` | `plugin.activerecord.load-error` |
|
|
34
34
|
| A schema source that exists but cannot be read or parsed | `:warning` | `plugin.activerecord.load-error` |
|
|
35
35
|
|
|
36
36
|
Did-you-mean suggestions use `DidYouMean` fuzzy matching against
|
|
37
37
|
the resolved table's column names.
|
|
38
38
|
|
|
39
|
+
A model that defines its own `self.find` owns that method's arity.
|
|
40
|
+
The plugin reports no `wrong-arity` for it, and no note for the
|
|
41
|
+
several-id or block form, where the call types as the model's
|
|
42
|
+
method rather than Rails' `find`. A single id is still noted as the
|
|
43
|
+
model, which is how it types. In an editor, a `self.find` in the
|
|
44
|
+
same file is not yet seen here, so the note and the error still
|
|
45
|
+
appear there ([#1329](https://github.com/rigortype/rigor/issues/1329)).
|
|
46
|
+
|
|
39
47
|
## Configuration
|
|
40
48
|
|
|
41
49
|
```yaml
|
|
@@ -61,8 +69,17 @@ All keys are optional. Tweak them when:
|
|
|
61
69
|
## What it infers
|
|
62
70
|
|
|
63
71
|
The plugin contributes call-site types as well as diagnostics.
|
|
64
|
-
Class-side: `User.find(1)` → `User`, `User.
|
|
65
|
-
`User
|
|
72
|
+
Class-side: `User.find(1)` → `User`, `User.find(1, 2)` →
|
|
73
|
+
`Array[User]`, `User.find_by(...)` → `User | nil`,
|
|
74
|
+
`User.find_by!(...)` → non-nullable `User`. A single argument
|
|
75
|
+
stays `User` even when it is an Array (`User.find([1, 2])`), so
|
|
76
|
+
that an untyped one, such as `params[:id]`, keeps the model type.
|
|
77
|
+
A relation or association (`user.posts.find(1, 2)`) answers the
|
|
78
|
+
same way. With a block, `find` is `Enumerable#find` over the
|
|
79
|
+
records, on the class and on a relation alike:
|
|
80
|
+
`User.find { |u| u.admin? }` → `User | nil`, and it takes no id.
|
|
81
|
+
The block's parameter is the model on a relation; on the class
|
|
82
|
+
side it stays untyped.
|
|
66
83
|
Instance-side: a column read (`user.name`) narrows to the
|
|
67
84
|
column's value type, `user.admin?` to `bool`, and a singular
|
|
68
85
|
association (`post.user`) to the target model.
|
|
@@ -76,6 +93,84 @@ Chained query methods keep the element type, and iteration
|
|
|
76
93
|
scope invoked on a typed relation (`User.where(...).published`)
|
|
77
94
|
never surfaces a false `call.undefined-method`.
|
|
78
95
|
|
|
96
|
+
A `scope` declared inside a concern's `included do ... end` block
|
|
97
|
+
counts as the including model's own. `Account.without_suspended`
|
|
98
|
+
types as `ActiveRecord::Relation[Account]` when `Account` includes
|
|
99
|
+
the concern that declares the scope — directly, or through another
|
|
100
|
+
concern that concern includes. A concern included once in your
|
|
101
|
+
base class (`ApplicationRecord`) reaches every model under it.
|
|
102
|
+
Attribution follows the `include` you wrote, not the name: a
|
|
103
|
+
model that includes nothing gets nothing, whatever some other
|
|
104
|
+
concern in the project declares.
|
|
105
|
+
|
|
106
|
+
The gate is the `included do ... end` block itself. A scope
|
|
107
|
+
declared some other way — in a `class_methods do` block, a
|
|
108
|
+
hand-written `def self.included(base)` with `base.class_eval`, or
|
|
109
|
+
directly in the body of your base class rather than in a concern —
|
|
110
|
+
is not folded, and the call stays as untyped as it was.
|
|
111
|
+
|
|
112
|
+
`belongs_to` / `has_one` / `has_many` /
|
|
113
|
+
`has_and_belongs_to_many` declared in that same `included do ...
|
|
114
|
+
end` block count as the including model's own too, with the same
|
|
115
|
+
`include`-edge attribution: `account.user` narrows to
|
|
116
|
+
`User | nil` when `Account` includes the concern that declares
|
|
117
|
+
`has_one :user`, and `where(user: ...)` stops reporting a false
|
|
118
|
+
`unknown-column`. A model that declares the association itself
|
|
119
|
+
keeps its own version.
|
|
120
|
+
|
|
121
|
+
### The names a macro defines
|
|
122
|
+
|
|
123
|
+
Three macro families define ordinary instance methods that are
|
|
124
|
+
neither columns nor associations, and the model's recorded
|
|
125
|
+
surface now carries their names:
|
|
126
|
+
|
|
127
|
+
- `delegate :followers_count, to: :account_stat` — every
|
|
128
|
+
delegated name, including the `prefix:` spellings
|
|
129
|
+
(`delegate :can?, to: :user, prefix: true` defines
|
|
130
|
+
`user_can?`). `delegate` is read from the model body, from a
|
|
131
|
+
concern's `included do ... end`, and from a concern's own
|
|
132
|
+
top level, where it defines an instance method the including
|
|
133
|
+
model inherits.
|
|
134
|
+
- Attachment macros — Paperclip's `has_attached_file :avatar`
|
|
135
|
+
(`avatar`, `avatar=`, `avatar?`) and Active Storage's
|
|
136
|
+
`has_one_attached` / `has_many_attached` (`banner`,
|
|
137
|
+
`banner_attachment`, `banner_blob`; `docs`,
|
|
138
|
+
`docs_attachments`, `docs_blobs`). Paperclip's
|
|
139
|
+
`avatar_file_name` / `avatar_content_type` / `avatar_file_size`
|
|
140
|
+
/ `avatar_updated_at` are real columns, so they come from your
|
|
141
|
+
schema rather than from the macro.
|
|
142
|
+
- `enum` value predicates — `enum :visibility, { limited: 4 },
|
|
143
|
+
suffix: :visibility` defines `limited_visibility?`, and
|
|
144
|
+
`prefix:` / `_prefix:` / `_suffix:` are read the same way. An
|
|
145
|
+
`enum` declared `instance_methods: false` defines none of
|
|
146
|
+
them, and none are recorded.
|
|
147
|
+
|
|
148
|
+
These are recorded as NAMES. Nothing here says what a delegated
|
|
149
|
+
method returns, and the plugin contributes no type for one — the
|
|
150
|
+
value is that a consumer asking "does this model answer
|
|
151
|
+
`followers_count`?" gets the right answer. The consumer this was
|
|
152
|
+
built for is
|
|
153
|
+
[`rigor-active-model-serializers`](rigor-active-model-serializers.md),
|
|
154
|
+
which types a serializer's `object` only when the candidate model
|
|
155
|
+
answers every name the serializer reads.
|
|
156
|
+
|
|
157
|
+
A declaration this plugin cannot read off the source contributes
|
|
158
|
+
nothing rather than a guess: a `prefix: true` whose `to:` is a
|
|
159
|
+
method call, a non-literal `prefix:`, a computed enum value list.
|
|
160
|
+
|
|
161
|
+
If the project also installs `activerecord` through
|
|
162
|
+
`rbs collection install`, the collection declares
|
|
163
|
+
`ActiveRecord::Relation` without a type parameter while the
|
|
164
|
+
plugin declares `ActiveRecord::Relation[Elem]`, and RBS cannot
|
|
165
|
+
hold both. The plugin's declaration stands down: relation call
|
|
166
|
+
sites still type as `ActiveRecord::Relation[Model]`, but calls
|
|
167
|
+
into a relation resolve against the collection's declaration,
|
|
168
|
+
so the plugin's element typing (`.first` as `Model?`, for
|
|
169
|
+
example) is unavailable, and the run reports one
|
|
170
|
+
`rbs.coverage.plugin-signature-stood-down` info row naming both
|
|
171
|
+
files. Nothing is broken; the plugin's typing returns only when
|
|
172
|
+
the collection stops declaring the class.
|
|
173
|
+
|
|
79
174
|
`User.table_name` types as `String`, and as the exact string
|
|
80
175
|
only when your source says the name: a literal
|
|
81
176
|
`self.table_name = "people"` on the class or on an STI ancestor,
|
|
@@ -118,6 +213,21 @@ than none, so `Blog::Post`'s column, alias and association checks
|
|
|
118
213
|
stand down entirely rather than run against a table that might not
|
|
119
214
|
be the real one.
|
|
120
215
|
|
|
216
|
+
## Framework constants resolve
|
|
217
|
+
|
|
218
|
+
The bundled signatures also name Active Record's exception hierarchy
|
|
219
|
+
(`ActiveRecordError` and the classes apps rescue: `RecordNotFound`,
|
|
220
|
+
`RecordInvalid`, `RecordNotSaved`, `StatementInvalid`,
|
|
221
|
+
`RecordNotUnique`, `StaleObjectError`, …), the `ActiveModel`
|
|
222
|
+
namespace, and `Arel`. `rescue ActiveRecord::RecordNotFound => e` types
|
|
223
|
+
`e` instead of leaving it opaque.
|
|
224
|
+
|
|
225
|
+
None of them declares a method surface — the declaration buys constant
|
|
226
|
+
resolution and asserts nothing else, so `e.record` and every other
|
|
227
|
+
member left out stays lenient rather than reported.
|
|
228
|
+
`ActiveRecord::Base` is deliberately **not** declared: closing it would
|
|
229
|
+
close every model in the project.
|
|
230
|
+
|
|
121
231
|
## Limitations
|
|
122
232
|
|
|
123
233
|
- **Direct-superclass match only.** `class Admin < User` where
|
|
@@ -154,12 +264,25 @@ be the real one.
|
|
|
154
264
|
the column-dependent half stands down — column readers stay
|
|
155
265
|
untyped and `where(col:)` keys are not validated, exactly as they
|
|
156
266
|
are for a table the schema does not describe. The plugin says so
|
|
157
|
-
once per run at `:info
|
|
267
|
+
once per run at `:info`, positioned on `.rigor.yml` — it is a
|
|
268
|
+
fact about your configuration, not about any one source file,
|
|
269
|
+
and you get the same single row with `--workers` as without. If
|
|
270
|
+
you baselined this row at its old position (a controller or a
|
|
271
|
+
model), that baseline entry no longer matches it — run `rigor
|
|
272
|
+
baseline regenerate`. Committing a schema dump (or pointing
|
|
158
273
|
`schema_file` / `structure_sql_file` at one) turns the column half
|
|
159
274
|
back on from the next cold run — a warm cache keeps serving the
|
|
160
275
|
reduced index until it is invalidated, so use `rigor check
|
|
161
276
|
--no-cache` (or `make cache-clean`) if you want to see the change
|
|
162
277
|
immediately.
|
|
278
|
+
- **Every kind of relation shares one signature.**
|
|
279
|
+
`user.posts`, `user.posts.where(...)` and `Post.where(...)` all
|
|
280
|
+
type as `ActiveRecord::Relation[Post]`, although only the first
|
|
281
|
+
is an association's `CollectionProxy`, so the signature they share
|
|
282
|
+
accepts the widest argument list any of them takes.
|
|
283
|
+
`user.posts.delete_all(:nullify)` is valid and not reported. The
|
|
284
|
+
same call on the other two raises `ArgumentError` at run time, and
|
|
285
|
+
is not reported either.
|
|
163
286
|
- **Column reads, not setters.** The plugin types instance-side
|
|
164
287
|
column *reads* (`user.name`, `user.admin?`) and singular
|
|
165
288
|
associations, but not the `name=` setter or the dirty-tracking
|
|
@@ -173,6 +296,17 @@ be the real one.
|
|
|
173
296
|
|
|
174
297
|
## Plugin internals
|
|
175
298
|
|
|
299
|
+
The plugin also answers `Plugin::Base#declared_members` (ADR-113
|
|
300
|
+
WD4): it enumerates each model's synthesized members — column
|
|
301
|
+
readers and `column?` predicates, association accessors, declared
|
|
302
|
+
scopes, enum attributes, and macro-defined names — off the prepared
|
|
303
|
+
model index, so `rigor lens` can list `User`'s members without a
|
|
304
|
+
grep-able declaration. A row carries the member-level type the
|
|
305
|
+
plugin commits to: `Dynamic[top]` for column readers on purpose
|
|
306
|
+
(the bare, receiver-less read's answer — a written `user.name`
|
|
307
|
+
still narrows to the column's type), and a type only where the
|
|
308
|
+
plugin already answers one at `check`.
|
|
309
|
+
|
|
176
310
|
Architecture (the cached schema-parser → model-index → analyzer
|
|
177
311
|
chain), the source layout, how to run the demo, and the plugin
|
|
178
312
|
contract surfaces this plugin exercises are documented in the
|
|
@@ -40,12 +40,19 @@ arguments decline — those are covered by ActiveStorage's own RBS.
|
|
|
40
40
|
| Rule | Severity | When |
|
|
41
41
|
| --- | --- | --- |
|
|
42
42
|
| `plugin.activestorage.attachment-call` | info | a recognised `model.attachment_name` call surfaces; confirms the model → attachment mapping |
|
|
43
|
-
| `plugin.activestorage.load-error` | warning | discovery failed (e.g. the model directory is inaccessible under the IoBoundary trust policy) |
|
|
43
|
+
| `plugin.activestorage.load-error` | warning | discovery failed (e.g. the model directory is inaccessible under the IoBoundary trust policy) — once per run, on `.rigor.yml` |
|
|
44
44
|
|
|
45
45
|
No `:error` diagnostics in this slice — the value is the
|
|
46
46
|
return-type contribution; an "unknown attachment name" rule is a
|
|
47
47
|
future slice.
|
|
48
48
|
|
|
49
|
+
The `load-error` warning is run-scoped: it is a fact about your
|
|
50
|
+
configuration, not about any one source file, so it is reported once
|
|
51
|
+
per run on `.rigor.yml` rather than repeated on every analysed file.
|
|
52
|
+
It is `:warning`, so if you baselined it at its old position that
|
|
53
|
+
entry no longer matches and the row fails a `--fail-on=warning` run —
|
|
54
|
+
regenerate with `rigor baseline regenerate`.
|
|
55
|
+
|
|
49
56
|
## Configuration
|
|
50
57
|
|
|
51
58
|
```yaml
|
|
@@ -36,21 +36,27 @@ path, no vendoring, no `signature_paths:` wiring.
|
|
|
36
36
|
|
|
37
37
|
Roughly the top ~40 selectors plus their close neighbours, across:
|
|
38
38
|
|
|
39
|
-
- **Object (universal)** — `#blank?`, `#present?`, `#presence`,
|
|
40
|
-
`#try!`, `#acts_like
|
|
39
|
+
- **Object (universal)** — `#blank?`, `#present?`, `#presence`,
|
|
40
|
+
`#presence_in`, `#try`, `#try!`, `#acts_like?`, `#deep_dup`, `#with`,
|
|
41
|
+
`#with_options`, `#html_safe?`, `Kernel#class_eval` (+ `NilClass` /
|
|
42
|
+
`TrueClass` / `FalseClass`).
|
|
41
43
|
- **Integer / Float** — Duration multipliers (`#days`, `#hours`,
|
|
42
44
|
`#minutes`, …) and Bytes multipliers (`#megabytes`, `#gigabytes`, …).
|
|
43
45
|
- **String** — inflections (`#underscore`, `#camelize`, `#classify`,
|
|
44
46
|
`#constantize`, `#pluralize`, …), filters (`#squish`, `#truncate`),
|
|
45
|
-
`#html_safe`, `#starts_with?` / `#ends_with
|
|
47
|
+
`#html_safe`, `#starts_with?` / `#ends_with?` (also on **Symbol**),
|
|
48
|
+
conversions and `#in_time_zone`.
|
|
46
49
|
- **Time / Date / DateTime** — `.current`, `.zone`, `#yesterday`,
|
|
47
50
|
`#tomorrow`, `#beginning_of_*` / `#end_of_*`, `#ago`, `#since`. `Time`
|
|
48
51
|
additionally carries its **whole** Rails instance surface (see below);
|
|
49
52
|
`Date` and `DateTime` carry the same subset they always did.
|
|
50
53
|
- **Array** — `.wrap`, `#to_sentence`, `#in_groups_of`, `#second` …
|
|
51
54
|
`#fifth`, `#compact_blank`, `#exclude?`.
|
|
52
|
-
- **Hash** — `#symbolize_keys` / `#stringify_keys` (+ deep / bang)
|
|
53
|
-
`#deep_merge`, `#
|
|
55
|
+
- **Hash** — `#symbolize_keys` / `#stringify_keys` (+ deep / bang) and
|
|
56
|
+
their `#to_options` alias, `#deep_merge`, `#reverse_merge` /
|
|
57
|
+
`#with_defaults` (+ bang), `#with_indifferent_access`, `#except!`,
|
|
58
|
+
`#extract!`.
|
|
59
|
+
- **Range** — `#overlaps?`, `#to_fs` / `#to_formatted_s`.
|
|
54
60
|
- **Enumerable** — `#index_by`, `#index_with`, `#pluck`, `#exclude?`.
|
|
55
61
|
|
|
56
62
|
```ruby
|
|
@@ -129,8 +135,29 @@ singletons `.days_in_month`, `.days_in_year`, `.rfc3339`, `.use_zone`,
|
|
|
129
135
|
`.find_zone` / `.find_zone!` and `.zone_default`.
|
|
130
136
|
|
|
131
137
|
Where a return cannot honestly be named it is widened rather than
|
|
132
|
-
guessed: `#in_time_zone` answers an `ActiveSupport::TimeWithZone
|
|
133
|
-
|
|
138
|
+
guessed: `#in_time_zone` answers an `ActiveSupport::TimeWithZone` under a
|
|
139
|
+
zone and the receiver's own class when none is configured, so it reads
|
|
140
|
+
`untyped` rather than picking one of the two.
|
|
141
|
+
|
|
142
|
+
`ActiveSupport::TimeWithZone` itself **is** modelled, as a subclass of
|
|
143
|
+
`Time` — which is what `Time.current` and the whole `1.hour.ago` family
|
|
144
|
+
answer:
|
|
145
|
+
|
|
146
|
+
```ruby
|
|
147
|
+
Time.current.time_zone # the zone (untyped)
|
|
148
|
+
Time.current.comparable_time # Time
|
|
149
|
+
Time.current.to_fs(:db) # String — Time's own surface, inherited
|
|
150
|
+
1.hour.ago.time_zone # the same class from the Duration family
|
|
151
|
+
Time.now.time_zone # still call.undefined-method — a plain
|
|
152
|
+
# Time really does not have it
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Rails overrides `TimeWithZone#is_a?` to answer true for `::Time` and
|
|
156
|
+
forwards everything it does not define to the wrapped `Time`, so the
|
|
157
|
+
subclass says what a `Time` return said and adds the four readers a TWZ
|
|
158
|
+
has of its own. A `Time | TimeWithZone` union was measured instead and
|
|
159
|
+
rejected: it fires nothing, but types the whole downstream chain
|
|
160
|
+
`Dynamic[top]`.
|
|
134
161
|
|
|
135
162
|
What is left out is twelve names, measured against a real
|
|
136
163
|
`require "active_support/all"`: ten instance and two singleton, every one
|
|
@@ -145,6 +172,15 @@ code that does will see them reported.
|
|
|
145
172
|
`Date` and `DateTime` are extended by the same ActiveSupport modules and
|
|
146
173
|
do **not** carry this yet — `Date.current.past?` still reports.
|
|
147
174
|
|
|
175
|
+
## `ActiveSupport::Concern` resolves
|
|
176
|
+
|
|
177
|
+
`extend ActiveSupport::Concern` is the first line of every concern in a
|
|
178
|
+
Rails app, and the constant used to resolve to nothing. The bundle now
|
|
179
|
+
names the module, along with the three members `extend` puts on the
|
|
180
|
+
extender — `included`, `prepended` and `class_methods` — so
|
|
181
|
+
`included do … end` keeps resolving rather than becoming a report on the
|
|
182
|
+
newly-named module. Everything else `Concern` responds to stays lenient.
|
|
183
|
+
|
|
148
184
|
## No diagnostics, no config
|
|
149
185
|
|
|
150
186
|
The plugin emits no diagnostics and has no configuration knobs. It
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# rigor-grape
|
|
2
|
+
|
|
3
|
+
Types the [Grape](https://github.com/ruby-grape/grape)
|
|
4
|
+
endpoint-declaration DSL so calls inside `class API < Grape::API`
|
|
5
|
+
bodies — and inside `Grape::Entity` subclasses from
|
|
6
|
+
[grape-entity](https://github.com/ruby-grape/grape-entity) — resolve to
|
|
7
|
+
real carriers instead of `Dynamic[top]`. It reads source only, with no
|
|
8
|
+
`grape` runtime dependency.
|
|
9
|
+
|
|
10
|
+
It ships bundled in `rigortype`. Activate it under `plugins:` (or let
|
|
11
|
+
bundler auto-detection pick it up when `grape` or `grape-entity` is in
|
|
12
|
+
`Gemfile.lock`):
|
|
13
|
+
|
|
14
|
+
```yaml
|
|
15
|
+
plugins:
|
|
16
|
+
- rigor-grape
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## What it types
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
class ThingsAPI < Grape::API
|
|
23
|
+
version "v1", using: :path
|
|
24
|
+
format :json
|
|
25
|
+
|
|
26
|
+
desc "List things" # Object?
|
|
27
|
+
route_setting :swagger, tags: %w[things] # Object?
|
|
28
|
+
|
|
29
|
+
params do # → Grape::Validations::ParamsScope
|
|
30
|
+
requires :id, type: Integer # Object?
|
|
31
|
+
optional :q, type: String # Object?
|
|
32
|
+
requires :filter, type: Hash do # nested scope re-enters ParamsScope
|
|
33
|
+
requires :state, type: String
|
|
34
|
+
end
|
|
35
|
+
mutually_exclusive :q, :filter
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
namespace :things do # self: the API::Instance class object
|
|
39
|
+
get "/:id" do # self: Grape::Endpoint
|
|
40
|
+
params # Hash[untyped, untyped]
|
|
41
|
+
error!("nope", 404) # bot
|
|
42
|
+
present Thing.first, with: Entities::Thing
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class Entities::Thing < Grape::Entity
|
|
48
|
+
expose :id # Array[untyped]
|
|
49
|
+
expose :name do # `self` stays the class object
|
|
50
|
+
expose :first
|
|
51
|
+
end
|
|
52
|
+
format_with(:iso) { |d| d.to_s } # Object
|
|
53
|
+
end
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Recognised surfaces:
|
|
57
|
+
|
|
58
|
+
- **Class-body declarations** on `Grape::API` subclasses (including
|
|
59
|
+
through intermediate source base classes): `params`, `namespace` /
|
|
60
|
+
`group` / `resource` / `resources` / `segment` / `route_param` /
|
|
61
|
+
`version` / `given` / `mounted`, `get`/`put`/`post`/`delete`/`head`/
|
|
62
|
+
`patch`/`options`/`route`, `desc`, `route_setting`, `helpers`, `use`,
|
|
63
|
+
`mount`, `rescue_from`, the format/error-format setters, callbacks
|
|
64
|
+
(`before`/`after`/`before_validation`/`after_validation`), `prefix`,
|
|
65
|
+
`scope`, `contract`, and friends.
|
|
66
|
+
- **`params` block bodies** bind `self` to
|
|
67
|
+
`Grape::Validations::ParamsScope`, so `requires`, `optional`, `given`,
|
|
68
|
+
`with`, `use`, and the grouping macros (`mutually_exclusive`,
|
|
69
|
+
`exactly_one_of`, `at_least_one_of`, `all_or_none_of`) resolve —
|
|
70
|
+
including nested `requires :x, type: Hash do ... end` bodies.
|
|
71
|
+
- **Namespace-family bodies** (`namespace`, `route_param`, `version`,
|
|
72
|
+
`given`, `mounted`) bind `self` to the `Grape::API::Instance` class
|
|
73
|
+
object, matching Grape's `instance_eval`-on-class semantics, so nested
|
|
74
|
+
declarations resolve the same surface.
|
|
75
|
+
- **`desc 'x' do ... end` bodies** bind `self` to
|
|
76
|
+
`Grape::DSL::Desc::ConfigContext` — the closed `ROUTE_ATTRIBUTES`
|
|
77
|
+
setter surface — so `detail`, `success`, `failure`, `tags`,
|
|
78
|
+
`entity`, `hidden`, `is_array`, `consumes`, `headers`, `summary`,
|
|
79
|
+
`deprecated`, `named`, `nickname`, `produces`, `security`,
|
|
80
|
+
`http_codes`, `body_name`, `default`, `description`, and `params`
|
|
81
|
+
(the documentation setter, not `ParamsScope`) resolve.
|
|
82
|
+
- **Verb bodies** bind `self` to `Grape::Endpoint`, so `params`,
|
|
83
|
+
`headers`, `cookies`, `env`, `declared`, `present`, `error!`,
|
|
84
|
+
`status`, `redirect`, `body`, `content_type`, `route`,
|
|
85
|
+
`route_setting`, `stream`, `sendfile` resolve.
|
|
86
|
+
- **`Grape::Entity` class bodies**: `expose`, `unexpose`,
|
|
87
|
+
`with_options`, `documentation`, `format_with`, `root`,
|
|
88
|
+
`root_element`, `represent`, `present_collection`, `root_exposures`.
|
|
89
|
+
Nested `expose` bodies keep `self` on the class object, so they
|
|
90
|
+
resolve the same way.
|
|
91
|
+
|
|
92
|
+
## Deferred
|
|
93
|
+
|
|
94
|
+
- `helpers do ... end` bodies (an anonymous module is `self` —
|
|
95
|
+
unnameable).
|
|
96
|
+
- Named `params :name` scopes inside `helpers` and `contract` schema
|
|
97
|
+
blocks.
|
|
98
|
+
- Value-level typing: `present`/`declared` results against the declared
|
|
99
|
+
entity or params, entity `represent` result typing.
|
|
100
|
+
- `Grape::Middleware` and custom-middleware DSL.
|
|
101
|
+
|
|
102
|
+
Calls on classes outside `Grape::API` / `Grape::Entity` ancestry keep
|
|
103
|
+
the `Dynamic` fallback, and DSL names the bundled signature does not
|
|
104
|
+
declare stay opaque rather than diagnosed — the declared classes are
|
|
105
|
+
registered as open receivers because Grape's runtime surface is
|
|
106
|
+
generated (`override_all_methods!`) and user base classes extend it.
|
|
@@ -58,11 +58,25 @@ name. `null:` extracts to `nullable:` (defaulting to `true`, mirroring
|
|
|
58
58
|
graphql-ruby); `required:` defaults to `false`. The single-element
|
|
59
59
|
`[String]` list form is recognised.
|
|
60
60
|
|
|
61
|
+
## Typed DSL surface
|
|
62
|
+
|
|
63
|
+
Beyond the fact tables, the plugin bundles the graphql-ruby class-level
|
|
64
|
+
DSL signature, so calls inside a recognised subclass type as their real
|
|
65
|
+
carriers instead of staying opaque: `field` returns
|
|
66
|
+
`GraphQL::Schema::Field`, `argument` returns `GraphQL::Schema::Argument`,
|
|
67
|
+
`Enum.value` returns `GraphQL::Schema::EnumValue`, `description` /
|
|
68
|
+
`graphql_name` return their configured strings, and the `Schema`
|
|
69
|
+
registration macros (`query`, `mutation`, `use`, `orphan_types`, …)
|
|
70
|
+
return what they registered. A block parameter on `field`/`argument`
|
|
71
|
+
(`field(:comments) { |f| … }`) types as `GraphQL::Schema::Field` /
|
|
72
|
+
`GraphQL::Schema::Argument`.
|
|
73
|
+
|
|
61
74
|
## No diagnostics, no config
|
|
62
75
|
|
|
63
76
|
The plugin emits no diagnostics and has no configuration knobs — it
|
|
64
|
-
contributes the type tables above for
|
|
65
|
-
walks every `paths:` entry's `.rb` files
|
|
77
|
+
contributes the type tables and signature above for the engine and
|
|
78
|
+
other plugins to consume. It walks every `paths:` entry's `.rb` files
|
|
79
|
+
for the schema-class shapes.
|
|
66
80
|
|
|
67
81
|
## Limitations
|
|
68
82
|
|
|
@@ -72,6 +86,13 @@ walks every `paths:` entry's `.rb` files for the schema-class shapes.
|
|
|
72
86
|
- **No `Schema.execute(...)` result typing.** Typing
|
|
73
87
|
`Schema.execute(query).to_h` against the queried fields is a future
|
|
74
88
|
plugin.
|
|
89
|
+
- **Interface DSL stays opaque.** `include GraphQL::Schema::Interface`
|
|
90
|
+
wires the DSL onto the includer through an include-time `extend`
|
|
91
|
+
hook RBS cannot express, so `field` inside an interface module is
|
|
92
|
+
not yet typed.
|
|
93
|
+
- **Zero-arity definition blocks keep an opaque `self`.**
|
|
94
|
+
`field :x do ... end` `instance_eval`s on the new `Field` at
|
|
95
|
+
runtime; only the explicit-parameter form (`{ |f| … }`) is typed.
|
|
75
96
|
- **Constant-form types only.** The string form (`field :foo, "User"`)
|
|
76
97
|
and the `<Type>.array` / `<Type>!` sugar chains are not recognised
|
|
77
98
|
(the `[String]` bracket form is). Multi-element and empty list
|
|
@@ -33,7 +33,7 @@ authorize(Comment, :edit) # error: no policy class CommentPolicy (did you mean
|
|
|
33
33
|
| `plugin.pundit.policy-call` | info | an `authorize` / `policy` / `policy_scope` call resolved to a discovered policy |
|
|
34
34
|
| `plugin.pundit.unknown-policy-class` | error | the record maps to a `<Type>Policy` with no entry in the index (with a did-you-mean) |
|
|
35
35
|
| `plugin.pundit.unknown-policy-method` | error | the policy exists but the `:action` has no `<action>?` predicate (lists known predicates + a did-you-mean) |
|
|
36
|
-
| `plugin.pundit.load-error` | warning | policy discovery failed (parse/read error) — once per
|
|
36
|
+
| `plugin.pundit.load-error` | warning | policy discovery failed (parse/read error) — once per run, on `.rigor.yml` |
|
|
37
37
|
|
|
38
38
|
The record maps to a policy by constant name or inferred
|
|
39
39
|
`Nominal[T]` (`Post` → `PostPolicy`); `:update` normalises to
|
|
@@ -88,6 +88,13 @@ candidate rather than being guessed at.
|
|
|
88
88
|
not validated when `local` has no inferred `Nominal[T]`.
|
|
89
89
|
- **`Scope` policies** are validated for class existence, not for
|
|
90
90
|
`Scope#resolve`.
|
|
91
|
+
- **The "failed to discover policies" warning is run-scoped.** It is
|
|
92
|
+
a fact about your configuration, not about any one source file, so
|
|
93
|
+
it is reported once per run on `.rigor.yml` rather than repeated on
|
|
94
|
+
every analysed file. It is `:warning`, so if you baselined it at its
|
|
95
|
+
old position that entry no longer matches and the row fails a
|
|
96
|
+
`--fail-on=warning` run — regenerate with `rigor baseline
|
|
97
|
+
regenerate`.
|
|
91
98
|
|
|
92
99
|
## Plugin internals
|
|
93
100
|
|
|
@@ -88,11 +88,16 @@ view templates containing lazy `t('.key')` calls.
|
|
|
88
88
|
may come from controller instance variables not visible in the
|
|
89
89
|
template source. Configure `view_search_paths:` to override the
|
|
90
90
|
default `["app/views"]`.
|
|
91
|
-
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
- **`load-error` rows are reported on `.rigor.yml`** — a locale
|
|
92
|
+
file that does not parse, or a locale or view scan that fails,
|
|
93
|
+
is reported once per run at `.rigor.yml:1:1`. They are
|
|
94
|
+
`:warning`, so if you baselined one at its old position on a
|
|
95
|
+
Ruby file, that entry no longer matches and the row fails a
|
|
96
|
+
`--fail-on=warning` run — regenerate with `rigor baseline
|
|
97
|
+
regenerate`. View diagnostics keep their view file position and
|
|
98
|
+
are reported once per run whatever `--workers` is set to
|
|
99
|
+
([#1060](https://github.com/rigortype/rigor/issues/1060)); a
|
|
100
|
+
baseline entry recorded against a view still matches.
|
|
96
101
|
- **Pluralization is recognised but not validated** — `count:` is
|
|
97
102
|
treated as a reserved option; whether the locale defines
|
|
98
103
|
`:zero` / `:one` / `:other` is not checked.
|
|
@@ -129,6 +129,13 @@ routed. Helper-name recognition for all three is unaffected.
|
|
|
129
129
|
doesn't model) may not register, which can surface a false
|
|
130
130
|
`unknown-helper`. Record those in a baseline, or
|
|
131
131
|
`# rigor:disable` the line.
|
|
132
|
+
- **The "routes file did not load" warning is run-scoped.** It is a
|
|
133
|
+
fact about your configuration, not about any one source file, so
|
|
134
|
+
it is reported once per run on `.rigor.yml` rather than on the
|
|
135
|
+
first analysed file. It is `:warning`, so if you baselined it at
|
|
136
|
+
its old position that entry no longer matches and the row fails a
|
|
137
|
+
`--fail-on=warning` run — regenerate with `rigor baseline
|
|
138
|
+
regenerate`.
|
|
132
139
|
- **Project-custom inflections** declared in
|
|
133
140
|
`config/initializers/inflections.rb` are not yet fully ingested
|
|
134
141
|
(ADR-39 slice 3); the standard ActiveSupport inflections are
|