rigortype 0.4.2 → 0.4.3
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/docs/handbook/11-sig-gen.md +12 -5
- data/docs/manual/02-cli-reference.md +19 -1
- data/docs/manual/03-configuration.md +6 -4
- data/docs/manual/05-inspecting-types.md +50 -0
- data/docs/manual/12-caching.md +18 -1
- data/docs/manual/14-rails-quickstart.md +2 -2
- data/docs/manual/18-removing-dead-code.md +16 -9
- data/lib/rigor/analysis/check_rules/rule_ids.rb +7 -0
- data/lib/rigor/analysis/check_rules.rb +23 -22
- data/lib/rigor/analysis/effects_cache_probe.rb +1 -1
- data/lib/rigor/analysis/incremental_run_slot.rb +3 -3
- data/lib/rigor/analysis/incremental_session.rb +89 -22
- data/lib/rigor/analysis/path_expansion.rb +62 -6
- data/lib/rigor/analysis/plugin_fact_fingerprint.rb +124 -37
- data/lib/rigor/analysis/reachability/graph.rb +119 -15
- data/lib/rigor/analysis/reachability/scan.rb +332 -173
- data/lib/rigor/analysis/reachability/scan_cache.rb +4 -2
- data/lib/rigor/analysis/run_cache_probe.rb +1 -1
- data/lib/rigor/analysis/run_stats.rb +28 -6
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +26 -1
- data/lib/rigor/analysis/runner/pool_coordinator.rb +28 -9
- data/lib/rigor/analysis/runner/project_pre_passes.rb +21 -1
- data/lib/rigor/analysis/runner.rb +29 -11
- data/lib/rigor/analysis/worker_session.rb +1 -1
- data/lib/rigor/cache/engine_source.rb +21 -7
- data/lib/rigor/cache/incremental_snapshot.rb +36 -8
- data/lib/rigor/cli/check_command.rb +138 -39
- data/lib/rigor/cli/docs_command.rb +5 -4
- data/lib/rigor/cli/lens_command.rb +144 -0
- data/lib/rigor/cli/lsp_command.rb +5 -2
- data/lib/rigor/cli/skill_command.rb +3 -3
- data/lib/rigor/cli/skill_describe.rb +1 -1
- data/lib/rigor/cli/type_of_command.rb +2 -1
- data/lib/rigor/cli/unused_command.rb +157 -24
- data/lib/rigor/cli.rb +30 -4
- data/lib/rigor/configuration.rb +15 -0
- data/lib/rigor/environment/bundle_sig_discovery.rb +11 -7
- data/lib/rigor/environment/installed_gem_set.rb +38 -11
- data/lib/rigor/environment/lockfile_resolver.rb +37 -6
- data/lib/rigor/environment/missing_gem_constant_index.rb +22 -7
- data/lib/rigor/environment/rbs_loader.rb +33 -0
- data/lib/rigor/environment/required_features.rb +4 -2
- data/lib/rigor/environment.rb +12 -5
- data/lib/rigor/inference/builtins/cruby_definers.rb +22 -5
- data/lib/rigor/inference/captured_locals.rb +43 -3
- data/lib/rigor/inference/expression_typer.rb +58 -25
- data/lib/rigor/inference/in_effect_refinements/scope_reads.rb +21 -17
- data/lib/rigor/inference/match_rebinding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/argument_nodes.rb +25 -0
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +3 -2
- data/lib/rigor/inference/method_dispatcher/match_data_folding.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/member_shape_projection.rb +3 -3
- data/lib/rigor/inference/method_dispatcher/optional_count.rb +63 -0
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +4 -16
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +4 -7
- data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +8 -26
- data/lib/rigor/inference/method_dispatcher/unit_denominator_rational.rb +67 -0
- data/lib/rigor/inference/method_dispatcher.rb +52 -3
- data/lib/rigor/inference/project_patched_definedness_guard.rb +86 -0
- data/lib/rigor/inference/project_patched_methods.rb +2 -2
- data/lib/rigor/inference/project_patched_scanner.rb +38 -24
- data/lib/rigor/inference/refined_dispatch/class_object.rb +350 -0
- data/lib/rigor/inference/refined_dispatch/own_method.rb +112 -40
- data/lib/rigor/inference/refined_dispatch.rb +62 -14
- data/lib/rigor/inference/repeated_or_writes.rb +2 -0
- data/lib/rigor/inference/scope_indexer.rb +140 -5
- data/lib/rigor/inference/statement_evaluator.rb +223 -31
- data/lib/rigor/inference/untyped_rejoin.rb +75 -0
- data/lib/rigor/language_server/project_context.rb +56 -5
- data/lib/rigor/lens/anchor.rb +115 -0
- data/lib/rigor/lens/contract_reader.rb +118 -0
- data/lib/rigor/lens/document.rb +113 -0
- data/lib/rigor/lens/file_reader.rb +433 -0
- data/lib/rigor/lens/members.rb +153 -0
- data/lib/rigor/lens/parameters.rb +91 -0
- data/lib/rigor/lens/plugins.rb +40 -0
- data/lib/rigor/lens/run.rb +280 -0
- data/lib/rigor/lens/slot.rb +79 -0
- data/lib/rigor/lens.rb +40 -0
- data/lib/rigor/project_environment.rb +20 -1
- data/lib/rigor/protection/mutation_cache.rb +2 -1
- data/lib/rigor/scope.rb +22 -11
- data/lib/rigor/sig_gen/generator.rb +45 -5
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_discoverer.rb +29 -3
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +5 -1
- data/sig/rigor/scope.rbs +3 -0
- data/sig/rigor.rbs +6 -3
- data/skills/rigor-project-init/references/02-configure.md +2 -2
- metadata +18 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "rigor/source/node_children"
|
|
4
|
+
require "rigor/source/symbol_name"
|
|
4
5
|
|
|
5
6
|
require "prism"
|
|
6
7
|
|
|
@@ -81,11 +82,16 @@ module Rigor
|
|
|
81
82
|
# fixed point rather than recursing keeps a cyclic `class A < B; class B < A` source — which Ruby
|
|
82
83
|
# rejects but a static parse can still be handed — from recursing forever.
|
|
83
84
|
def close_over_roots(candidates)
|
|
84
|
-
|
|
85
|
+
groups = candidates.group_by(&:class_name)
|
|
86
|
+
# Files that name different superclasses for one class are a TypeError in Ruby, so no ancestry
|
|
87
|
+
# reading of that class is correct. It is declined outright, and so is everything beneath it.
|
|
88
|
+
conflicted = groups.filter_map { |name, group| name if group.map(&:superclass_name).uniq.size > 1 }.to_set
|
|
89
|
+
by_name = groups.except(*conflicted).transform_values { |group| merge_reopened(group) }
|
|
85
90
|
reached = @base_classes.to_set
|
|
86
91
|
loop do
|
|
87
92
|
grown = candidates.select do |entry|
|
|
88
|
-
!
|
|
93
|
+
!conflicted.include?(entry.class_name) && !reached.include?(entry.class_name) &&
|
|
94
|
+
reached.include?(entry.superclass_name)
|
|
89
95
|
end
|
|
90
96
|
break if grown.empty?
|
|
91
97
|
|
|
@@ -94,6 +100,21 @@ module Rigor
|
|
|
94
100
|
reached.filter_map { |name| by_name[name] }
|
|
95
101
|
end
|
|
96
102
|
|
|
103
|
+
# A class declared in several files that each name its superclass is one class to Ruby, so its names
|
|
104
|
+
# are the union of every file's. Keeping only the last file's entry let a sibling that declared nothing
|
|
105
|
+
# usable shadow the valid one. The `own_method_names` union assumes every reopening file is loaded; a
|
|
106
|
+
# file Zeitwerk shadows is not modelled. A superclass-less reopening is not a candidate (see visit_class).
|
|
107
|
+
def merge_reopened(entries)
|
|
108
|
+
return entries.first if entries.size == 1
|
|
109
|
+
|
|
110
|
+
first = entries.first
|
|
111
|
+
first.with(
|
|
112
|
+
declared_names: entries.flat_map(&:declared_names).uniq.sort.freeze,
|
|
113
|
+
object_reads: entries.flat_map(&:object_reads).uniq.sort.freeze,
|
|
114
|
+
own_method_names: entries.flat_map(&:own_method_names).uniq.sort.freeze
|
|
115
|
+
)
|
|
116
|
+
end
|
|
117
|
+
|
|
97
118
|
def read_safely(path)
|
|
98
119
|
@io_boundary.read_file(path)
|
|
99
120
|
rescue Plugin::AccessDeniedError, Errno::ENOENT
|
|
@@ -180,9 +201,14 @@ module Rigor
|
|
|
180
201
|
receiver.arguments.nil?
|
|
181
202
|
end
|
|
182
203
|
|
|
204
|
+
# A name whose bytes no Symbol can hold (`attributes :"\xff"` in a file that does not parse cleanly)
|
|
205
|
+
# is dropped here, so it never reaches the index or the `project_defines?` lookup that would raise.
|
|
206
|
+
# The file's other names are kept: a recoverable syntax error elsewhere in it does not void them.
|
|
183
207
|
def symbol_arguments(node)
|
|
184
208
|
(node.arguments&.arguments || []).filter_map do |argument|
|
|
185
|
-
|
|
209
|
+
next unless argument.is_a?(Prism::SymbolNode)
|
|
210
|
+
|
|
211
|
+
Rigor::Source::SymbolName.of(argument.unescaped)&.to_s
|
|
186
212
|
end
|
|
187
213
|
end
|
|
188
214
|
|
|
@@ -239,7 +239,11 @@ module Rigor
|
|
|
239
239
|
def project_defines?(class_name, method_name, scope)
|
|
240
240
|
return false unless scope.respond_to?(:user_def_through_ancestors)
|
|
241
241
|
|
|
242
|
-
|
|
242
|
+
# A name no Symbol can hold cannot be a method the project defines (#1831): decline, do not raise.
|
|
243
|
+
method = Rigor::Source::SymbolName.of(method_name.to_s)
|
|
244
|
+
return false if method.nil?
|
|
245
|
+
|
|
246
|
+
!scope.user_def_through_ancestors(class_name, method).first.nil?
|
|
243
247
|
end
|
|
244
248
|
|
|
245
249
|
# `REST::AccountSerializer` offers two readings — the namespaced `REST::Account` and the
|
data/sig/rigor/scope.rbs
CHANGED
|
@@ -247,6 +247,7 @@ module Rigor
|
|
|
247
247
|
def optimistic_local_miss: (String | Symbol name) -> Object?
|
|
248
248
|
def optimistic_ivar_miss: (String | Symbol name) -> Object?
|
|
249
249
|
def with_local: (String | Symbol name, Type::t type) -> Scope
|
|
250
|
+
def with_rejoined_locals: (untyped) -> Rigor::Scope
|
|
250
251
|
def with_ivar: (String | Symbol name, Type::t type) -> Scope
|
|
251
252
|
def with_local_origin: (String | Symbol name, Symbol? cause) -> Scope
|
|
252
253
|
def with_optimistic_local: (String | Symbol name, Symbol? cause, ?miss: Object?) -> Scope
|
|
@@ -299,6 +300,8 @@ module Rigor
|
|
|
299
300
|
def inferred_param?: (String | Symbol name) -> bool
|
|
300
301
|
def forget_match_globals: () -> Scope
|
|
301
302
|
def untyped_match_globals: () -> Scope
|
|
303
|
+
# sig-gen gap: #1154 — the reader over the `@globals` ivar `initialize` assigns from a parameter reaches
|
|
304
|
+
# `untyped`, so the `bool` is hand-written.
|
|
302
305
|
def match_globals_bound?: () -> bool
|
|
303
306
|
def with_match_frame: (untyped body, ?untyped parameters) -> Scope
|
|
304
307
|
# sig-gen gap: #1154 — the frame reader over an ivar assigned in `initialize` from a parameter reaches
|
data/sig/rigor.rbs
CHANGED
|
@@ -83,7 +83,6 @@ module Rigor
|
|
|
83
83
|
|
|
84
84
|
class RunStats
|
|
85
85
|
attr_reader wall_seconds: Float
|
|
86
|
-
attr_reader peak_rss_bytes: Integer?
|
|
87
86
|
attr_reader target_files: Integer
|
|
88
87
|
attr_reader rbs_classes_total: Integer
|
|
89
88
|
attr_reader rbs_classes_project_sig: Integer
|
|
@@ -93,21 +92,25 @@ module Rigor
|
|
|
93
92
|
attr_reader rbs_attribution_available: bool
|
|
94
93
|
|
|
95
94
|
CACHED_SENTINEL: String
|
|
95
|
+
CURRENT_PROCESS_PEAK_RSS: ^() -> Integer?
|
|
96
96
|
|
|
97
|
+
# authored: #1529 memoised lazy read; its type enters only through the deliberate `peak_rss_probe:` initialize parameter.
|
|
98
|
+
def peak_rss_bytes: () -> Integer?
|
|
97
99
|
def self.peak_rss_bytes: () -> Integer?
|
|
98
100
|
def self.partition_classes: (class_decl_paths: Hash[String, String], signature_paths: Array[untyped]) -> [Integer, Integer]
|
|
99
101
|
def self.attribution_available?: (class_decl_paths: Hash[String, String]) -> bool
|
|
100
102
|
|
|
101
103
|
def initialize: (
|
|
102
104
|
wall_seconds: Float,
|
|
103
|
-
peak_rss_bytes: Integer?,
|
|
104
105
|
target_files: Integer,
|
|
105
106
|
rbs_classes_total: Integer,
|
|
106
107
|
rbs_classes_project_sig: Integer,
|
|
107
108
|
rbs_classes_bundled: Integer,
|
|
108
109
|
gem_walk_classes: Integer,
|
|
109
110
|
gem_walk_gems: Integer,
|
|
110
|
-
?rbs_attribution_available: bool
|
|
111
|
+
?rbs_attribution_available: bool,
|
|
112
|
+
?peak_rss_bytes: Integer?,
|
|
113
|
+
?peak_rss_probe: ^() -> Integer?
|
|
111
114
|
) -> void
|
|
112
115
|
def format: (untyped out, ?prefix: String) -> void
|
|
113
116
|
def to_h: () -> Hash[Symbol, untyped]
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rigortype
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rigor contributors
|
|
@@ -564,6 +564,7 @@ files:
|
|
|
564
564
|
- lib/rigor/cli/explain_command.rb
|
|
565
565
|
- lib/rigor/cli/fused_protection_renderer.rb
|
|
566
566
|
- lib/rigor/cli/fused_protection_report.rb
|
|
567
|
+
- lib/rigor/cli/lens_command.rb
|
|
567
568
|
- lib/rigor/cli/lsp_command.rb
|
|
568
569
|
- lib/rigor/cli/mcp_command.rb
|
|
569
570
|
- lib/rigor/cli/measurement_integrity_warning.rb
|
|
@@ -756,6 +757,7 @@ files:
|
|
|
756
757
|
- lib/rigor/inference/match_rebinding/self_calls.rb
|
|
757
758
|
- lib/rigor/inference/method_dispatcher.rb
|
|
758
759
|
- lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb
|
|
760
|
+
- lib/rigor/inference/method_dispatcher/argument_nodes.rb
|
|
759
761
|
- lib/rigor/inference/method_dispatcher/arithmetic_sequence_elements.rb
|
|
760
762
|
- lib/rigor/inference/method_dispatcher/array_to_h_folding.rb
|
|
761
763
|
- lib/rigor/inference/method_dispatcher/block_folding.rb
|
|
@@ -777,6 +779,7 @@ files:
|
|
|
777
779
|
- lib/rigor/inference/method_dispatcher/math_folding.rb
|
|
778
780
|
- lib/rigor/inference/method_dispatcher/member_shape_projection.rb
|
|
779
781
|
- lib/rigor/inference/method_dispatcher/method_folding.rb
|
|
782
|
+
- lib/rigor/inference/method_dispatcher/optional_count.rb
|
|
780
783
|
- lib/rigor/inference/method_dispatcher/overload_selector.rb
|
|
781
784
|
- lib/rigor/inference/method_dispatcher/process_folding.rb
|
|
782
785
|
- lib/rigor/inference/method_dispatcher/proven_overload.rb
|
|
@@ -795,6 +798,7 @@ files:
|
|
|
795
798
|
- lib/rigor/inference/method_dispatcher/struct_folding.rb
|
|
796
799
|
- lib/rigor/inference/method_dispatcher/struct_materialization.rb
|
|
797
800
|
- lib/rigor/inference/method_dispatcher/time_folding.rb
|
|
801
|
+
- lib/rigor/inference/method_dispatcher/unit_denominator_rational.rb
|
|
798
802
|
- lib/rigor/inference/method_dispatcher/universal_object_dispatch.rb
|
|
799
803
|
- lib/rigor/inference/method_dispatcher/uri_folding.rb
|
|
800
804
|
- lib/rigor/inference/method_parameter_binder.rb
|
|
@@ -812,6 +816,7 @@ files:
|
|
|
812
816
|
- lib/rigor/inference/pre_eval_constants.rb
|
|
813
817
|
- lib/rigor/inference/precision_scanner.rb
|
|
814
818
|
- lib/rigor/inference/project_method_ownership.rb
|
|
819
|
+
- lib/rigor/inference/project_patched_definedness_guard.rb
|
|
815
820
|
- lib/rigor/inference/project_patched_methods.rb
|
|
816
821
|
- lib/rigor/inference/project_patched_scanner.rb
|
|
817
822
|
- lib/rigor/inference/protection_scanner.rb
|
|
@@ -822,6 +827,7 @@ files:
|
|
|
822
827
|
- lib/rigor/inference/refine_census.rb
|
|
823
828
|
- lib/rigor/inference/refine_self.rb
|
|
824
829
|
- lib/rigor/inference/refined_dispatch.rb
|
|
830
|
+
- lib/rigor/inference/refined_dispatch/class_object.rb
|
|
825
831
|
- lib/rigor/inference/refined_dispatch/own_method.rb
|
|
826
832
|
- lib/rigor/inference/refinement_mutation.rb
|
|
827
833
|
- lib/rigor/inference/repeated_or_writes.rb
|
|
@@ -846,6 +852,7 @@ files:
|
|
|
846
852
|
- lib/rigor/inference/synthetic_method_scanner.rb
|
|
847
853
|
- lib/rigor/inference/unknown_store_widening.rb
|
|
848
854
|
- lib/rigor/inference/unthreaded_rebinds.rb
|
|
855
|
+
- lib/rigor/inference/untyped_rejoin.rb
|
|
849
856
|
- lib/rigor/inference/version_guard.rb
|
|
850
857
|
- lib/rigor/inference/void_origin.rb
|
|
851
858
|
- lib/rigor/inference/void_tail_summary.rb
|
|
@@ -868,6 +875,16 @@ files:
|
|
|
868
875
|
- lib/rigor/language_server/signature_help_provider.rb
|
|
869
876
|
- lib/rigor/language_server/synchronized_writer.rb
|
|
870
877
|
- lib/rigor/language_server/uri.rb
|
|
878
|
+
- lib/rigor/lens.rb
|
|
879
|
+
- lib/rigor/lens/anchor.rb
|
|
880
|
+
- lib/rigor/lens/contract_reader.rb
|
|
881
|
+
- lib/rigor/lens/document.rb
|
|
882
|
+
- lib/rigor/lens/file_reader.rb
|
|
883
|
+
- lib/rigor/lens/members.rb
|
|
884
|
+
- lib/rigor/lens/parameters.rb
|
|
885
|
+
- lib/rigor/lens/plugins.rb
|
|
886
|
+
- lib/rigor/lens/run.rb
|
|
887
|
+
- lib/rigor/lens/slot.rb
|
|
871
888
|
- lib/rigor/mcp.rb
|
|
872
889
|
- lib/rigor/mcp/loop.rb
|
|
873
890
|
- lib/rigor/mcp/server.rb
|