rigortype 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/data/core_overlay/csv.rbs +28 -0
- data/data/core_overlay/psych.rbs +22 -0
- data/docs/handbook/01-getting-started.md +9 -1
- data/docs/handbook/02-everyday-types.md +4 -1
- data/docs/handbook/08-understanding-errors.md +3 -3
- data/docs/manual/01-installation.md +1 -0
- data/docs/manual/02-cli-reference.md +16 -7
- data/docs/manual/04-diagnostics.md +7 -4
- data/docs/manual/06-baseline.md +5 -2
- data/docs/manual/07-plugins.md +1 -1
- data/docs/manual/14-rails-quickstart.md +4 -2
- data/docs/manual/15-type-protection-coverage.md +27 -4
- data/docs/manual/plugins/rigor-actionpack.md +1 -1
- data/docs/manual/plugins/rigor-activerecord.md +12 -5
- data/docs/manual/plugins/rigor-rails-routes.md +11 -0
- data/lib/rigor/analysis/baseline.rb +56 -96
- data/lib/rigor/analysis/buffer_binding.rb +13 -20
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +29 -48
- data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +35 -54
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +23 -37
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +16 -23
- data/lib/rigor/analysis/check_rules/rule_walk.rb +48 -71
- data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +19 -28
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +48 -67
- data/lib/rigor/analysis/check_rules.rb +174 -274
- data/lib/rigor/analysis/dependency_recorder.rb +26 -38
- data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +13 -25
- data/lib/rigor/analysis/dependency_source_inference/builder.rb +17 -30
- data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +15 -26
- data/lib/rigor/analysis/dependency_source_inference/index.rb +45 -76
- data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +23 -40
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +50 -83
- data/lib/rigor/analysis/dependency_source_inference.rb +6 -10
- data/lib/rigor/analysis/diagnostic.rb +48 -75
- data/lib/rigor/analysis/erb_template_detector.rb +13 -18
- data/lib/rigor/analysis/fact_store.rb +12 -22
- data/lib/rigor/analysis/incremental.rb +47 -63
- data/lib/rigor/analysis/incremental_session.rb +74 -100
- data/lib/rigor/analysis/project_scan.rb +12 -23
- data/lib/rigor/analysis/result.rb +3 -5
- data/lib/rigor/analysis/rule_catalog.rb +67 -95
- data/lib/rigor/analysis/run_stats.rb +38 -61
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +101 -160
- data/lib/rigor/analysis/runner/pool_coordinator.rb +121 -188
- data/lib/rigor/analysis/runner/project_pre_passes.rb +62 -96
- data/lib/rigor/analysis/runner/run_snapshots.rb +12 -18
- data/lib/rigor/analysis/runner.rb +220 -333
- data/lib/rigor/analysis/self_call_resolution_recorder.rb +30 -43
- data/lib/rigor/analysis/worker_session.rb +64 -102
- data/lib/rigor/ast/type_node.rb +6 -8
- data/lib/rigor/ast.rb +6 -10
- data/lib/rigor/bleeding_edge.rb +27 -35
- data/lib/rigor/builtins/hkt_builtins.rb +7 -14
- data/lib/rigor/builtins/imported_refinements.rb +106 -149
- data/lib/rigor/builtins/predefined_constant_refinements.rb +51 -65
- data/lib/rigor/builtins/regex_refinement.rb +32 -43
- data/lib/rigor/builtins/static_return_refinements.rb +57 -81
- data/lib/rigor/cache/descriptor.rb +58 -94
- data/lib/rigor/cache/incremental_snapshot.rb +32 -48
- data/lib/rigor/cache/rbs_cache_producer.rb +10 -15
- data/lib/rigor/cache/rbs_class_ancestor_table.rb +10 -16
- data/lib/rigor/cache/rbs_class_type_param_names.rb +10 -16
- data/lib/rigor/cache/rbs_constant_table.rb +8 -13
- data/lib/rigor/cache/rbs_descriptor.rb +8 -13
- data/lib/rigor/cache/rbs_environment.rb +11 -19
- data/lib/rigor/cache/rbs_environment_marshal_patch.rb +11 -19
- data/lib/rigor/cache/rbs_known_class_names.rb +8 -12
- data/lib/rigor/cache/store.rb +248 -186
- data/lib/rigor/cli/annotate_command.rb +51 -88
- data/lib/rigor/cli/baseline_command.rb +10 -17
- data/lib/rigor/cli/check_command.rb +121 -199
- data/lib/rigor/cli/check_runner_factory.rb +8 -14
- data/lib/rigor/cli/ci_detector.rb +9 -14
- data/lib/rigor/cli/command.rb +8 -14
- data/lib/rigor/cli/coverage_command.rb +62 -48
- data/lib/rigor/cli/coverage_mutation.rb +14 -19
- data/lib/rigor/cli/coverage_report.rb +0 -2
- data/lib/rigor/cli/coverage_scan.rb +7 -11
- data/lib/rigor/cli/diagnostic_formats.rb +46 -62
- data/lib/rigor/cli/diff_command.rb +10 -20
- data/lib/rigor/cli/docs_command.rb +26 -40
- data/lib/rigor/cli/doctor_command.rb +8 -9
- data/lib/rigor/cli/explain_command.rb +4 -7
- data/lib/rigor/cli/fused_protection_renderer.rb +4 -5
- data/lib/rigor/cli/fused_protection_report.rb +6 -8
- data/lib/rigor/cli/lsp_command.rb +11 -19
- data/lib/rigor/cli/mcp_command.rb +4 -6
- data/lib/rigor/cli/mutation_protection_renderer.rb +3 -4
- data/lib/rigor/cli/mutation_protection_report.rb +6 -9
- data/lib/rigor/cli/options.rb +11 -19
- data/lib/rigor/cli/plugin_command.rb +18 -30
- data/lib/rigor/cli/plugins_command.rb +29 -51
- data/lib/rigor/cli/plugins_renderer.rb +12 -20
- data/lib/rigor/cli/prism_colorizer.rb +13 -19
- data/lib/rigor/cli/protection_fork_scan.rb +55 -0
- data/lib/rigor/cli/protection_renderer.rb +5 -7
- data/lib/rigor/cli/protection_report.rb +34 -18
- data/lib/rigor/cli/renderable.rb +4 -6
- data/lib/rigor/cli/show_bleedingedge_command.rb +5 -8
- data/lib/rigor/cli/sig_gen_command.rb +14 -26
- data/lib/rigor/cli/skill_command.rb +30 -47
- data/lib/rigor/cli/skill_describe.rb +40 -64
- data/lib/rigor/cli/trace_command.rb +9 -16
- data/lib/rigor/cli/trace_renderer.rb +35 -51
- data/lib/rigor/cli/triage_command.rb +6 -10
- data/lib/rigor/cli/triage_renderer.rb +1 -2
- data/lib/rigor/cli/type_of_command.rb +14 -23
- data/lib/rigor/cli/type_of_renderer.rb +3 -5
- data/lib/rigor/cli/type_scan_command.rb +6 -10
- data/lib/rigor/cli/type_scan_renderer.rb +3 -5
- data/lib/rigor/cli/type_scan_report.rb +2 -3
- data/lib/rigor/cli/upgrade_command.rb +2 -3
- data/lib/rigor/cli.rb +16 -28
- data/lib/rigor/config_audit.rb +35 -44
- data/lib/rigor/configuration/dependencies.rb +41 -70
- data/lib/rigor/configuration/severity_profile.rb +28 -42
- data/lib/rigor/configuration.rb +150 -241
- data/lib/rigor/environment/bundle_sig_discovery.rb +74 -118
- data/lib/rigor/environment/class_registry.rb +19 -26
- data/lib/rigor/environment/constant_type_cache_holder.rb +14 -21
- data/lib/rigor/environment/hkt_registry_holder.rb +6 -12
- data/lib/rigor/environment/lockfile_resolver.rb +31 -47
- data/lib/rigor/environment/missing_gem_constant_index.rb +128 -0
- data/lib/rigor/environment/rbs_collection_discovery.rb +39 -63
- data/lib/rigor/environment/rbs_coverage_report.rb +24 -42
- data/lib/rigor/environment/rbs_loader.rb +420 -518
- data/lib/rigor/environment/reflection.rb +28 -53
- data/lib/rigor/environment/reporters.rb +13 -24
- data/lib/rigor/environment.rb +225 -304
- data/lib/rigor/flow_contribution/conflict.rb +16 -27
- data/lib/rigor/flow_contribution/element.rb +7 -12
- data/lib/rigor/flow_contribution/fact.rb +33 -57
- data/lib/rigor/flow_contribution/merge_result.rb +6 -9
- data/lib/rigor/flow_contribution/merger.rb +32 -47
- data/lib/rigor/flow_contribution.rb +37 -55
- data/lib/rigor/inference/acceptance.rb +133 -219
- data/lib/rigor/inference/block_parameter_binder.rb +52 -82
- data/lib/rigor/inference/body_fixpoint.rb +22 -30
- data/lib/rigor/inference/budget_trace.rb +43 -63
- data/lib/rigor/inference/builtins/array_catalog.rb +4 -6
- data/lib/rigor/inference/builtins/comparable_catalog.rb +4 -6
- data/lib/rigor/inference/builtins/complex_catalog.rb +13 -19
- data/lib/rigor/inference/builtins/date_catalog.rb +38 -67
- data/lib/rigor/inference/builtins/encoding_catalog.rb +22 -36
- data/lib/rigor/inference/builtins/enumerable_catalog.rb +4 -6
- data/lib/rigor/inference/builtins/exception_catalog.rb +38 -57
- data/lib/rigor/inference/builtins/hash_catalog.rb +9 -14
- data/lib/rigor/inference/builtins/method_catalog.rb +29 -48
- data/lib/rigor/inference/builtins/numeric_catalog.rb +13 -18
- data/lib/rigor/inference/builtins/pathname_catalog.rb +8 -13
- data/lib/rigor/inference/builtins/proc_catalog.rb +38 -62
- data/lib/rigor/inference/builtins/random_catalog.rb +21 -32
- data/lib/rigor/inference/builtins/range_catalog.rb +12 -21
- data/lib/rigor/inference/builtins/rational_catalog.rb +9 -15
- data/lib/rigor/inference/builtins/re_catalog.rb +29 -48
- data/lib/rigor/inference/builtins/set_catalog.rb +18 -27
- data/lib/rigor/inference/builtins/string_catalog.rb +12 -19
- data/lib/rigor/inference/builtins/struct_catalog.rb +18 -30
- data/lib/rigor/inference/builtins/time_catalog.rb +28 -44
- data/lib/rigor/inference/closure_escape_analyzer.rb +44 -67
- data/lib/rigor/inference/coverage_scanner.rb +13 -18
- data/lib/rigor/inference/def_return_typer.rb +8 -14
- data/lib/rigor/inference/dynamic_origin.rb +23 -20
- data/lib/rigor/inference/expression_typer.rb +794 -1154
- data/lib/rigor/inference/fallback.rb +8 -12
- data/lib/rigor/inference/fallback_tracer.rb +4 -10
- data/lib/rigor/inference/flow_tracer.rb +25 -36
- data/lib/rigor/inference/fork_map.rb +87 -0
- data/lib/rigor/inference/hkt_body.rb +45 -68
- data/lib/rigor/inference/hkt_body_parser.rb +33 -52
- data/lib/rigor/inference/hkt_reducer.rb +38 -59
- data/lib/rigor/inference/hkt_registry.rb +50 -76
- data/lib/rigor/inference/indexed_narrowing.rb +55 -81
- data/lib/rigor/inference/macro_block_self_type.rb +21 -34
- data/lib/rigor/inference/method_dispatcher/array_to_h_folding.rb +11 -18
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +49 -83
- data/lib/rigor/inference/method_dispatcher/call_context.rb +16 -23
- data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +13 -22
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +307 -454
- data/lib/rigor/inference/method_dispatcher/data_folding.rb +24 -34
- data/lib/rigor/inference/method_dispatcher/file_folding.rb +22 -37
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +52 -81
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +51 -78
- data/lib/rigor/inference/method_dispatcher/literal_string_folding.rb +60 -97
- data/lib/rigor/inference/method_dispatcher/math_folding.rb +23 -34
- data/lib/rigor/inference/method_dispatcher/member_shape_projection.rb +18 -26
- data/lib/rigor/inference/method_dispatcher/method_folding.rb +37 -71
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +114 -182
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +122 -193
- data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +15 -24
- data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +64 -93
- data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +31 -45
- data/lib/rigor/inference/method_dispatcher/set_folding.rb +6 -9
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +356 -511
- data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +22 -32
- data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +15 -21
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +66 -82
- data/lib/rigor/inference/method_dispatcher/time_folding.rb +10 -15
- data/lib/rigor/inference/method_dispatcher/uri_folding.rb +9 -13
- data/lib/rigor/inference/method_dispatcher.rb +378 -524
- data/lib/rigor/inference/method_parameter_binder.rb +81 -114
- data/lib/rigor/inference/multi_target_binder.rb +51 -68
- data/lib/rigor/inference/mutation_widening.rb +115 -158
- data/lib/rigor/inference/narrowing.rb +627 -727
- data/lib/rigor/inference/origin_lookup.rb +38 -0
- data/lib/rigor/inference/parameter_inference_collector.rb +154 -109
- data/lib/rigor/inference/precision_scanner.rb +26 -35
- data/lib/rigor/inference/project_patched_methods.rb +20 -32
- data/lib/rigor/inference/project_patched_scanner.rb +23 -37
- data/lib/rigor/inference/protection_scanner.rb +16 -18
- data/lib/rigor/inference/rbs_type_translator.rb +49 -66
- data/lib/rigor/inference/scope_indexer.rb +473 -821
- data/lib/rigor/inference/statement_evaluator.rb +754 -1114
- data/lib/rigor/inference/struct_fold_safety.rb +34 -48
- data/lib/rigor/inference/synthetic_method.rb +9 -16
- data/lib/rigor/inference/synthetic_method_index.rb +20 -35
- data/lib/rigor/inference/synthetic_method_scanner.rb +63 -103
- data/lib/rigor/language_server/buffer_resolution.rb +6 -9
- data/lib/rigor/language_server/buffer_table.rb +11 -18
- data/lib/rigor/language_server/completion_provider.rb +69 -116
- data/lib/rigor/language_server/debouncer.rb +16 -25
- data/lib/rigor/language_server/diagnostic_publisher.rb +26 -40
- data/lib/rigor/language_server/document_symbol_provider.rb +14 -19
- data/lib/rigor/language_server/folding_range_provider.rb +11 -19
- data/lib/rigor/language_server/hover_provider.rb +8 -11
- data/lib/rigor/language_server/hover_renderer.rb +56 -93
- data/lib/rigor/language_server/loop.rb +14 -19
- data/lib/rigor/language_server/project_context.rb +46 -74
- data/lib/rigor/language_server/selection_range_provider.rb +9 -12
- data/lib/rigor/language_server/server.rb +55 -83
- data/lib/rigor/language_server/signature_help_provider.rb +29 -46
- data/lib/rigor/language_server/synchronized_writer.rb +4 -7
- data/lib/rigor/language_server/uri.rb +8 -13
- data/lib/rigor/language_server.rb +4 -6
- data/lib/rigor/mcp/loop.rb +2 -3
- data/lib/rigor/mcp/server.rb +4 -7
- data/lib/rigor/mcp.rb +3 -6
- data/lib/rigor/plugin/access_denied_error.rb +5 -8
- data/lib/rigor/plugin/additional_initializer.rb +21 -31
- data/lib/rigor/plugin/base.rb +335 -518
- data/lib/rigor/plugin/blueprint.rb +14 -23
- data/lib/rigor/plugin/box.rb +18 -29
- data/lib/rigor/plugin/fact_store.rb +16 -26
- data/lib/rigor/plugin/inflector.rb +37 -53
- data/lib/rigor/plugin/io_boundary.rb +33 -56
- data/lib/rigor/plugin/isolation.rb +42 -55
- data/lib/rigor/plugin/load_error.rb +10 -15
- data/lib/rigor/plugin/loader.rb +30 -49
- data/lib/rigor/plugin/macro/block_as_method.rb +20 -32
- data/lib/rigor/plugin/macro/heredoc_template.rb +35 -58
- data/lib/rigor/plugin/macro/nested_class_template.rb +22 -36
- data/lib/rigor/plugin/macro/trait_registry.rb +34 -51
- data/lib/rigor/plugin/macro.rb +10 -15
- data/lib/rigor/plugin/manifest.rb +85 -144
- data/lib/rigor/plugin/node_context.rb +14 -22
- data/lib/rigor/plugin/node_rule_walk.rb +49 -74
- data/lib/rigor/plugin/protocol_contract.rb +25 -39
- data/lib/rigor/plugin/registry.rb +132 -205
- data/lib/rigor/plugin/services.rb +21 -33
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -19
- data/lib/rigor/plugin/trust_policy.rb +24 -38
- data/lib/rigor/plugin/type_node_resolver.rb +15 -24
- data/lib/rigor/protection/diagnostic_oracle.rb +11 -13
- data/lib/rigor/protection/mutation_scanner.rb +27 -35
- data/lib/rigor/protection/mutator.rb +50 -70
- data/lib/rigor/protection/test_suite_oracle.rb +20 -27
- data/lib/rigor/rbs_extended/conformance_checker.rb +48 -68
- data/lib/rigor/rbs_extended/hkt_directives.rb +28 -54
- data/lib/rigor/rbs_extended/reporter.rb +24 -40
- data/lib/rigor/rbs_extended.rb +107 -197
- data/lib/rigor/reflection.rb +68 -86
- data/lib/rigor/scope/discovery_index.rb +14 -19
- data/lib/rigor/scope.rb +255 -310
- data/lib/rigor/sig_gen/classification.rb +6 -10
- data/lib/rigor/sig_gen/generator.rb +197 -323
- data/lib/rigor/sig_gen/layout_index.rb +12 -20
- data/lib/rigor/sig_gen/method_candidate.rb +12 -17
- data/lib/rigor/sig_gen/observation_collector.rb +38 -70
- data/lib/rigor/sig_gen/observed_call.rb +13 -23
- data/lib/rigor/sig_gen/path_mapper.rb +17 -29
- data/lib/rigor/sig_gen/renderer.rb +7 -13
- data/lib/rigor/sig_gen/type_elaborator.rb +15 -28
- data/lib/rigor/sig_gen/write_result.rb +8 -16
- data/lib/rigor/sig_gen/writer.rb +95 -174
- data/lib/rigor/sig_gen.rb +3 -6
- data/lib/rigor/signature_path_audit.rb +24 -30
- data/lib/rigor/source/constant_path.rb +10 -14
- data/lib/rigor/source/literals.rb +31 -45
- data/lib/rigor/source/node_locator.rb +9 -11
- data/lib/rigor/source/node_walker.rb +9 -13
- data/lib/rigor/source.rb +3 -4
- data/lib/rigor/testing.rb +16 -20
- data/lib/rigor/triage/catalogue.rb +38 -62
- data/lib/rigor/triage.rb +31 -52
- data/lib/rigor/trinary.rb +9 -13
- data/lib/rigor/type/acceptance_router.rb +4 -6
- data/lib/rigor/type/accepts_result.rb +10 -14
- data/lib/rigor/type/app.rb +19 -27
- data/lib/rigor/type/bot.rb +4 -6
- data/lib/rigor/type/bound_method.rb +10 -15
- data/lib/rigor/type/combinator.rb +165 -257
- data/lib/rigor/type/constant.rb +23 -34
- data/lib/rigor/type/data_class.rb +10 -15
- data/lib/rigor/type/data_instance.rb +14 -20
- data/lib/rigor/type/difference.rb +21 -32
- data/lib/rigor/type/dynamic.rb +3 -5
- data/lib/rigor/type/hash_shape.rb +32 -18
- data/lib/rigor/type/integer_range.rb +11 -16
- data/lib/rigor/type/intersection.rb +27 -42
- data/lib/rigor/type/nominal.rb +10 -15
- data/lib/rigor/type/plain_lattice.rb +9 -13
- data/lib/rigor/type/refined.rb +67 -114
- data/lib/rigor/type/singleton.rb +4 -6
- data/lib/rigor/type/struct_class.rb +11 -16
- data/lib/rigor/type/struct_instance.rb +15 -21
- data/lib/rigor/type/tuple.rb +14 -19
- data/lib/rigor/type/union.rb +30 -42
- data/lib/rigor/type_node/generic.rb +14 -26
- data/lib/rigor/type_node/identifier.rb +12 -19
- data/lib/rigor/type_node.rb +3 -12
- data/lib/rigor/value_semantics.rb +16 -21
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +18 -30
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +16 -29
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +12 -23
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +22 -39
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +26 -46
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +51 -87
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +10 -17
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +26 -39
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +141 -184
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +30 -51
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +57 -92
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +92 -108
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +13 -22
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +15 -25
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +8 -13
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +16 -24
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +40 -48
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +140 -129
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +56 -59
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +27 -41
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +16 -24
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +172 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +168 -241
- data/plugins/rigor-activerecord/lib/rigor-activerecord.rb +3 -5
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +8 -14
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +9 -15
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +4 -7
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +23 -41
- data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +3 -5
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +6 -10
- data/plugins/rigor-activesupport-core-ext/lib/rigor-activesupport-core-ext.rb +8 -11
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +32 -0
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +30 -45
- data/plugins/rigor-devise/lib/rigor-devise.rb +3 -5
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +43 -69
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +26 -35
- data/plugins/rigor-dry-schema/lib/rigor-dry-schema.rb +3 -5
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +30 -47
- data/plugins/rigor-dry-struct/lib/rigor-dry-struct.rb +3 -5
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +67 -113
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +29 -46
- data/plugins/rigor-dry-types/lib/rigor-dry-types.rb +3 -5
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -20
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +14 -23
- data/plugins/rigor-dry-validation/lib/rigor-dry-validation.rb +2 -3
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +22 -37
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +28 -46
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +13 -17
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +30 -47
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +52 -80
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +21 -31
- data/plugins/rigor-graphql/lib/rigor-graphql.rb +3 -5
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +11 -17
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +20 -34
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +45 -75
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +22 -36
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +22 -41
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +17 -32
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +6 -12
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +4 -8
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +17 -32
- data/plugins/rigor-rails/lib/rigor-rails.rb +11 -18
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +58 -92
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +20 -34
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +20 -31
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +49 -82
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +55 -92
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +51 -90
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +17 -30
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/grape_api_discoverer.rb +189 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +38 -70
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +61 -75
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +319 -505
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +91 -96
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +32 -54
- data/plugins/rigor-rbs-inline/lib/rigor-rbs-inline.rb +8 -13
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +9 -16
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +24 -39
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +13 -22
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +34 -56
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/scope_walker.rb +22 -42
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +43 -75
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +27 -39
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/http_status_codes.rb +14 -19
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +20 -34
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +28 -47
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +21 -37
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +13 -22
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +18 -31
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +6 -10
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +14 -29
- data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +23 -41
- data/plugins/rigor-sinatra/lib/rigor-sinatra.rb +3 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +23 -38
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +57 -96
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +22 -35
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +41 -69
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/method_signature.rb +6 -10
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +24 -41
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +29 -50
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +55 -88
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +159 -262
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +21 -29
- data/plugins/rigor-statesman/lib/rigor-statesman.rb +3 -5
- data/plugins/rigor-typescript-utility-types/lib/rigor/plugin/typescript_utility_types.rb +23 -37
- data/plugins/rigor-typescript-utility-types/lib/rigor-typescript-utility-types.rb +4 -6
- data/sig/rigor/environment.rbs +1 -0
- data/sig/rigor/scope.rbs +6 -0
- metadata +9 -1
|
@@ -7,15 +7,11 @@ require_relative "controller_index"
|
|
|
7
7
|
module Rigor
|
|
8
8
|
module Plugin
|
|
9
9
|
class Actionpack < Rigor::Plugin::Base
|
|
10
|
-
# Walks `controller_search_paths` building a
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# chains) to validate that `before_action :name`
|
|
14
|
-
# references a method defined on the controller or its
|
|
15
|
-
# ancestor chain.
|
|
10
|
+
# Walks `controller_search_paths` building a {ControllerIndex} of `(class_name, methods,
|
|
11
|
+
# parent_class_name)` triples. Used by Phase 2 (filter chains) to validate that `before_action
|
|
12
|
+
# :name` references a method defined on the controller or its ancestor chain.
|
|
16
13
|
#
|
|
17
|
-
# Two declaration shapes are recognised and qualified
|
|
18
|
-
# the same way:
|
|
14
|
+
# Two declaration shapes are recognised and qualified the same way:
|
|
19
15
|
#
|
|
20
16
|
# class Admin::AccountsController < BaseController
|
|
21
17
|
# # → registered as "Admin::AccountsController"
|
|
@@ -26,25 +22,18 @@ module Rigor
|
|
|
26
22
|
# end
|
|
27
23
|
# end
|
|
28
24
|
#
|
|
29
|
-
# Pre-fix the nested form ignored the enclosing `module
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
# `
|
|
33
|
-
#
|
|
34
|
-
# `AccountsController` + `Admin::AccountsController` +
|
|
35
|
-
# `Api::V1::AccountsController`) and the overwrite caused
|
|
36
|
-
# the wrong inheritance / method set to flow downstream,
|
|
37
|
-
# producing dozens of false `unknown-filter-method`
|
|
25
|
+
# Pre-fix the nested form ignored the enclosing `module Admin` and registered the inner class as
|
|
26
|
+
# bare `"AccountsController"`, overwriting the top-level `app/controllers/accounts_controller.rb`
|
|
27
|
+
# entry. Mastodon has both shapes for the same logical name (top-level `AccountsController` +
|
|
28
|
+
# `Admin::AccountsController` + `Api::V1::AccountsController`) and the overwrite caused the wrong
|
|
29
|
+
# inheritance / method set to flow downstream, producing dozens of false `unknown-filter-method`
|
|
38
30
|
# diagnostics.
|
|
39
31
|
#
|
|
40
|
-
# Multi-level inheritance is also walked: `Admin::AccountsController
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
# tries `Admin::BaseController`, then falls through to
|
|
46
|
-
# top-level `BaseController`, matching Ruby's constant-
|
|
47
|
-
# resolution semantics.
|
|
32
|
+
# Multi-level inheritance is also walked: `Admin::AccountsController < BaseController <
|
|
33
|
+
# ApplicationController` resolves methods from all three. Cycle-safe via a visited set. The
|
|
34
|
+
# parent-name lookup is **lexically scoped** — a bare `BaseController` reference inside `module
|
|
35
|
+
# Admin` first tries `Admin::BaseController`, then falls through to top-level `BaseController`,
|
|
36
|
+
# matching Ruby's constant-resolution semantics.
|
|
48
37
|
class ControllerDiscoverer
|
|
49
38
|
def initialize(io_boundary:, search_paths:)
|
|
50
39
|
@io_boundary = io_boundary
|
|
@@ -84,15 +73,12 @@ module Rigor
|
|
|
84
73
|
nil
|
|
85
74
|
end
|
|
86
75
|
|
|
87
|
-
# Walks every `ClassNode` / `ModuleNode` in the AST,
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
# `["Admin"]`). The yielded declaration's own segment
|
|
94
|
-
# is added to the chain for its body's recursion so
|
|
95
|
-
# constants nested two levels deep qualify correctly.
|
|
76
|
+
# Walks every `ClassNode` / `ModuleNode` in the AST, yielding `[declaration_node,
|
|
77
|
+
# enclosing_namespace_array]` for each. `enclosing` is the chain of module / class qualifiers
|
|
78
|
+
# OUTSIDE the yielded declaration (e.g. for `module Admin; class AccountsController; end; end`
|
|
79
|
+
# the inner class yields with enclosing `["Admin"]`). The yielded declaration's own segment is
|
|
80
|
+
# added to the chain for its body's recursion so constants nested two levels deep qualify
|
|
81
|
+
# correctly.
|
|
96
82
|
def walk_declarations(node, namespace:, &)
|
|
97
83
|
return unless node.is_a?(Prism::Node)
|
|
98
84
|
|
|
@@ -109,11 +95,9 @@ module Rigor
|
|
|
109
95
|
end
|
|
110
96
|
end
|
|
111
97
|
|
|
112
|
-
# The segments contributed by a declaration to the
|
|
113
|
-
#
|
|
114
|
-
#
|
|
115
|
-
# Returns `[]` for an anonymous declaration the walker
|
|
116
|
-
# cannot qualify.
|
|
98
|
+
# The segments contributed by a declaration to the qualifier chain of its body. For `class A::B`
|
|
99
|
+
# this is `["A", "B"]`; for `module Outer` it is `["Outer"]`. Returns `[]` for an anonymous
|
|
100
|
+
# declaration the walker cannot qualify.
|
|
117
101
|
def namespace_segments_for(declaration_node)
|
|
118
102
|
path = qualified_name_for(declaration_node.constant_path)
|
|
119
103
|
path ? path.split("::") : []
|
|
@@ -133,13 +117,10 @@ module Rigor
|
|
|
133
117
|
)
|
|
134
118
|
end
|
|
135
119
|
|
|
136
|
-
# Resolves the declared name against the enclosing
|
|
137
|
-
#
|
|
138
|
-
# `
|
|
139
|
-
#
|
|
140
|
-
# `ConstantReadNode` (bare `Foo` in `module Admin;
|
|
141
|
-
# class Foo`) is qualified against the chain so the
|
|
142
|
-
# name becomes `Admin::Foo`.
|
|
120
|
+
# Resolves the declared name against the enclosing namespace chain. A `ConstantPathNode` (e.g.
|
|
121
|
+
# `Admin::Foo` in `class Admin::Foo`) is already absolute and ignores the enclosing chain. A
|
|
122
|
+
# `ConstantReadNode` (bare `Foo` in `module Admin; class Foo`) is qualified against the chain so
|
|
123
|
+
# the name becomes `Admin::Foo`.
|
|
143
124
|
def qualified_name_with_enclosing(node, enclosing)
|
|
144
125
|
return nil unless node.is_a?(Prism::Node)
|
|
145
126
|
|
|
@@ -165,11 +146,9 @@ module Rigor
|
|
|
165
146
|
accumulator
|
|
166
147
|
end
|
|
167
148
|
|
|
168
|
-
# Collects the qualified-constant targets passed to
|
|
169
|
-
# `
|
|
170
|
-
#
|
|
171
|
-
# declared inside a concern doesn't pull the concern's
|
|
172
|
-
# includes into itself.
|
|
149
|
+
# Collects the qualified-constant targets passed to `include` calls inside the body. Stops at
|
|
150
|
+
# nested `ClassNode` / `ModuleNode` boundaries so a class declared inside a concern doesn't pull
|
|
151
|
+
# the concern's includes into itself.
|
|
173
152
|
def collect_include_targets(node, accumulator = [])
|
|
174
153
|
return accumulator unless node.is_a?(Prism::Node)
|
|
175
154
|
return accumulator if node.is_a?(Prism::ClassNode) || node.is_a?(Prism::ModuleNode)
|
|
@@ -3,13 +3,11 @@
|
|
|
3
3
|
module Rigor
|
|
4
4
|
module Plugin
|
|
5
5
|
class Actionpack < Rigor::Plugin::Base
|
|
6
|
-
# Per-run frozen index of discovered controllers AND
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
# parent (one level of inheritance), or any module the
|
|
12
|
-
# controller or its ancestor chain transitively `include`s.
|
|
6
|
+
# Per-run frozen index of discovered controllers AND concerns (modules) in
|
|
7
|
+
# `controller_search_paths`. Phase 2 (filter-chain validation) consults the index at every call
|
|
8
|
+
# site to check that `before_action :name` references a method that actually exists on the
|
|
9
|
+
# controller, its parent (one level of inheritance), or any module the controller or its ancestor
|
|
10
|
+
# chain transitively `include`s.
|
|
13
11
|
#
|
|
14
12
|
# Real-world example (Mastodon):
|
|
15
13
|
# AccountsController < ApplicationController
|
|
@@ -19,23 +17,17 @@ module Rigor
|
|
|
19
17
|
# SignatureVerification < module
|
|
20
18
|
# def require_account_signature! # ← the filter target
|
|
21
19
|
#
|
|
22
|
-
# The include chain spans three concern modules.
|
|
23
|
-
#
|
|
24
|
-
# of them transitively to collect `require_account_signature!`.
|
|
20
|
+
# The include chain spans three concern modules. `effective_methods_for("AccountsController")`
|
|
21
|
+
# walks all of them transitively to collect `require_account_signature!`.
|
|
25
22
|
class ControllerIndex
|
|
26
|
-
# `defined_methods` carries the discovered method names
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
# `module Admin; class Foo; end; end`). Used by the
|
|
35
|
-
# index's parent / module lookup to try lexically-scoped
|
|
36
|
-
# constant resolution before falling through to the
|
|
37
|
-
# top-level form — Ruby's constant lookup walks the
|
|
38
|
-
# enclosing scope chain before `Object`.
|
|
23
|
+
# `defined_methods` carries the discovered method names (Symbols). `included_module_names`
|
|
24
|
+
# carries the constant names passed to `include X` calls inside the class / module body
|
|
25
|
+
# (Strings). `parent_class_name` is the immediate superclass (nil for plain modules).
|
|
26
|
+
# `enclosing_namespace` is the qualifier chain of the declaration's *lexical* enclosing scope
|
|
27
|
+
# (e.g. `["Admin"]` for an `Admin::Foo` declared via `module Admin; class Foo; end; end`). Used
|
|
28
|
+
# by the index's parent / module lookup to try lexically-scoped constant resolution before
|
|
29
|
+
# falling through to the top-level form — Ruby's constant lookup walks the enclosing scope chain
|
|
30
|
+
# before `Object`.
|
|
39
31
|
Entry = Data.define(:class_name, :defined_methods, :parent_class_name, :included_module_names,
|
|
40
32
|
:enclosing_namespace)
|
|
41
33
|
|
|
@@ -51,20 +43,15 @@ module Rigor
|
|
|
51
43
|
@entries[class_name]
|
|
52
44
|
end
|
|
53
45
|
|
|
54
|
-
# Resolves the **effective** method set for a controller,
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
# methods inherited from the ancestor chain (unbounded
|
|
58
|
-
# depth, cycle-safe via a visited set).
|
|
46
|
+
# Resolves the **effective** method set for a controller, including methods contributed by
|
|
47
|
+
# every module the controller / any ancestor transitively `include`s AND methods inherited from
|
|
48
|
+
# the ancestor chain (unbounded depth, cycle-safe via a visited set).
|
|
59
49
|
#
|
|
60
|
-
# Parent / module lookups are **lexically scoped** — a
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
#
|
|
65
|
-
# `Admin::Foo < BaseController` declaration would
|
|
66
|
-
# incorrectly walk the top-level `BaseController` even
|
|
67
|
-
# when an `Admin::BaseController` exists.
|
|
50
|
+
# Parent / module lookups are **lexically scoped** — a bare `BaseController` reference inside
|
|
51
|
+
# `module Admin` first tries `Admin::BaseController`, then falls through to the top-level
|
|
52
|
+
# `BaseController`. Matches Ruby's constant-resolution semantics. Without this an `Admin::Foo <
|
|
53
|
+
# BaseController` declaration would incorrectly walk the top-level `BaseController` even when an
|
|
54
|
+
# `Admin::BaseController` exists.
|
|
68
55
|
def effective_methods_for(class_name)
|
|
69
56
|
seen_classes = {}
|
|
70
57
|
seen_modules = {}
|
|
@@ -81,11 +68,9 @@ module Rigor
|
|
|
81
68
|
collect_methods(resolved_include, seen_modules, methods)
|
|
82
69
|
end
|
|
83
70
|
next_parent = entry.parent_class_name
|
|
84
|
-
# Same self-reference guard as `unresolved_include?`:
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
# `ApplicationController` to itself; fall back to
|
|
88
|
-
# the unprefixed top-level name in that case.
|
|
71
|
+
# Same self-reference guard as `unresolved_include?`: `class ActivityPub::ApplicationController
|
|
72
|
+
# < ::ApplicationController` lexically resolves `ApplicationController` to itself; fall back
|
|
73
|
+
# to the unprefixed top-level name in that case.
|
|
89
74
|
current = if next_parent
|
|
90
75
|
resolved = resolve_constant_lexically(next_parent, entry.enclosing_namespace)
|
|
91
76
|
resolved == current ? next_parent.sub(/\A::/, "") : resolved
|
|
@@ -94,30 +79,23 @@ module Rigor
|
|
|
94
79
|
methods.uniq.freeze
|
|
95
80
|
end
|
|
96
81
|
|
|
97
|
-
# @return [Boolean] true when the class has at least one
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
# `Devise::
|
|
101
|
-
#
|
|
102
|
-
# or
|
|
103
|
-
#
|
|
104
|
-
# to silence — the unresolved module / parent may
|
|
105
|
-
# legitimately contribute the filter (either directly,
|
|
106
|
-
# or via its own ancestor chain which the static
|
|
107
|
-
# analyzer cannot follow), and there's no way to verify.
|
|
82
|
+
# @return [Boolean] true when the class has at least one include OR parent class we couldn't
|
|
83
|
+
# resolve in the index (typically a gem-shipped concern such as Devise's
|
|
84
|
+
# `Devise::Controllers::Helpers`, or a gem-shipped parent controller such as
|
|
85
|
+
# `Devise::ConfirmationsController` or `Doorkeeper::AuthorizedApplicationsController`). Phase
|
|
86
|
+
# 2 uses this to downgrade `unknown-filter-method` to silence — the unresolved module / parent
|
|
87
|
+
# may legitimately contribute the filter (either directly, or via its own ancestor chain which
|
|
88
|
+
# the static analyzer cannot follow), and there's no way to verify.
|
|
108
89
|
def unresolved_include?(class_name)
|
|
109
90
|
entry = @entries[class_name]
|
|
110
91
|
return false if entry.nil?
|
|
111
92
|
|
|
112
|
-
# Walk the full ancestor chain. `Admin::Foo <
|
|
113
|
-
#
|
|
114
|
-
#
|
|
115
|
-
# a
|
|
116
|
-
#
|
|
117
|
-
#
|
|
118
|
-
# `current_entry` on a subsequent iteration means the
|
|
119
|
-
# AST-side `< Parent` reached a gem-shipped class
|
|
120
|
-
# whose ancestor methods are invisible to us.
|
|
93
|
+
# Walk the full ancestor chain. `Admin::Foo < BaseController < ApplicationController` should
|
|
94
|
+
# report an unresolved include if ANY of the three references a gem-shipped concern OR a
|
|
95
|
+
# gem-shipped parent class we cannot index. The first iteration's `current_entry` is always
|
|
96
|
+
# resolved (caller verified `known?`); a nil `current_entry` on a subsequent iteration means
|
|
97
|
+
# the AST-side `< Parent` reached a gem-shipped class whose ancestor methods are invisible to
|
|
98
|
+
# us.
|
|
121
99
|
seen_classes = {}
|
|
122
100
|
current = class_name
|
|
123
101
|
first = true
|
|
@@ -136,15 +114,11 @@ module Rigor
|
|
|
136
114
|
return true if resolved.nil? || !@entries.key?(resolved)
|
|
137
115
|
end
|
|
138
116
|
next_parent = current_entry.parent_class_name
|
|
139
|
-
# Avoid lexically resolving to ourselves. `class
|
|
140
|
-
#
|
|
141
|
-
#
|
|
142
|
-
# the lexical
|
|
143
|
-
#
|
|
144
|
-
# circuit the walk before reaching the top-level
|
|
145
|
-
# parent. When the lexical match is the current
|
|
146
|
-
# class itself, fall back to the unprefixed
|
|
147
|
-
# top-level name.
|
|
117
|
+
# Avoid lexically resolving to ourselves. `class ActivityPub::ApplicationController <
|
|
118
|
+
# ::ApplicationController` would otherwise resolve `ApplicationController` (in the lexical
|
|
119
|
+
# scope `["ActivityPub"]`) to `ActivityPub::ApplicationController` and short-circuit the walk
|
|
120
|
+
# before reaching the top-level parent. When the lexical match is the current class itself,
|
|
121
|
+
# fall back to the unprefixed top-level name.
|
|
148
122
|
current = if next_parent
|
|
149
123
|
resolved = resolve_constant_lexically(next_parent, current_entry.enclosing_namespace)
|
|
150
124
|
resolved == current ? next_parent.sub(/\A::/, "") : resolved
|
|
@@ -181,37 +155,28 @@ module Rigor
|
|
|
181
155
|
end
|
|
182
156
|
end
|
|
183
157
|
|
|
184
|
-
# Ruby's constant-lookup walk: a bare constant name
|
|
185
|
-
#
|
|
186
|
-
#
|
|
187
|
-
#
|
|
188
|
-
# the
|
|
189
|
-
#
|
|
190
|
-
# candidate that has an entry in the index. When
|
|
191
|
-
# nothing resolves, return the original name
|
|
192
|
-
# unchanged — the caller treats unresolved entries as
|
|
193
|
-
# "gem-shipped concerns we cannot see" (the
|
|
194
|
-
# `unresolved_include?` predicate).
|
|
158
|
+
# Ruby's constant-lookup walk: a bare constant name inside `module Admin` first tries
|
|
159
|
+
# `Admin::Const`, then walks outward, and finally falls through to top-level `Const`. We
|
|
160
|
+
# approximate that by trying the candidate `enclosing + name` chains from deepest to shallowest,
|
|
161
|
+
# and returning the first candidate that has an entry in the index. When nothing resolves,
|
|
162
|
+
# return the original name unchanged — the caller treats unresolved entries as "gem-shipped
|
|
163
|
+
# concerns we cannot see" (the `unresolved_include?` predicate).
|
|
195
164
|
#
|
|
196
|
-
# `name` may already be qualified (`Foo::Bar`); we
|
|
197
|
-
#
|
|
198
|
-
# first segment doesn't match a top-level entry.
|
|
165
|
+
# `name` may already be qualified (`Foo::Bar`); we only try lexical prefixing when the
|
|
166
|
+
# unqualified first segment doesn't match a top-level entry.
|
|
199
167
|
def resolve_constant_lexically(name, enclosing)
|
|
200
168
|
return nil if name.nil?
|
|
201
169
|
|
|
202
|
-
# A leading `::` denotes the top-level constant
|
|
203
|
-
#
|
|
204
|
-
#
|
|
205
|
-
#
|
|
206
|
-
# `class ActivityPub::ApplicationController <
|
|
207
|
-
# ::ApplicationController` parent never resolved.
|
|
170
|
+
# A leading `::` denotes the top-level constant explicitly (`< ::ApplicationController`).
|
|
171
|
+
# Strip it for index lookup — the discoverer registers entries under their unprefixed name.
|
|
172
|
+
# Without this strip a `class ActivityPub::ApplicationController < ::ApplicationController`
|
|
173
|
+
# parent never resolved.
|
|
208
174
|
name = name.sub(/\A::/, "")
|
|
209
175
|
|
|
210
176
|
# Constant already absolute or no enclosing scope.
|
|
211
177
|
return name if enclosing.nil? || enclosing.empty?
|
|
212
178
|
|
|
213
|
-
# Try the deepest enclosing scope first, walking
|
|
214
|
-
# outward. `enclosing = ["A", "B"]` produces
|
|
179
|
+
# Try the deepest enclosing scope first, walking outward. `enclosing = ["A", "B"]` produces
|
|
215
180
|
# candidates `["A::B::name", "A::name", "name"]`.
|
|
216
181
|
enclosing.length.downto(0).each do |depth|
|
|
217
182
|
prefix = enclosing[0, depth]
|