rigortype 0.4.5 → 0.4.7
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/gem_overlay/activesupport/core_ext.rbs +16 -13
- data/data/vendored_gem_sigs/bundler/bundler.rbs +1 -1
- data/data/vendored_gem_sigs/rubygems/rubygems_extras.rbs +4 -3
- data/docs/handbook/01-getting-started.md +5 -2
- data/docs/handbook/11-sig-gen.md +61 -5
- data/docs/handbook/appendix-phpstan.md +4 -4
- data/docs/manual/02-cli-reference.md +192 -27
- data/docs/manual/03-configuration.md +38 -4
- data/docs/manual/04-diagnostics.md +1 -1
- data/docs/manual/06-baseline.md +6 -4
- data/docs/manual/09-editor-integration.md +13 -2
- data/docs/manual/10-mcp-server.md +47 -3
- data/docs/manual/12-caching.md +9 -1
- data/docs/manual/plugins/rigor-actionmailer.md +30 -0
- data/docs/manual/plugins/rigor-actionpack.md +49 -11
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +20 -1
- data/docs/manual/plugins/rigor-devise.md +15 -0
- data/docs/manual/plugins/rigor-rspec.md +2 -1
- data/lib/rigor/analysis/baseline.rb +24 -27
- data/lib/rigor/analysis/buffer_binding.rb +14 -0
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +5 -6
- data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +4 -4
- data/lib/rigor/analysis/check_rules/duplicate_hash_key_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/inferred_param_guard.rb +105 -12
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +143 -15
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +4 -1
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +5 -8
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +1 -1
- data/lib/rigor/analysis/check_rules/rbs_receiver_surface.rb +66 -3
- data/lib/rigor/analysis/check_rules/rebinding_block_callees/dispatch.rb +112 -0
- data/lib/rigor/analysis/check_rules/rebinding_block_callees.rb +394 -0
- data/lib/rigor/analysis/check_rules/return_in_ensure_collector.rb +1 -2
- data/lib/rigor/analysis/check_rules/ruby_deprecations.rb +7 -0
- data/lib/rigor/analysis/check_rules/rule_ids.rb +1 -1
- data/lib/rigor/analysis/check_rules/rule_walk.rb +9 -7
- data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +3 -4
- data/lib/rigor/analysis/check_rules/special_global_setters.rb +3 -3
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +53 -2
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +1 -1
- data/lib/rigor/analysis/check_rules.rb +217 -52
- data/lib/rigor/analysis/crash_signature.rb +2 -2
- data/lib/rigor/analysis/dependency_recorder.rb +15 -4
- data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +14 -3
- data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +1 -1
- data/lib/rigor/analysis/dependency_source_inference/index.rb +6 -8
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
- data/lib/rigor/analysis/edit_replay.rb +154 -0
- data/lib/rigor/analysis/fact_store.rb +3 -3
- data/lib/rigor/analysis/incremental.rb +37 -0
- data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +2 -2
- data/lib/rigor/analysis/incremental_run_slot.rb +2 -2
- data/lib/rigor/analysis/incremental_session.rb +202 -43
- data/lib/rigor/analysis/path_expansion.rb +41 -0
- data/lib/rigor/analysis/require_relative_closure.rb +100 -0
- data/lib/rigor/analysis/rule_catalog.rb +7 -3
- data/lib/rigor/analysis/run_disclosure_credit.rb +80 -0
- data/lib/rigor/analysis/run_disclosure_ledger.rb +155 -0
- data/lib/rigor/analysis/run_stats.rb +2 -2
- data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +8 -4
- data/lib/rigor/analysis/runner/declaration_position.rb +1 -1
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +204 -96
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +1 -1
- data/lib/rigor/analysis/runner/pool_coordinator.rb +157 -320
- data/lib/rigor/analysis/runner/project_pre_passes.rb +48 -6
- data/lib/rigor/analysis/runner/run_level_facts.rb +304 -0
- data/lib/rigor/analysis/runner/run_snapshots.rb +44 -54
- data/lib/rigor/analysis/runner/scan_environment.rb +51 -0
- data/lib/rigor/analysis/runner/worker_payload.rb +36 -0
- data/lib/rigor/analysis/runner.rb +233 -120
- data/lib/rigor/analysis/self_call_resolution_recorder.rb +1 -1
- data/lib/rigor/analysis/template_unit_positions.rb +2 -3
- data/lib/rigor/analysis/template_units.rb +9 -1
- data/lib/rigor/analysis/worker_session.rb +38 -33
- data/lib/rigor/bleeding_edge.rb +3 -6
- data/lib/rigor/builtins/imported_refinements.rb +6 -8
- data/lib/rigor/builtins/predefined_constant_refinements.rb +1 -1
- data/lib/rigor/builtins/regex_refinement.rb +4 -6
- data/lib/rigor/cache/descriptor.rb +6 -5
- data/lib/rigor/cache/incremental_snapshot.rb +60 -18
- data/lib/rigor/cache/rbs_cache_producer.rb +2 -2
- data/lib/rigor/cache/rbs_class_ancestor_table.rb +1 -1
- data/lib/rigor/cache/rbs_class_type_param_names.rb +2 -2
- data/lib/rigor/cache/rbs_constant_table.rb +1 -1
- data/lib/rigor/cache/rbs_descriptor.rb +54 -3
- data/lib/rigor/cache/rbs_environment.rb +4 -1
- data/lib/rigor/cache/rbs_environment_marshal_patch.rb +2 -2
- data/lib/rigor/cache/rbs_known_class_names.rb +1 -1
- data/lib/rigor/cache/store.rb +11 -10
- data/lib/rigor/ci_detector.rb +1 -1
- data/lib/rigor/cli/annotate_command.rb +24 -19
- data/lib/rigor/cli/baseline_command.rb +145 -55
- data/lib/rigor/cli/catalogue.rb +256 -0
- data/lib/rigor/cli/check_command.rb +188 -93
- data/lib/rigor/cli/check_runner_factory.rb +2 -2
- data/lib/rigor/cli/command.rb +15 -1
- data/lib/rigor/cli/coverage_command.rb +21 -8
- data/lib/rigor/cli/coverage_mutation.rb +5 -7
- data/lib/rigor/cli/coverage_renderer.rb +2 -1
- data/lib/rigor/cli/coverage_scan.rb +3 -5
- data/lib/rigor/cli/diff_command.rb +27 -21
- data/lib/rigor/cli/docs_command.rb +1 -2
- data/lib/rigor/cli/doctor_command.rb +12 -12
- data/lib/rigor/cli/effects_command.rb +50 -40
- data/lib/rigor/cli/effects_diff_renderer.rb +18 -17
- data/lib/rigor/cli/effects_explain_renderer.rb +13 -12
- data/lib/rigor/cli/effects_renderer.rb +2 -1
- data/lib/rigor/cli/effects_snapshot_command.rb +18 -17
- data/lib/rigor/cli/explain_command.rb +18 -8
- data/lib/rigor/cli/fused_protection_renderer.rb +2 -1
- data/lib/rigor/cli/json_document.rb +41 -0
- data/lib/rigor/cli/lens_command.rb +17 -13
- data/lib/rigor/cli/lsp_command.rb +250 -23
- data/lib/rigor/cli/mcp_command.rb +14 -8
- data/lib/rigor/cli/mutation_fork_scan.rb +1 -1
- data/lib/rigor/cli/mutation_protection_renderer.rb +3 -2
- data/lib/rigor/cli/options.rb +60 -4
- data/lib/rigor/cli/plugin_command.rb +93 -46
- data/lib/rigor/cli/plugins_command.rb +22 -18
- data/lib/rigor/cli/plugins_renderer.rb +34 -8
- data/lib/rigor/cli/protection_fork_scan.rb +2 -2
- data/lib/rigor/cli/protection_renderer.rb +2 -1
- data/lib/rigor/cli/show_bleedingedge_command.rb +23 -16
- data/lib/rigor/cli/sig_gen_command.rb +130 -34
- data/lib/rigor/cli/skill_command.rb +32 -3
- data/lib/rigor/cli/skill_deep_probe.rb +1 -1
- data/lib/rigor/cli/skill_describe.rb +1 -1
- data/lib/rigor/cli/trace_command.rb +14 -9
- data/lib/rigor/cli/triage_command.rb +10 -11
- data/lib/rigor/cli/triage_renderer.rb +2 -1
- data/lib/rigor/cli/type_of_command.rb +18 -12
- data/lib/rigor/cli/type_of_project_scope.rb +24 -0
- data/lib/rigor/cli/type_of_renderer.rb +4 -1
- data/lib/rigor/cli/type_scan_command.rb +14 -9
- data/lib/rigor/cli/type_scan_renderer.rb +2 -1
- data/lib/rigor/cli/unused_command.rb +27 -17
- data/lib/rigor/cli/upgrade_command.rb +5 -0
- data/lib/rigor/cli.rb +209 -54
- data/lib/rigor/config_audit.rb +17 -6
- data/lib/rigor/configuration/severity_profile.rb +5 -5
- data/lib/rigor/configuration.rb +86 -34
- data/lib/rigor/effects/definition_context.rb +0 -2
- data/lib/rigor/effects/envelope.rb +1 -1
- data/lib/rigor/effects/framework_units.rb +1 -1
- data/lib/rigor/effects/mutation_classifier.rb +4 -7
- data/lib/rigor/effects/propagator.rb +1 -1
- data/lib/rigor/effects/registry.rb +2 -2
- data/lib/rigor/effects/snapshot.rb +1 -1
- data/lib/rigor/effects/taint_cause.rb +0 -2
- data/lib/rigor/effects/unit_scan.rb +9 -13
- data/lib/rigor/environment/bundle_sig_discovery.rb +5 -9
- data/lib/rigor/environment/class_registry.rb +3 -3
- data/lib/rigor/environment/core_root.rb +77 -0
- data/lib/rigor/environment/default_libraries.rb +1 -1
- data/lib/rigor/environment/deferred_signature_plan.rb +283 -0
- data/lib/rigor/environment/gated_signature_guard.rb +1 -1
- data/lib/rigor/environment/gated_signature_plan.rb +5 -2
- data/lib/rigor/environment/lockfile_resolver.rb +28 -12
- data/lib/rigor/environment/member_consistency/comparator.rb +18 -1
- data/lib/rigor/environment/member_consistency.rb +56 -7
- data/lib/rigor/environment/missing_gem_constant_index.rb +3 -2
- data/lib/rigor/environment/project_path_gems.rb +124 -0
- data/lib/rigor/environment/rbs_hierarchy.rb +6 -15
- data/lib/rigor/environment/rbs_loader.rb +592 -70
- data/lib/rigor/environment/reflection.rb +7 -7
- data/lib/rigor/environment/required_features.rb +136 -32
- data/lib/rigor/environment/ruby_library_roots.rb +122 -0
- data/lib/rigor/environment/vendored_signature_plan.rb +153 -0
- data/lib/rigor/environment.rb +44 -11
- data/lib/rigor/flow_contribution/merger.rb +4 -4
- data/lib/rigor/inference/acceptance.rb +93 -32
- data/lib/rigor/inference/block_parameter_binder.rb +2 -3
- data/lib/rigor/inference/block_run_count.rb +178 -0
- data/lib/rigor/inference/budget_trace.rb +8 -2
- data/lib/rigor/inference/builtins/exception_catalog.rb +2 -2
- data/lib/rigor/inference/builtins/numeric_catalog.rb +2 -5
- data/lib/rigor/inference/builtins/random_catalog.rb +2 -2
- data/lib/rigor/inference/callee_mutation_chain.rb +126 -0
- data/lib/rigor/inference/callee_write_census.rb +815 -0
- data/lib/rigor/inference/construction_escape.rb +217 -0
- data/lib/rigor/inference/declaration_walk/traversal.rb +1 -1
- data/lib/rigor/inference/deep_erasure.rb +170 -0
- data/lib/rigor/inference/def_handle.rb +1 -1
- data/lib/rigor/inference/def_node_resolver.rb +1 -1
- data/lib/rigor/inference/def_return_typer.rb +204 -12
- data/lib/rigor/inference/definer_resolution.rb +21 -5
- data/lib/rigor/inference/definers_index.rb +106 -0
- data/lib/rigor/inference/direct_ivar_writes.rb +300 -0
- data/lib/rigor/inference/element_read_widening.rb +49 -3
- data/lib/rigor/inference/error_info.rb +17 -3
- data/lib/rigor/inference/expression_typer.rb +173 -57
- data/lib/rigor/inference/external_ancestor_resolution.rb +3 -4
- data/lib/rigor/inference/global_write_census.rb +110 -1
- data/lib/rigor/inference/global_writer_reach.rb +260 -0
- data/lib/rigor/inference/hkt_body.rb +1 -2
- data/lib/rigor/inference/hkt_body_parser.rb +3 -5
- data/lib/rigor/inference/hkt_reducer.rb +2 -2
- data/lib/rigor/inference/hkt_registry.rb +3 -5
- data/lib/rigor/inference/indexed_narrowing.rb +4 -7
- data/lib/rigor/inference/intervening_ivar_reset.rb +26 -4
- data/lib/rigor/inference/ivar_writer_census.rb +246 -0
- data/lib/rigor/inference/key_presence_guard.rb +2 -1
- data/lib/rigor/inference/loop_value_record.rb +57 -0
- data/lib/rigor/inference/match_rebinding/frame.rb +65 -0
- data/lib/rigor/inference/match_rebinding/yielding_match.rb +45 -0
- data/lib/rigor/inference/match_rebinding.rb +11 -1
- data/lib/rigor/inference/memo_audit.rb +55 -0
- data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/argument_distribution.rb +40 -0
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +113 -12
- data/lib/rigor/inference/method_dispatcher/contested_overloads.rb +89 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +7 -3
- data/lib/rigor/inference/method_dispatcher/no_match_fallback.rb +54 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +39 -27
- data/lib/rigor/inference/method_dispatcher/random_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +203 -17
- data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/self_substitute.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/set_folding.rb +59 -24
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +83 -20
- data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +0 -1
- data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +50 -17
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -5
- data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +4 -6
- data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher.rb +109 -29
- data/lib/rigor/inference/module_function_state/spellings.rb +64 -0
- data/lib/rigor/inference/module_function_state.rb +23 -1
- data/lib/rigor/inference/multi_target_binder.rb +1 -1
- data/lib/rigor/inference/mutation_rejoin.rb +240 -4
- data/lib/rigor/inference/mutation_widening.rb +162 -29
- data/lib/rigor/inference/narrowing.rb +113 -38
- data/lib/rigor/inference/object_mixins.rb +13 -1
- data/lib/rigor/inference/optimistic_origin.rb +1 -1
- data/lib/rigor/inference/out_buffer_mutation.rb +72 -0
- data/lib/rigor/inference/parameter_inference_collector.rb +5 -6
- data/lib/rigor/inference/pre_eval_constants.rb +1 -1
- data/lib/rigor/inference/project_method_ownership.rb +6 -3
- data/lib/rigor/inference/project_seed_tables.rb +2 -1
- data/lib/rigor/inference/project_yielder.rb +122 -0
- data/lib/rigor/inference/receiver_alias.rb +20 -0
- data/lib/rigor/inference/refined_dispatch/constructed_class.rb +3 -1
- data/lib/rigor/inference/refined_dispatch/own_method.rb +2 -1
- data/lib/rigor/inference/remover_holder_scan.rb +233 -0
- data/lib/rigor/inference/remover_narrowing.rb +224 -0
- data/lib/rigor/inference/rewrite_mutation.rb +53 -2
- data/lib/rigor/inference/scope_indexer/certainty.rb +9 -1
- data/lib/rigor/inference/scope_indexer/constant_ivar_value.rb +93 -0
- data/lib/rigor/inference/scope_indexer/declared_ivar_types.rb +64 -0
- data/lib/rigor/inference/scope_indexer/declared_param_writes.rb +205 -0
- data/lib/rigor/inference/scope_indexer/derived_param_value.rb +112 -0
- data/lib/rigor/inference/scope_indexer/empty_seed.rb +99 -0
- data/lib/rigor/inference/scope_indexer/ivar_contributions.rb +135 -0
- data/lib/rigor/inference/scope_indexer/unseen_ivar_writers.rb +133 -0
- data/lib/rigor/inference/scope_indexer.rb +614 -146
- data/lib/rigor/inference/self_call_ivar_writes.rb +101 -17
- data/lib/rigor/inference/set_mutation.rb +189 -0
- data/lib/rigor/inference/singleton_hook_decline.rb +1 -2
- data/lib/rigor/inference/statement_evaluator.rb +3036 -278
- data/lib/rigor/inference/struct_fold_safety.rb +4 -6
- data/lib/rigor/inference/synthetic_method_index.rb +23 -0
- data/lib/rigor/inference/synthetic_method_scanner/project_members.rb +130 -0
- data/lib/rigor/inference/synthetic_method_scanner.rb +73 -14
- data/lib/rigor/inference/toplevel_def_census.rb +59 -0
- data/lib/rigor/inference/unknown_store_widening.rb +103 -4
- data/lib/rigor/inference/unthreaded_rebinds.rb +2 -3
- data/lib/rigor/inference/void_tail_summary.rb +2 -1
- data/lib/rigor/language_server/buffer_table.rb +9 -3
- data/lib/rigor/language_server/completion_provider.rb +26 -20
- data/lib/rigor/language_server/config_warning_announcer.rb +28 -0
- data/lib/rigor/language_server/diagnostic_publisher.rb +28 -9
- data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
- data/lib/rigor/language_server/folding_range_provider.rb +1 -2
- data/lib/rigor/language_server/hover_provider.rb +1 -7
- data/lib/rigor/language_server/hover_renderer.rb +6 -8
- data/lib/rigor/language_server/project_context.rb +98 -4
- data/lib/rigor/language_server/publish_batcher.rb +3 -4
- data/lib/rigor/language_server/selection_range_provider.rb +2 -4
- data/lib/rigor/language_server/server.rb +12 -6
- data/lib/rigor/language_server/signature_help_provider.rb +4 -4
- data/lib/rigor/lens/plugins.rb +1 -1
- data/lib/rigor/mcp/server.rb +82 -3
- data/lib/rigor/mcp.rb +1 -1
- data/lib/rigor/plugin/access_denied_error.rb +1 -2
- data/lib/rigor/plugin/base.rb +26 -11
- data/lib/rigor/plugin/bundled_catalog.rb +1 -12
- data/lib/rigor/plugin/io_boundary.rb +1 -1
- data/lib/rigor/plugin/loader.rb +25 -8
- data/lib/rigor/plugin/macro/heredoc_template.rb +7 -8
- data/lib/rigor/plugin/macro/trait_registry.rb +6 -9
- data/lib/rigor/plugin/manifest.rb +38 -16
- data/lib/rigor/plugin/registry.rb +41 -3
- data/lib/rigor/plugin/services.rb +2 -3
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -0
- data/lib/rigor/plugin/trust_policy.rb +2 -2
- data/lib/rigor/plugin/type_node_resolver.rb +2 -4
- data/lib/rigor/plugin.rb +6 -8
- data/lib/rigor/plugin_gap_advisory.rb +5 -1
- data/lib/rigor/project_environment.rb +16 -2
- data/lib/rigor/protection/analysis_guard.rb +1 -1
- data/lib/rigor/protection/discovery_seed.rb +96 -2
- data/lib/rigor/protection/mutator.rb +1 -1
- data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
- data/lib/rigor/rbs_extended/hkt_directives.rb +6 -10
- data/lib/rigor/rbs_extended/reporter.rb +27 -3
- data/lib/rigor/rbs_extended.rb +2 -3
- data/lib/rigor/reflection/constant_ancestors.rb +5 -3
- data/lib/rigor/rooted_glob.rb +25 -2
- data/lib/rigor/run_scoped_slots.rb +38 -0
- data/lib/rigor/runtime/jit.rb +1 -1
- data/lib/rigor/scope/discovery_index.rb +19 -6
- data/lib/rigor/scope/resolution_chain.rb +3 -1
- data/lib/rigor/scope.rb +379 -36
- data/lib/rigor/sig_gen/classification.rb +4 -0
- data/lib/rigor/sig_gen/effect_annotation.rb +3 -3
- data/lib/rigor/sig_gen/generator.rb +668 -84
- data/lib/rigor/sig_gen/generic_header_scan.rb +189 -0
- data/lib/rigor/sig_gen/inline_declarations.rb +2 -2
- data/lib/rigor/sig_gen/layout_index.rb +3 -3
- data/lib/rigor/sig_gen/method_candidate.rb +23 -4
- data/lib/rigor/sig_gen/observation_collector.rb +7 -6
- data/lib/rigor/sig_gen/observed_call.rb +1 -1
- data/lib/rigor/sig_gen/path_mapper.rb +6 -0
- data/lib/rigor/sig_gen/rbs_validity.rb +1 -1
- data/lib/rigor/sig_gen/renderer.rb +21 -12
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +15 -2
- data/lib/rigor/sig_gen/type_elaborator.rb +21 -5
- data/lib/rigor/sig_gen/type_name_qualification.rb +69 -0
- data/lib/rigor/sig_gen/write_reporter.rb +63 -14
- data/lib/rigor/sig_gen/write_result.rb +23 -12
- data/lib/rigor/sig_gen/writer.rb +217 -37
- data/lib/rigor/type/acceptance_router.rb +2 -2
- data/lib/rigor/type/accepts_result.rb +1 -1
- data/lib/rigor/type/app.rb +4 -6
- data/lib/rigor/type/combinator.rb +13 -16
- data/lib/rigor/type/constant.rb +48 -7
- data/lib/rigor/type/hash_shape.rb +26 -40
- data/lib/rigor/type/struct_instance.rb +3 -2
- data/lib/rigor/type/union.rb +1 -1
- data/lib/rigor/type_node/identifier.rb +1 -2
- data/lib/rigor/type_node/resolver_chain.rb +1 -1
- data/lib/rigor/type_node/string_literal.rb +1 -2
- data/lib/rigor/type_node/symbol_literal.rb +1 -2
- data/lib/rigor/type_node/union.rb +3 -6
- data/lib/rigor/value_semantics.rb +1 -10
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +2 -2
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +2 -3
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +1 -1
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +89 -70
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +4 -2
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +25 -4
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +1 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -5
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +0 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +2 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +1 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +79 -19
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +6 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/association_roots.rb +3 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +2 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +21 -31
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +10 -16
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +2 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +0 -1
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +5 -4
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +3 -4
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +1 -1
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +7 -12
- data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +1 -1
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +1 -1
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/symbolize_keys.rb +102 -0
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +19 -6
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +26 -13
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_index.rb +3 -3
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +5 -3
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +1 -3
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +6 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +5 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +7 -6
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/params_shape.rb +2 -3
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +5 -8
- data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +0 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +1 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +10 -18
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/analyzer.rb +0 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/discoverer.rb +0 -2
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +4 -5
- data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +0 -2
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +6 -7
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +2 -4
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +2 -5
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +2 -2
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +6 -6
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +2 -1
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +3 -8
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +2 -3
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +5 -8
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +1 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +2 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +1 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +4 -11
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +1 -1
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +2 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +102 -11
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +2 -2
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +3 -4
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +6 -8
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +5 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +4 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +6 -7
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +1 -1
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +2 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +17 -21
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +2 -3
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_discoverer.rb +3 -2
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_index.rb +4 -4
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer.rb +1 -1
- data/sig/rigor/analysis/baseline.rbs +0 -2
- data/sig/rigor/analysis/fact_store.rbs +1 -0
- data/sig/rigor/analysis/reachability/scan_cache.rbs +1 -1
- data/sig/rigor/cli/diff_command.rbs +1 -1
- data/sig/rigor/cli/explain_command.rbs +1 -1
- data/sig/rigor/effects/file_collection.rbs +5 -6
- data/sig/rigor/effects/registry.rbs +8 -6
- data/sig/rigor/effects/summary.rbs +6 -5
- data/sig/rigor/environment.rbs +5 -3
- data/sig/rigor/inference/optimistic_origin.rbs +11 -0
- data/sig/rigor/inference.rbs +10 -1
- data/sig/rigor/plugin/additional_initializer.rbs +0 -5
- data/sig/rigor/plugin/base.rbs +1 -0
- data/sig/rigor/plugin/effect_ancestry.rbs +6 -4
- data/sig/rigor/plugin/effect_attribution.rbs +25 -10
- data/sig/rigor/plugin/effect_edge.rbs +12 -5
- data/sig/rigor/plugin/effect_entry_points.rbs +8 -3
- data/sig/rigor/plugin/io_boundary.rbs +6 -5
- data/sig/rigor/plugin/manifest.rbs +16 -18
- data/sig/rigor/plugin/protocol_contract.rbs +6 -9
- data/sig/rigor/plugin/registry.rbs +1 -1
- data/sig/rigor/scope.rbs +51 -50
- data/sig/rigor/type.rbs +0 -6
- data/skills/rigor-plugin-author/SKILL.md +4 -4
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +5 -5
- data/skills/rigor-plugin-review/SKILL.md +3 -3
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +12 -1
- metadata +55 -3
|
@@ -42,7 +42,7 @@ module Rigor
|
|
|
42
42
|
@project_context = project_context
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
# @return LSP
|
|
45
|
+
# @return LSP completion items, or nil
|
|
46
46
|
# when the cursor isn't at a position the provider can
|
|
47
47
|
# enumerate completions for. Returning nil maps to
|
|
48
48
|
# `result: null` per the LSP spec — clients treat it as
|
|
@@ -65,19 +65,20 @@ module Rigor
|
|
|
65
65
|
line: locate_at[0] + 1, character: locate_at[1] + 1)
|
|
66
66
|
return nil if node.nil?
|
|
67
67
|
|
|
68
|
+
query = ScopeQuery.new(path: path, bytes: bytes_to_parse, index: nil)
|
|
68
69
|
case node
|
|
69
70
|
when Prism::CallNode
|
|
70
71
|
# `hash[:|` patches to `hash[:KEY_SENTINEL]`, an index access call whose argument is the sentinel
|
|
71
72
|
# symbol; NodeLocator at the sentinel returns the inner CallNode for `[]`. Hash-key completion wins
|
|
72
73
|
# when the call is an index access on a HashShape carrier; otherwise fall through to method
|
|
73
74
|
# completion.
|
|
74
|
-
hash_key_completion_for(node, parse_result.value,
|
|
75
|
-
method_completion_for(node, parse_result.value,
|
|
75
|
+
hash_key_completion_for(node, parse_result.value, query) ||
|
|
76
|
+
method_completion_for(node, parse_result.value, query)
|
|
76
77
|
when Prism::SymbolNode
|
|
77
78
|
# The sentinel symbol's NodeLocator hit; walk up via the AST to find the enclosing `[]` call.
|
|
78
|
-
hash_key_completion_for_symbol(node, parse_result.value,
|
|
79
|
+
hash_key_completion_for_symbol(node, parse_result.value, query)
|
|
79
80
|
when Prism::ConstantPathNode
|
|
80
|
-
constant_path_completion_for(node
|
|
81
|
+
constant_path_completion_for(node)
|
|
81
82
|
end
|
|
82
83
|
end
|
|
83
84
|
|
|
@@ -141,11 +142,11 @@ module Rigor
|
|
|
141
142
|
nil
|
|
142
143
|
end
|
|
143
144
|
|
|
144
|
-
def method_completion_for(call_node, root,
|
|
145
|
+
def method_completion_for(call_node, root, query)
|
|
145
146
|
receiver_node = call_node.receiver
|
|
146
147
|
return nil if receiver_node.nil? # implicit-self — slice-3 territory of completion
|
|
147
148
|
|
|
148
|
-
index = build_scope_index(root,
|
|
149
|
+
index = build_scope_index(root, query)
|
|
149
150
|
receiver_scope = index[receiver_node]
|
|
150
151
|
receiver_type = receiver_scope.type_of(receiver_node)
|
|
151
152
|
method_completions(receiver_type, receiver_scope)
|
|
@@ -155,13 +156,13 @@ module Rigor
|
|
|
155
156
|
# `[]` call AND the receiver's inferred type is a `Type::HashShape`. Returns nil for any other receiver
|
|
156
157
|
# carrier so the dispatcher falls through to method completion (which still surfaces Hash's methods for
|
|
157
158
|
# genuine method calls on a hash receiver).
|
|
158
|
-
def hash_key_completion_for(call_node, root,
|
|
159
|
+
def hash_key_completion_for(call_node, root, query)
|
|
159
160
|
return nil unless call_node.name == :[]
|
|
160
161
|
|
|
161
162
|
receiver_node = call_node.receiver
|
|
162
163
|
return nil if receiver_node.nil?
|
|
163
164
|
|
|
164
|
-
index = build_scope_index(root,
|
|
165
|
+
index = build_scope_index(root, query)
|
|
165
166
|
receiver_type = index[receiver_node].type_of(receiver_node)
|
|
166
167
|
return nil unless receiver_type.is_a?(Type::HashShape)
|
|
167
168
|
|
|
@@ -171,11 +172,11 @@ module Rigor
|
|
|
171
172
|
# When NodeLocator returns the sentinel SymbolNode directly (rather than the enclosing CallNode), walk
|
|
172
173
|
# up the AST for the smallest `[]` call containing the symbol's location. Re-walks the root once; cheap
|
|
173
174
|
# for LSP-sized buffers.
|
|
174
|
-
def hash_key_completion_for_symbol(symbol_node, root,
|
|
175
|
+
def hash_key_completion_for_symbol(symbol_node, root, query)
|
|
175
176
|
call_node = enclosing_index_call(root, symbol_node)
|
|
176
177
|
return nil if call_node.nil?
|
|
177
178
|
|
|
178
|
-
hash_key_completion_for(call_node, root,
|
|
179
|
+
hash_key_completion_for(call_node, root, query)
|
|
179
180
|
end
|
|
180
181
|
|
|
181
182
|
def enclosing_index_call(root, symbol_node)
|
|
@@ -212,11 +213,11 @@ module Rigor
|
|
|
212
213
|
# resolves to a class / module FQN; we enumerate every known class whose name is an immediate child of
|
|
213
214
|
# that parent. Top-level constants (`::Foo`) and parent-less paths are not yet supported (queued for
|
|
214
215
|
# slice 6 follow-up).
|
|
215
|
-
def constant_path_completion_for(const_path_node
|
|
216
|
+
def constant_path_completion_for(const_path_node)
|
|
216
217
|
parent_fqn = parent_fqn_of(const_path_node)
|
|
217
218
|
return nil if parent_fqn.nil?
|
|
218
219
|
|
|
219
|
-
scope =
|
|
220
|
+
scope = Scope.empty(environment: @project_context.environment) # reads only the environment
|
|
220
221
|
children = enumerate_constant_children(parent_fqn, scope)
|
|
221
222
|
return nil if children.empty?
|
|
222
223
|
|
|
@@ -277,8 +278,14 @@ module Rigor
|
|
|
277
278
|
}
|
|
278
279
|
end
|
|
279
280
|
|
|
280
|
-
|
|
281
|
-
|
|
281
|
+
# The (path, bytes) a scope query is seeded from: the bytes the parse saw, sentinel splice included. `index`
|
|
282
|
+
# memoises the request's scope index, so a `hash[...]` request that falls through from hash-key to method
|
|
283
|
+
# completion builds it once.
|
|
284
|
+
ScopeQuery = Struct.new(:path, :bytes, :index)
|
|
285
|
+
private_constant :ScopeQuery
|
|
286
|
+
|
|
287
|
+
def seeded_scope(query)
|
|
288
|
+
@project_context.seeded_scope_for(path: query.path, bytes: query.bytes)
|
|
282
289
|
end
|
|
283
290
|
|
|
284
291
|
def locate_node(source:, root:, line:, character:)
|
|
@@ -287,12 +294,11 @@ module Rigor
|
|
|
287
294
|
nil
|
|
288
295
|
end
|
|
289
296
|
|
|
290
|
-
def build_scope_index(root,
|
|
291
|
-
|
|
292
|
-
Inference::ScopeIndexer.index(root, default_scope: scope)
|
|
297
|
+
def build_scope_index(root, query)
|
|
298
|
+
query.index ||= Inference::ScopeIndexer.index(root, default_scope: seeded_scope(query))
|
|
293
299
|
end
|
|
294
300
|
|
|
295
|
-
# Returns
|
|
301
|
+
# Returns the LSP completion items for every public method callable on the receiver.
|
|
296
302
|
# Slice B3 extends the slice-B1 floor with:
|
|
297
303
|
# - `Type::Refined` / `Type::Difference` — enumerate the underlying nominal (refinement narrows the
|
|
298
304
|
# value set, not the method set).
|
|
@@ -312,7 +318,7 @@ module Rigor
|
|
|
312
318
|
end
|
|
313
319
|
end
|
|
314
320
|
|
|
315
|
-
# Returns
|
|
321
|
+
# Returns the receiver's method table with its dispatch kind (`:instance` or `:singleton`). Composite
|
|
316
322
|
# carriers (Union / Intersection / Refined / shape carriers) reduce to instance-method enumeration; the
|
|
317
323
|
# receiver-class label that lands in each CompletionItem's `detail` still comes from each method's own
|
|
318
324
|
# `defs.first.implemented_in`, so the rendered prefix stays accurate per-method.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rigor
|
|
4
|
+
module LanguageServer
|
|
5
|
+
# Issue #2231 — shows each {ConfigAudit} warning the editor has not seen yet as a `window/showMessage`
|
|
6
|
+
# (`MessageType.Warning`), worded as `rigor check` prints it on STDERR. {ProjectContext#unannounced_config_warnings}
|
|
7
|
+
# decides what is new, so a call after a reload that changed nothing writes nothing. Called on `initialized` and
|
|
8
|
+
# after each save round's configuration reload (`DiagnosticPublisher`).
|
|
9
|
+
class ConfigWarningAnnouncer
|
|
10
|
+
# LSP `MessageType.Warning`, the `type` of a `window/showMessage` notification.
|
|
11
|
+
MESSAGE_TYPE_WARNING = 2
|
|
12
|
+
|
|
13
|
+
def initialize(writer:, project_context:)
|
|
14
|
+
@writer = writer
|
|
15
|
+
@project_context = project_context
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def announce
|
|
19
|
+
return unless @project_context.respond_to?(:unannounced_config_warnings)
|
|
20
|
+
|
|
21
|
+
@project_context.unannounced_config_warnings.each do |warning|
|
|
22
|
+
@writer.write(method: "window/showMessage",
|
|
23
|
+
params: { type: MESSAGE_TYPE_WARNING, message: "rigor: #{warning.message}" })
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -4,6 +4,7 @@ require "tempfile"
|
|
|
4
4
|
|
|
5
5
|
require_relative "uri"
|
|
6
6
|
require_relative "publish_batcher"
|
|
7
|
+
require_relative "config_warning_announcer"
|
|
7
8
|
require_relative "../analysis/runner"
|
|
8
9
|
require_relative "../analysis/buffer_binding"
|
|
9
10
|
|
|
@@ -19,7 +20,7 @@ module Rigor
|
|
|
19
20
|
# buffers' debounce timers elapse around the same moment, the `PublishBatcher` coalesces them into one
|
|
20
21
|
# `#publish_many` round dispatched across the fork-based worker pool (issue #142) instead of N
|
|
21
22
|
# independent, GVL-serialized `Runner` calls.
|
|
22
|
-
class DiagnosticPublisher
|
|
23
|
+
class DiagnosticPublisher # rubocop:disable Metrics/ClassLength
|
|
23
24
|
# Maps Rigor severity symbols to LSP DiagnosticSeverity
|
|
24
25
|
# integers per spec § "Diagnostic":
|
|
25
26
|
# 1 = Error, 2 = Warning, 3 = Information, 4 = Hint.
|
|
@@ -51,6 +52,7 @@ module Rigor
|
|
|
51
52
|
@project_context = project_context
|
|
52
53
|
@debouncer = debouncer
|
|
53
54
|
@debounce_seconds = debounce_seconds
|
|
55
|
+
@config_warning_announcer = ConfigWarningAnnouncer.new(writer: writer, project_context: project_context)
|
|
54
56
|
@round_lock = Mutex.new
|
|
55
57
|
@round_running = false
|
|
56
58
|
@round_pending = false
|
|
@@ -100,7 +102,8 @@ module Rigor
|
|
|
100
102
|
publish_batch(eligible)
|
|
101
103
|
end
|
|
102
104
|
|
|
103
|
-
# Runs one whole-project save round and publishes to the publish set (#246)
|
|
105
|
+
# Runs one whole-project save round and publishes to the publish set (#246), then re-publishes each dirty buffer
|
|
106
|
+
# from its own bytes (ADR-124). Called from `didSave`.
|
|
104
107
|
#
|
|
105
108
|
# Analysis scope is the whole project; the PUBLISH SET is the open buffers that are not dirty, plus the
|
|
106
109
|
# buffer that was just saved. A dirty buffer is excluded because only its own `didChange` analysis has
|
|
@@ -117,12 +120,21 @@ module Rigor
|
|
|
117
120
|
end
|
|
118
121
|
end
|
|
119
122
|
|
|
123
|
+
# Re-publishes every open buffer from its own bytes, each through {#publish_for}. Called after the project
|
|
124
|
+
# context is invalidated (a watched file or the configuration changed): every marker on screen was computed
|
|
125
|
+
# against the world that is gone, and since ADR-124 a buffer's markers read other files' declarations, so
|
|
126
|
+
# they can move without the buffer itself changing.
|
|
127
|
+
def republish_open = @buffer_table.uris.each { |uri| publish_for(uri) }
|
|
128
|
+
|
|
120
129
|
# Publishes an EMPTY diagnostic array for `uri`. The LSP-spec idiom for "clear inline markers" — called
|
|
121
130
|
# from `didClose` so clients drop stale highlights when the user closes a buffer.
|
|
122
131
|
def publish_empty(uri)
|
|
123
132
|
notify(uri, [])
|
|
124
133
|
end
|
|
125
134
|
|
|
135
|
+
# Issue #2231 — shows the configuration warnings the editor has not seen yet ({ConfigWarningAnnouncer}).
|
|
136
|
+
def announce_config_warnings = @config_warning_announcer.announce
|
|
137
|
+
|
|
126
138
|
# Cancels every in-flight debounced task. Called from `Server#handle_shutdown` so pending publishes
|
|
127
139
|
# don't fire against a closed STDOUT.
|
|
128
140
|
def cancel_pending
|
|
@@ -160,8 +172,7 @@ module Rigor
|
|
|
160
172
|
|
|
161
173
|
# True when a save arrived mid-round and the loop should run once more. Releases ownership otherwise.
|
|
162
174
|
# `next`, not `break`: inside `Mutex#synchronize`'s block, `break` returns from the SYNCHRONIZE call, so
|
|
163
|
-
# a `break`
|
|
164
|
-
# before this was split out.
|
|
175
|
+
# a `break` here would leave the caller's `loop` spinning forever.
|
|
165
176
|
def consume_pending
|
|
166
177
|
@round_lock.synchronize do
|
|
167
178
|
next(@round_running = false) unless @round_pending
|
|
@@ -178,6 +189,7 @@ module Rigor
|
|
|
178
189
|
def execute_project_round(saved_uri)
|
|
179
190
|
generation = @project_context.generation
|
|
180
191
|
diagnostics = @project_context.project_diagnostics
|
|
192
|
+
announce_config_warnings # the round re-read the configuration; the reload stands even if the result does not
|
|
181
193
|
return if generation != @project_context.generation
|
|
182
194
|
|
|
183
195
|
by_path = diagnostics.group_by(&:path)
|
|
@@ -187,16 +199,20 @@ module Rigor
|
|
|
187
199
|
|
|
188
200
|
notify(uri, (by_path[path] || []).filter_map { |diagnostic| to_lsp_diagnostic(diagnostic, path) })
|
|
189
201
|
end
|
|
202
|
+
republish_dirty
|
|
190
203
|
end
|
|
191
204
|
|
|
205
|
+
# The dirty buffers the round may not speak for, re-published from their own bytes (ADR-124). The save that
|
|
206
|
+
# started the round may have moved a declaration a dirty buffer's markers read across files, and nothing
|
|
207
|
+
# else re-analyses that buffer until its next change or save. Each goes through {#publish_for}, so the
|
|
208
|
+
# debouncer and `PublishBatcher` order it against the buffer's own `didChange` publishes: a re-publish run
|
|
209
|
+
# here, beside them, could land its older bytes' markers after a newer edit's.
|
|
210
|
+
def republish_dirty = @buffer_table.uris.each { |uri| publish_for(uri) if @buffer_table.dirty?(uri) }
|
|
211
|
+
|
|
192
212
|
# The URIs this round may speak for: every open buffer whose bytes are the ones on disk. The just-saved
|
|
193
213
|
# URI qualifies by definition (the client wrote it), and is named explicitly so a client that sends
|
|
194
214
|
# `didSave` without a preceding applied `didChange` still refreshes it.
|
|
195
|
-
def publish_set(saved_uri)
|
|
196
|
-
([saved_uri] + @buffer_table.uris).uniq.select do |uri|
|
|
197
|
-
@buffer_table.open?(uri) && !@buffer_table.dirty?(uri) && !@buffer_table.desynchronized?(uri)
|
|
198
|
-
end
|
|
199
|
-
end
|
|
215
|
+
def publish_set(saved_uri) = ([saved_uri] + @buffer_table.uris).uniq.select { |uri| @buffer_table.on_disk?(uri) }
|
|
200
216
|
|
|
201
217
|
def run_and_notify(uri, path)
|
|
202
218
|
entry = @buffer_table[uri]
|
|
@@ -239,11 +255,13 @@ module Rigor
|
|
|
239
255
|
def publish_batch(jobs)
|
|
240
256
|
with_tempfiles(jobs) do |bound_jobs|
|
|
241
257
|
bindings = bound_jobs.map { |job| job.fetch(:binding) }
|
|
258
|
+
@project_context.prepare_discovery_seed
|
|
242
259
|
dispatcher = Analysis::Runner::BufferPoolDispatcher.new(
|
|
243
260
|
configuration: @project_context.configuration,
|
|
244
261
|
cache_store: @project_context.cache_store,
|
|
245
262
|
environment: @project_context.environment,
|
|
246
263
|
prebuilt: @project_context.project_scan,
|
|
264
|
+
discovery_seed_for: @project_context.method(:discovery_seed_for),
|
|
247
265
|
workers: worker_count
|
|
248
266
|
)
|
|
249
267
|
diagnostics_per_binding = dispatcher.analyze(bindings)
|
|
@@ -282,6 +300,7 @@ module Rigor
|
|
|
282
300
|
collect_stats: false,
|
|
283
301
|
buffer: binding,
|
|
284
302
|
prebuilt: @project_context.project_scan,
|
|
303
|
+
discovery_seed: @project_context.discovery_seed_for(binding),
|
|
285
304
|
environment: @project_context.environment
|
|
286
305
|
)
|
|
287
306
|
result = runner.run([path])
|
|
@@ -30,7 +30,7 @@ module Rigor
|
|
|
30
30
|
@project_context = project_context
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
# @return LSP
|
|
33
|
+
# @return LSP document symbols for the
|
|
34
34
|
# buffer at `uri`. Returns nil when the URI isn't open or
|
|
35
35
|
# doesn't parse cleanly enough to surface symbols — LSP
|
|
36
36
|
# clients fall back to no-outline in that case.
|
|
@@ -23,8 +23,7 @@ module Rigor
|
|
|
23
23
|
@project_context = project_context
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
# @return LSP
|
|
27
|
-
# buffer, or nil when the URI isn't open / parseable.
|
|
26
|
+
# @return LSP folding ranges for the buffer, or nil when the URI isn't open / parseable.
|
|
28
27
|
def provide(uri)
|
|
29
28
|
path, entry = buffer_for(uri)
|
|
30
29
|
return nil if entry.nil?
|
|
@@ -44,7 +44,7 @@ module Rigor
|
|
|
44
44
|
node = locate_node(source: entry.bytes, root: parse_result.value, line: line + 1, character: character + 1)
|
|
45
45
|
return nil if node.nil?
|
|
46
46
|
|
|
47
|
-
scope =
|
|
47
|
+
scope = @project_context.seeded_scope_for(path: path, bytes: entry.bytes)
|
|
48
48
|
index = Inference::ScopeIndexer.index(parse_result.value, default_scope: scope)
|
|
49
49
|
node_scope = index[node]
|
|
50
50
|
type = node_scope.type_of(node)
|
|
@@ -59,12 +59,6 @@ module Rigor
|
|
|
59
59
|
rescue Source::NodeLocator::OutOfRangeError
|
|
60
60
|
nil
|
|
61
61
|
end
|
|
62
|
-
|
|
63
|
-
def base_scope(_path)
|
|
64
|
-
# Pulls the Environment from the cached ProjectContext so each hover avoids repeating the RBS-load
|
|
65
|
-
# build.
|
|
66
|
-
Scope.empty(environment: @project_context.environment)
|
|
67
|
-
end
|
|
68
62
|
end
|
|
69
63
|
end
|
|
70
64
|
end
|
|
@@ -60,9 +60,8 @@ module Rigor
|
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
# Renders a `CallNode` hover when the receiver's type can be mapped to a known RBS class and the method
|
|
63
|
-
# is declared there. Returns nil for shapes
|
|
64
|
-
# Refined / Shape receivers
|
|
65
|
-
# default body.
|
|
63
|
+
# is declared there. Returns nil for shapes this renderer does not handle (implicit `self`, Union /
|
|
64
|
+
# Refined / Shape receivers); the caller falls back to the default body.
|
|
66
65
|
def render_call(call_node, return_type, node_scope_lookup)
|
|
67
66
|
receiver_node = call_node.receiver
|
|
68
67
|
return nil if receiver_node.nil?
|
|
@@ -133,17 +132,16 @@ module Rigor
|
|
|
133
132
|
body << "#{return_type.describe}\n"
|
|
134
133
|
body << "```"
|
|
135
134
|
if (doc = rbs_documentation(definition))
|
|
136
|
-
#
|
|
137
|
-
# necessary — plain markdown below the code reads better in clients.
|
|
135
|
+
# The fence is already closed, so the RBS comment renders as plain markdown below the code.
|
|
138
136
|
body << "\n\n---\n\n#{doc}"
|
|
139
137
|
end
|
|
140
138
|
body
|
|
141
139
|
end
|
|
142
140
|
|
|
143
141
|
# Returns the concatenated text of every RBS comment attached to the method definition, or nil when no
|
|
144
|
-
# comments exist. `RBS::Definition::Method#comments` is
|
|
145
|
-
# `.string`
|
|
146
|
-
#
|
|
142
|
+
# comments exist. `RBS::Definition::Method#comments` is a list of `AST::Comment`s, each with its raw text
|
|
143
|
+
# in `.string` (newline-terminated `# foo` lines). Multiple comments are joined with a blank line so each
|
|
144
|
+
# upstream `# Foo bar` paragraph is preserved.
|
|
147
145
|
def rbs_documentation(definition)
|
|
148
146
|
comments = definition.respond_to?(:comments) ? definition.comments : nil
|
|
149
147
|
return nil if comments.nil? || comments.empty?
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "tempfile"
|
|
4
|
+
|
|
3
5
|
require_relative "../environment"
|
|
4
6
|
require_relative "../project_environment"
|
|
5
7
|
require_relative "../cache/store"
|
|
@@ -7,6 +9,9 @@ require_relative "../analysis/runner"
|
|
|
7
9
|
require_relative "../analysis/incremental_session"
|
|
8
10
|
require_relative "../cache/incremental_snapshot"
|
|
9
11
|
require_relative "../effects/identity"
|
|
12
|
+
require_relative "../analysis/path_expansion"
|
|
13
|
+
require_relative "../protection/discovery_seed"
|
|
14
|
+
require_relative "../config_audit"
|
|
10
15
|
|
|
11
16
|
module Rigor
|
|
12
17
|
module LanguageServer
|
|
@@ -58,6 +63,7 @@ module Rigor
|
|
|
58
63
|
@primed_key = nil
|
|
59
64
|
@buffer_sources = {}
|
|
60
65
|
@disk_feature_files = nil
|
|
66
|
+
@disk_sig_names = nil
|
|
61
67
|
@environment_features = nil
|
|
62
68
|
@generation = 0
|
|
63
69
|
@environment = nil
|
|
@@ -65,6 +71,24 @@ module Rigor
|
|
|
65
71
|
@project_scan = nil
|
|
66
72
|
@incremental_session = nil
|
|
67
73
|
@session_primed = false
|
|
74
|
+
@announced_config_warnings = Set.new
|
|
75
|
+
@announce_lock = Mutex.new
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Issue #2231 — the {ConfigAudit} warnings for the configuration as last loaded that the editor has not been
|
|
79
|
+
# shown yet, or an empty array. `rigor check` prints these on every run; the server is one long run, so it
|
|
80
|
+
# announces each warning once: at `initialized` for the configuration it started with, and after a later reload
|
|
81
|
+
# (every save round re-reads `.rigor.yml`) only the warnings that were not in the previous reload's set. The
|
|
82
|
+
# comparison is by message, not by order, so reordering entries announces nothing, and fixing one of two
|
|
83
|
+
# warnings does not show the other again. A warning that was fixed and then comes back is new and is shown.
|
|
84
|
+
# Called from the dispatch thread and the save round's thread alike, hence the lock.
|
|
85
|
+
def unannounced_config_warnings
|
|
86
|
+
@announce_lock.synchronize do
|
|
87
|
+
warnings = ConfigAudit.warnings(@configuration)
|
|
88
|
+
fresh = warnings.reject { |warning| @announced_config_warnings.include?(warning.message) }
|
|
89
|
+
@announced_config_warnings = warnings.to_set(&:message)
|
|
90
|
+
fresh
|
|
91
|
+
end
|
|
68
92
|
end
|
|
69
93
|
|
|
70
94
|
# Returns the cached `Rigor::Environment` for this session, building it on first access. The build
|
|
@@ -112,6 +136,47 @@ module Rigor
|
|
|
112
136
|
@project_scan ||= build_project_scan
|
|
113
137
|
end
|
|
114
138
|
|
|
139
|
+
# Issue #2147 — the cross-file discovery tables a per-buffer publish seeds its `Runner` with
|
|
140
|
+
# (`discovery_seed:`, #260). A `prebuilt:` runner runs no discovery pass of its own, so without them every
|
|
141
|
+
# class another file declares reads as an external ancestor and a publish answers differently from
|
|
142
|
+
# `rigor check` over the same tree. The per-file bundles are walked once per generation; each publish
|
|
143
|
+
# re-folds them with `buffer`'s file re-walked from the buffer's bytes
|
|
144
|
+
# ({Protection::DiscoverySeed.tables_for_buffer}), so the buffer's own declarations win over its on-disk
|
|
145
|
+
# ones, and a file whose bytes on disk moved since the bundles were built is re-walked too (its digest no
|
|
146
|
+
# longer matches).
|
|
147
|
+
#
|
|
148
|
+
# The buffer's file is matched by its real path and handed to the fold under the buffer's own spelling: the
|
|
149
|
+
# binding substitutes bytes only for a path spelled exactly as its logical path (the URI's absolute path),
|
|
150
|
+
# while the configured paths may be relative (`lib`, the default) or reach the file through a symlink.
|
|
151
|
+
def discovery_seed_for(buffer)
|
|
152
|
+
Protection::DiscoverySeed.tables_for_buffer(paths: discovery_paths_for(buffer), bundles: discovery_bundles,
|
|
153
|
+
buffer: buffer, constant_sources: true)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Issue #2282 — the base scope an editor query (hover, completion, signature help) probes with: the same
|
|
157
|
+
# cross-file discovery seed the diagnostic publisher hands its `Runner` ({#discovery_seed_for}), so a constant
|
|
158
|
+
# or method another file defines answers what `rigor check` would. The seed fold reads the buffer through a
|
|
159
|
+
# {Analysis::BufferBinding}, so `bytes` is staged in a tempfile for the call. An empty seed (no configured
|
|
160
|
+
# files, or nothing discovered) leaves the bare single-file scope every query used before.
|
|
161
|
+
def seeded_scope_for(path:, bytes:)
|
|
162
|
+
seed = Tempfile.create(["rigor-lsp-query-", ".rb"]) do |tmp|
|
|
163
|
+
# Staged as the publisher stages them; the seed's job is to withhold the stale on-disk declarations of
|
|
164
|
+
# this file, so an empty-bytes stage is not observable by design.
|
|
165
|
+
tmp.write(bytes)
|
|
166
|
+
tmp.flush
|
|
167
|
+
discovery_seed_for(Analysis::BufferBinding.new(logical_path: path, physical_path: tmp.path))
|
|
168
|
+
end
|
|
169
|
+
Protection::DiscoverySeed.seeded_scope(environment: environment, seed: seed)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Builds what {#discovery_seed_for} reads once per generation, so a fork batch's children inherit it instead
|
|
173
|
+
# of each walking the project.
|
|
174
|
+
def prepare_discovery_seed
|
|
175
|
+
discovery_bundles
|
|
176
|
+
discovery_real_paths
|
|
177
|
+
nil
|
|
178
|
+
end
|
|
179
|
+
|
|
115
180
|
# Whole-project diagnostics for one save round (#246). The first call primes an in-process
|
|
116
181
|
# {Analysis::IncrementalSession} — seeded from the on-disk snapshot a terminal
|
|
117
182
|
# `rigor check --incremental` may have left, and otherwise from a full baseline; every later call is a
|
|
@@ -168,9 +233,14 @@ module Rigor
|
|
|
168
233
|
# file.
|
|
169
234
|
def required_features
|
|
170
235
|
disk = (@disk_feature_files ||= Environment::RequiredFeatures.feature_files(@configuration))
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
236
|
+
scanned = disk.reject { |path, _| @buffer_sources.key?(path) }.values
|
|
237
|
+
scanned += @buffer_sources.values.map { |source| Environment::RequiredFeatures.scan_source(source) }
|
|
238
|
+
features = scanned.flat_map(&:first).uniq
|
|
239
|
+
names = scanned.flat_map(&:last).to_set
|
|
240
|
+
names.merge(@disk_sig_names ||= Environment::RequiredFeatures.sig_names(
|
|
241
|
+
Environment::RequiredFeatures.configured_sig_paths(@configuration)
|
|
242
|
+
))
|
|
243
|
+
Environment::RequiredFeatures.relevant(features, names).sort.freeze
|
|
174
244
|
end
|
|
175
245
|
|
|
176
246
|
# Drops every cached collaborator and bumps the generation. The next reader rebuilds from scratch.
|
|
@@ -188,7 +258,11 @@ module Rigor
|
|
|
188
258
|
@environment = nil
|
|
189
259
|
@environment_features = nil
|
|
190
260
|
@disk_feature_files = nil
|
|
261
|
+
@disk_sig_names = nil
|
|
191
262
|
@project_scan = nil
|
|
263
|
+
@discovery_paths = nil
|
|
264
|
+
@discovery_real_paths = nil
|
|
265
|
+
@discovery_bundles = nil
|
|
192
266
|
# The session's per-file cache was computed against the old environment / project scan, so it cannot
|
|
193
267
|
# outlive them. The next save round primes a fresh one.
|
|
194
268
|
@incremental_session = nil
|
|
@@ -214,7 +288,8 @@ module Rigor
|
|
|
214
288
|
def reload_configuration
|
|
215
289
|
return unless @configuration_loader
|
|
216
290
|
|
|
217
|
-
|
|
291
|
+
loaded = @configuration_loader.call
|
|
292
|
+
@announce_lock.synchronize { @configuration = loaded }
|
|
218
293
|
rescue StandardError
|
|
219
294
|
nil
|
|
220
295
|
end
|
|
@@ -230,6 +305,25 @@ module Rigor
|
|
|
230
305
|
)
|
|
231
306
|
end
|
|
232
307
|
|
|
308
|
+
# The configured project files, expanded as `rigor check` expands its configured paths.
|
|
309
|
+
def discovery_paths
|
|
310
|
+
@discovery_paths ||= Analysis::PathExpansion.configured_files(@configuration).freeze
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
# Every entry that reaches the buffer's file is respelled, so a file configured under two roots (`lib` and a
|
|
314
|
+
# symlink to it) is not folded from disk through the second.
|
|
315
|
+
def discovery_paths_for(buffer)
|
|
316
|
+
Protection::DiscoverySeed.respell_for_buffer(discovery_paths, buffer, real_paths: discovery_real_paths)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def discovery_real_paths
|
|
320
|
+
@discovery_real_paths ||= discovery_paths.map { |path| Rigor::Analysis::BufferBinding.real_path(path) }.freeze
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def discovery_bundles
|
|
324
|
+
@discovery_bundles ||= Protection::DiscoverySeed.bundles(paths: discovery_paths)
|
|
325
|
+
end
|
|
326
|
+
|
|
233
327
|
def build_project_scan
|
|
234
328
|
runner = Analysis::Runner.new(
|
|
235
329
|
configuration: @configuration,
|
|
@@ -15,10 +15,9 @@ module Rigor
|
|
|
15
15
|
# dropped. The same claim/consume shape `DiagnosticPublisher#run_project_round` already uses for the
|
|
16
16
|
# whole-project save round (#246), generalised to an arbitrary key type and an arbitrary batch action.
|
|
17
17
|
class PublishBatcher
|
|
18
|
-
# @param on_batch —
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# @param on_error — `(exception) -> void`, called when `on_batch` raises. A round must
|
|
18
|
+
# @param on_batch — called with the deduplicated keys pending at the start of one round. May be called
|
|
19
|
+
# more than once in a row when keys keep arriving while a round runs.
|
|
20
|
+
# @param on_error — called with the exception when `on_batch` raises. A round must
|
|
22
21
|
# never wedge the coalescing lock for every future `#enqueue` call — ownership is always released
|
|
23
22
|
# before this fires. Whatever was mid-flight when the round raised is lost; anything enqueued by a
|
|
24
23
|
# concurrent `#enqueue` call after this round's drain but before the rescue stays pending and rides
|
|
@@ -20,10 +20,8 @@ module Rigor
|
|
|
20
20
|
@project_context = project_context
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
# @param positions — LSP `
|
|
24
|
-
#
|
|
25
|
-
# @return one `SelectionRange` per
|
|
26
|
-
# position, or nil when the URI / buffer isn't resolvable.
|
|
23
|
+
# @param positions — LSP positions, each `{ line:, character: }` 0-based.
|
|
24
|
+
# @return one `SelectionRange` per position, or nil when the URI / buffer isn't resolvable.
|
|
27
25
|
def provide(uri, positions)
|
|
28
26
|
path, entry = buffer_for(uri)
|
|
29
27
|
return nil if entry.nil?
|
|
@@ -194,7 +194,12 @@ module Rigor
|
|
|
194
194
|
|
|
195
195
|
# `initialized` is a notification — no response body. Nothing is registered here yet: the server handles
|
|
196
196
|
# `workspace/didChangeWatchedFiles` when a client sends it, but does not register for it dynamically.
|
|
197
|
+
#
|
|
198
|
+
# Issue #2231 — the configuration the server started with is audited here, the first point at which the
|
|
199
|
+
# client is listening, so a `.rigor.yml` key that does nothing is named in the editor as `rigor check`
|
|
200
|
+
# names it on STDERR.
|
|
197
201
|
def handle_initialized
|
|
202
|
+
@publisher&.announce_config_warnings
|
|
198
203
|
nil
|
|
199
204
|
end
|
|
200
205
|
|
|
@@ -267,8 +272,7 @@ module Rigor
|
|
|
267
272
|
|
|
268
273
|
# textDocument/hover REQUEST. Slice 5 returns either a `Hover` payload (markdown contents wrapping type
|
|
269
274
|
# + erased-RBS info) or nil when no expression is at the queried position. Nil maps to `result: null`
|
|
270
|
-
# per LSP spec; clients suppress the popup. Returns `MethodNotFound` when no hover_provider is wired
|
|
271
|
-
# (slice 1-4 behaviour).
|
|
275
|
+
# per LSP spec; clients suppress the popup. Returns `MethodNotFound` when no hover_provider is wired.
|
|
272
276
|
def handle_hover(params)
|
|
273
277
|
return method_not_found("textDocument/hover") unless @hover_provider
|
|
274
278
|
|
|
@@ -282,11 +286,12 @@ module Rigor
|
|
|
282
286
|
end
|
|
283
287
|
|
|
284
288
|
# workspace/didChangeWatchedFiles NOTIFICATION. Invalidates the ProjectContext so cached pre-pass /
|
|
285
|
-
# Environment is rebuilt on the next request
|
|
286
|
-
#
|
|
287
|
-
# follow-up; this is the LSP-correct floor.
|
|
289
|
+
# Environment is rebuilt on the next request, and re-publishes the open buffers against the new world
|
|
290
|
+
# (ADR-124). Slice 7's floor: any watched file change triggers a full context rebuild. Per-file surgical
|
|
291
|
+
# invalidation (per design doc § "Project context refresh") is a follow-up; this is the LSP-correct floor.
|
|
288
292
|
def handle_did_change_watched_files(_params)
|
|
289
293
|
@project_context&.invalidate!
|
|
294
|
+
@publisher&.republish_open
|
|
290
295
|
nil
|
|
291
296
|
end
|
|
292
297
|
|
|
@@ -295,6 +300,7 @@ module Rigor
|
|
|
295
300
|
# (.rigor.yml / Gemfile.lock / etc).
|
|
296
301
|
def handle_did_change_configuration(_params)
|
|
297
302
|
@project_context&.invalidate!
|
|
303
|
+
@publisher&.republish_open
|
|
298
304
|
nil
|
|
299
305
|
end
|
|
300
306
|
|
|
@@ -349,7 +355,7 @@ module Rigor
|
|
|
349
355
|
)
|
|
350
356
|
end
|
|
351
357
|
|
|
352
|
-
# textDocument/documentSymbol REQUEST. Returns the
|
|
358
|
+
# textDocument/documentSymbol REQUEST. Returns the document-symbol outline for the buffer at the
|
|
353
359
|
# requested URI. Returns `MethodNotFound` when no provider is wired.
|
|
354
360
|
def handle_document_symbol(params)
|
|
355
361
|
return method_not_found("textDocument/documentSymbol") unless @document_symbol_provider
|
|
@@ -25,7 +25,7 @@ module Rigor
|
|
|
25
25
|
# parses the buffer, locates the enclosing `CallNode`, infers the receiver's type, and returns the
|
|
26
26
|
# method's first overload as a `SignatureInformation`.
|
|
27
27
|
#
|
|
28
|
-
# Slice C1
|
|
28
|
+
# Slice C1 ships:
|
|
29
29
|
# - Sentinel patching for `obj.foo(|` so Prism's parse succeeds (mirrors `CompletionProvider`'s slice B4
|
|
30
30
|
# pattern).
|
|
31
31
|
# - First-overload signature only.
|
|
@@ -111,7 +111,7 @@ module Rigor
|
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
def build_signature(call_node, root, path, bytes, line, character)
|
|
114
|
-
scope_index = build_scope_index(root, path)
|
|
114
|
+
scope_index = build_scope_index(root, path, bytes)
|
|
115
115
|
receiver_node = call_node.receiver
|
|
116
116
|
return nil if receiver_node.nil?
|
|
117
117
|
|
|
@@ -197,8 +197,8 @@ module Rigor
|
|
|
197
197
|
end
|
|
198
198
|
end
|
|
199
199
|
|
|
200
|
-
def build_scope_index(root,
|
|
201
|
-
scope =
|
|
200
|
+
def build_scope_index(root, path, bytes)
|
|
201
|
+
scope = @project_context.seeded_scope_for(path: path, bytes: bytes)
|
|
202
202
|
Inference::ScopeIndexer.index(root, default_scope: scope)
|
|
203
203
|
end
|
|
204
204
|
|
data/lib/rigor/lens/plugins.rb
CHANGED
|
@@ -29,7 +29,7 @@ module Rigor
|
|
|
29
29
|
return Rigor::VERSION if absolute.start_with?("#{BUNDLED_PLUGINS}/")
|
|
30
30
|
|
|
31
31
|
spec = Gem.loaded_specs.each_value.find do |gem|
|
|
32
|
-
absolute.start_with?("#{gem.full_gem_path}/")
|
|
32
|
+
absolute.start_with?("#{gem.full_gem_path}/")
|
|
33
33
|
end
|
|
34
34
|
spec&.version&.to_s
|
|
35
35
|
rescue StandardError
|