rigortype 0.1.19 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +3 -23
- data/lib/rigor/analysis/check_rules/rule_walk.rb +3 -21
- data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +24 -15
- data/lib/rigor/analysis/check_rules.rb +492 -71
- data/lib/rigor/analysis/dependency_source_inference/index.rb +4 -7
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +2 -18
- data/lib/rigor/analysis/dependency_source_inference.rb +3 -12
- data/lib/rigor/analysis/fact_store.rb +5 -4
- data/lib/rigor/analysis/rule_catalog.rb +153 -6
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +17 -17
- data/lib/rigor/analysis/runner/project_pre_passes.rb +9 -8
- data/lib/rigor/analysis/runner.rb +17 -6
- data/lib/rigor/analysis/self_call_resolution_recorder.rb +3 -4
- data/lib/rigor/analysis/worker_session.rb +10 -14
- data/lib/rigor/builtins/predefined_constant_refinements.rb +151 -0
- data/lib/rigor/cache/store.rb +5 -3
- data/lib/rigor/cli/annotate_command.rb +28 -7
- data/lib/rigor/cli/baseline_command.rb +4 -3
- data/lib/rigor/cli/check_command.rb +115 -16
- data/lib/rigor/cli/coverage_command.rb +148 -16
- data/lib/rigor/cli/coverage_scan.rb +57 -0
- data/lib/rigor/cli/explain_command.rb +2 -0
- data/lib/rigor/cli/lsp_command.rb +3 -7
- data/lib/rigor/cli/mutation_protection_renderer.rb +63 -0
- data/lib/rigor/cli/mutation_protection_report.rb +73 -0
- data/lib/rigor/cli/options.rb +9 -0
- data/lib/rigor/cli/plugins_command.rb +2 -1
- data/lib/rigor/cli/protection_renderer.rb +63 -0
- data/lib/rigor/cli/protection_report.rb +68 -0
- data/lib/rigor/cli/sig_gen_command.rb +2 -1
- data/lib/rigor/cli/trace_command.rb +2 -1
- data/lib/rigor/cli/triage_command.rb +2 -1
- data/lib/rigor/cli/type_of_command.rb +1 -1
- data/lib/rigor/cli/type_scan_command.rb +2 -1
- data/lib/rigor/cli.rb +3 -2
- data/lib/rigor/configuration/dependencies.rb +2 -4
- data/lib/rigor/configuration.rb +45 -7
- data/lib/rigor/environment/bundle_sig_discovery.rb +61 -13
- data/lib/rigor/environment/class_registry.rb +4 -3
- data/lib/rigor/environment/constant_type_cache_holder.rb +43 -0
- data/lib/rigor/environment/lockfile_resolver.rb +1 -1
- data/lib/rigor/environment/rbs_collection_discovery.rb +1 -2
- data/lib/rigor/environment/rbs_coverage_report.rb +2 -1
- data/lib/rigor/environment/rbs_loader.rb +49 -5
- data/lib/rigor/environment.rb +17 -7
- data/lib/rigor/flow_contribution/fact.rb +1 -1
- data/lib/rigor/flow_contribution.rb +3 -5
- data/lib/rigor/inference/acceptance.rb +17 -9
- data/lib/rigor/inference/block_parameter_binder.rb +2 -3
- data/lib/rigor/inference/builtins/comparable_catalog.rb +2 -2
- data/lib/rigor/inference/builtins/enumerable_catalog.rb +2 -2
- data/lib/rigor/inference/builtins/method_catalog.rb +19 -0
- data/lib/rigor/inference/builtins/string_catalog.rb +9 -1
- data/lib/rigor/inference/expression_typer.rb +20 -28
- data/lib/rigor/inference/hkt_body.rb +8 -11
- data/lib/rigor/inference/hkt_body_parser.rb +10 -12
- data/lib/rigor/inference/hkt_registry.rb +10 -11
- data/lib/rigor/inference/method_dispatcher/call_context.rb +1 -4
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +156 -21
- data/lib/rigor/inference/method_dispatcher/data_folding.rb +9 -73
- data/lib/rigor/inference/method_dispatcher/file_folding.rb +6 -7
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +10 -16
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +25 -13
- data/lib/rigor/inference/method_dispatcher/member_shape_projection.rb +93 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +1 -3
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +24 -22
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +90 -15
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +303 -0
- data/lib/rigor/inference/method_dispatcher.rb +40 -48
- data/lib/rigor/inference/mutation_widening.rb +5 -11
- data/lib/rigor/inference/narrowing.rb +14 -16
- data/lib/rigor/inference/parameter_inference_collector.rb +367 -0
- data/lib/rigor/inference/project_patched_methods.rb +4 -7
- data/lib/rigor/inference/project_patched_scanner.rb +2 -13
- data/lib/rigor/inference/protection_scanner.rb +86 -0
- data/lib/rigor/inference/scope_indexer.rb +129 -55
- data/lib/rigor/inference/statement_evaluator.rb +244 -114
- data/lib/rigor/inference/struct_fold_safety.rb +181 -0
- data/lib/rigor/inference/synthetic_method.rb +7 -7
- data/lib/rigor/language_server/completion_provider.rb +6 -12
- data/lib/rigor/language_server/diagnostic_publisher.rb +4 -4
- data/lib/rigor/language_server/document_symbol_provider.rb +3 -3
- data/lib/rigor/language_server/hover_provider.rb +2 -3
- data/lib/rigor/language_server/hover_renderer.rb +2 -11
- data/lib/rigor/language_server/server.rb +9 -17
- data/lib/rigor/language_server.rb +4 -5
- data/lib/rigor/plugin/base.rb +10 -8
- data/lib/rigor/plugin/macro/block_as_method.rb +3 -4
- data/lib/rigor/plugin/macro/heredoc_template.rb +4 -7
- data/lib/rigor/plugin/macro/trait_registry.rb +3 -6
- data/lib/rigor/plugin/macro.rb +4 -5
- data/lib/rigor/plugin/manifest.rb +45 -66
- data/lib/rigor/plugin/registry.rb +6 -7
- data/lib/rigor/plugin/type_node_resolver.rb +6 -8
- data/lib/rigor/protection/mutation_scanner.rb +120 -0
- data/lib/rigor/protection/mutator.rb +246 -0
- data/lib/rigor/rbs_extended.rb +24 -36
- data/lib/rigor/reflection.rb +4 -7
- data/lib/rigor/scope/discovery_index.rb +14 -2
- data/lib/rigor/scope.rb +54 -11
- data/lib/rigor/sig_gen/observed_call.rb +3 -3
- data/lib/rigor/sig_gen/writer.rb +40 -2
- data/lib/rigor/source/constant_path.rb +62 -0
- data/lib/rigor/source.rb +1 -0
- data/lib/rigor/type/bound_method.rb +2 -11
- data/lib/rigor/type/combinator.rb +16 -3
- data/lib/rigor/type/constant.rb +2 -11
- data/lib/rigor/type/data_class.rb +2 -11
- data/lib/rigor/type/data_instance.rb +2 -11
- data/lib/rigor/type/hash_shape.rb +2 -11
- data/lib/rigor/type/integer_range.rb +2 -11
- data/lib/rigor/type/intersection.rb +2 -11
- data/lib/rigor/type/nominal.rb +2 -11
- data/lib/rigor/type/plain_lattice.rb +37 -0
- data/lib/rigor/type/refined.rb +72 -13
- data/lib/rigor/type/singleton.rb +2 -11
- data/lib/rigor/type/struct_class.rb +75 -0
- data/lib/rigor/type/struct_instance.rb +93 -0
- data/lib/rigor/type/tuple.rb +5 -15
- data/lib/rigor/type.rb +2 -0
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +3 -3
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +3 -3
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +5 -13
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +11 -17
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +7 -10
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +3 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +4 -4
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +6 -8
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +5 -7
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +1 -2
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +9 -11
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +8 -9
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +13 -12
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +3 -4
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +8 -8
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +9 -11
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +7 -8
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +7 -9
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +12 -13
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +15 -23
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +3 -3
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +3 -3
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +2 -4
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +27 -11
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +1 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +4 -6
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +12 -18
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +5 -5
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +3 -4
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +1 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +1 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +19 -14
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +0 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +5 -4
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +2 -3
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/method_signature.rb +7 -11
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +4 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +6 -9
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +5 -15
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +28 -41
- data/sig/rigor/scope.rbs +9 -1
- data/sig/rigor/type.rbs +36 -1
- metadata +19 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e5c87db4b1ce8d734a2c7f8d7f0b7af6a7d643612f011c08676a5bca123ae4cb
|
|
4
|
+
data.tar.gz: b9340fe30f78245443d61d82965e08f2833e4787b938886f8f42890981a88cff
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 94cafd68574caa752869465bcbf8a8e646bf302f4c540f9eb3dee122b6d455c193a21dd2debbf2c481f1676fb4c83aca131a3ba73508fef65c3dd1f2a3debaaa
|
|
7
|
+
data.tar.gz: f762d58ad77bd3e819f346b6de84408769320d6025030737b3611ce918db4c5e7943e0371b9b0603c27c2be8b8d2064975ff1e2bb113b4e3af8443bb2723fd05
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require "prism"
|
|
4
4
|
|
|
5
|
+
require_relative "../../source/constant_path"
|
|
6
|
+
|
|
5
7
|
module Rigor
|
|
6
8
|
module Analysis
|
|
7
9
|
module CheckRules
|
|
@@ -80,7 +82,7 @@ module Rigor
|
|
|
80
82
|
|
|
81
83
|
case node
|
|
82
84
|
when Prism::ClassNode, Prism::ModuleNode
|
|
83
|
-
name =
|
|
85
|
+
name = Source::ConstantPath.qualified_name(node.constant_path)
|
|
84
86
|
if name
|
|
85
87
|
walk(node.body, qualified_prefix + [name]) if node.body
|
|
86
88
|
return
|
|
@@ -119,28 +121,6 @@ module Rigor
|
|
|
119
121
|
@accumulator[class_name][node.name] ||= []
|
|
120
122
|
@accumulator[class_name][node.name] << { node: node, type: rvalue_type }
|
|
121
123
|
end
|
|
122
|
-
|
|
123
|
-
# Same shape resolution as `ScopeIndexer.qualified_name_for`
|
|
124
|
-
# (single-segment ConstantReadNode and dotted
|
|
125
|
-
# ConstantPathNode). Inlined here to keep the collector
|
|
126
|
-
# self-contained — the rule lives outside the indexer's
|
|
127
|
-
# private surface.
|
|
128
|
-
def qualified_name_for(constant_path_node)
|
|
129
|
-
case constant_path_node
|
|
130
|
-
when Prism::ConstantReadNode then constant_path_node.name.to_s
|
|
131
|
-
when Prism::ConstantPathNode then render_constant_path(constant_path_node)
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def render_constant_path(node)
|
|
136
|
-
prefix =
|
|
137
|
-
case node.parent
|
|
138
|
-
when Prism::ConstantReadNode then "#{node.parent.name}::"
|
|
139
|
-
when Prism::ConstantPathNode then "#{render_constant_path(node.parent)}::"
|
|
140
|
-
else ""
|
|
141
|
-
end
|
|
142
|
-
"#{prefix}#{node.name}"
|
|
143
|
-
end
|
|
144
124
|
end
|
|
145
125
|
end
|
|
146
126
|
end
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require "prism"
|
|
4
4
|
|
|
5
|
+
require_relative "../../source/constant_path"
|
|
6
|
+
|
|
5
7
|
module Rigor
|
|
6
8
|
module Analysis
|
|
7
9
|
module CheckRules
|
|
@@ -183,29 +185,9 @@ module Rigor
|
|
|
183
185
|
def extend_prefix(node, prefix)
|
|
184
186
|
return prefix unless CLASS_OR_MODULE_NODE_CLASSES.any? { |klass| node.is_a?(klass) }
|
|
185
187
|
|
|
186
|
-
name =
|
|
188
|
+
name = Source::ConstantPath.qualified_name(node.constant_path)
|
|
187
189
|
name ? prefix + [name] : prefix
|
|
188
190
|
end
|
|
189
|
-
|
|
190
|
-
# Same shape resolution as `IvarWriteCollector#qualified_name_for`
|
|
191
|
-
# and `ScopeIndexer.qualified_name_for` (single-segment
|
|
192
|
-
# ConstantReadNode and dotted ConstantPathNode).
|
|
193
|
-
def qualified_name_for(constant_path_node)
|
|
194
|
-
case constant_path_node
|
|
195
|
-
when Prism::ConstantReadNode then constant_path_node.name.to_s
|
|
196
|
-
when Prism::ConstantPathNode then render_constant_path(constant_path_node)
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
def render_constant_path(node)
|
|
201
|
-
prefix =
|
|
202
|
-
case node.parent
|
|
203
|
-
when Prism::ConstantReadNode then "#{node.parent.name}::"
|
|
204
|
-
when Prism::ConstantPathNode then "#{render_constant_path(node.parent)}::"
|
|
205
|
-
else ""
|
|
206
|
-
end
|
|
207
|
-
"#{prefix}#{node.name}"
|
|
208
|
-
end
|
|
209
191
|
end
|
|
210
192
|
end
|
|
211
193
|
end
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require "prism"
|
|
4
4
|
|
|
5
|
+
require_relative "../../source/constant_path"
|
|
6
|
+
|
|
5
7
|
module Rigor
|
|
6
8
|
module Analysis
|
|
7
9
|
module CheckRules
|
|
@@ -45,20 +47,27 @@ module Rigor
|
|
|
45
47
|
|
|
46
48
|
case node
|
|
47
49
|
when Prism::ModuleNode
|
|
48
|
-
name =
|
|
50
|
+
name = Source::ConstantPath.qualified_name_or_nil(node.constant_path)
|
|
49
51
|
child_prefix = name ? prefix + [name] : prefix
|
|
50
52
|
names << child_prefix.join("::") if name
|
|
51
53
|
walk(node.body, child_prefix, names) if node.body
|
|
52
54
|
when Prism::ClassNode
|
|
53
|
-
name =
|
|
55
|
+
name = Source::ConstantPath.qualified_name_or_nil(node.constant_path)
|
|
54
56
|
child_prefix = name ? prefix + [name] : prefix
|
|
55
|
-
names << child_prefix.join("::") if name &&
|
|
57
|
+
names << child_prefix.join("::") if name && class_surface_open?(node)
|
|
56
58
|
walk(node.body, child_prefix, names) if node.body
|
|
57
59
|
else
|
|
58
60
|
node.compact_child_nodes.each { |child| walk(child, prefix, names) }
|
|
59
61
|
end
|
|
60
62
|
end
|
|
61
63
|
|
|
64
|
+
# A class whose source-declared surface cannot be fully enumerated:
|
|
65
|
+
# a dynamic `attr_*` accessor, or a non-constant (dynamically produced)
|
|
66
|
+
# superclass.
|
|
67
|
+
def class_surface_open?(class_node)
|
|
68
|
+
dynamic_attr_class?(class_node) || dynamic_superclass?(class_node)
|
|
69
|
+
end
|
|
70
|
+
|
|
62
71
|
# True when the class body directly invokes an `attr_*` macro with a
|
|
63
72
|
# non-literal argument (a splat, a constant, a method call) — the
|
|
64
73
|
# synthesized accessor names are then not statically knowable.
|
|
@@ -81,18 +90,18 @@ module Rigor
|
|
|
81
90
|
args.any? { |arg| !arg.is_a?(Prism::SymbolNode) && !arg.is_a?(Prism::StringNode) }
|
|
82
91
|
end
|
|
83
92
|
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
# True when the class declares a superclass that is not a static
|
|
94
|
+
# constant — `class X < DelegateClass(Array)` / `< Struct.new(...)` /
|
|
95
|
+
# `< Data.define(...)`. The inherited surface is then a dynamically
|
|
96
|
+
# produced class the engine cannot enumerate from a constant name (the
|
|
97
|
+
# superclass is a method call, so `discovered_superclasses` never
|
|
98
|
+
# records it and the closed-class gate would wrongly treat the class as
|
|
99
|
+
# standalone), so a missed self-call is not provably a typo.
|
|
100
|
+
def dynamic_superclass?(class_node)
|
|
101
|
+
superclass = class_node.superclass
|
|
102
|
+
return false if superclass.nil?
|
|
103
|
+
|
|
104
|
+
!superclass.is_a?(Prism::ConstantReadNode) && !superclass.is_a?(Prism::ConstantPathNode)
|
|
96
105
|
end
|
|
97
106
|
end
|
|
98
107
|
end
|