rigortype 0.1.16 → 0.1.18

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.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -2
  3. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +18 -1
  4. data/lib/rigor/analysis/check_rules/rule_walk.rb +67 -0
  5. data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +100 -0
  6. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +226 -0
  7. data/lib/rigor/analysis/check_rules.rb +180 -73
  8. data/lib/rigor/analysis/dependency_recorder.rb +122 -0
  9. data/lib/rigor/analysis/diagnostic.rb +18 -0
  10. data/lib/rigor/analysis/incremental.rb +162 -0
  11. data/lib/rigor/analysis/incremental_session.rb +337 -0
  12. data/lib/rigor/analysis/rule_catalog.rb +48 -0
  13. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +580 -0
  14. data/lib/rigor/analysis/runner/pool_coordinator.rb +569 -0
  15. data/lib/rigor/analysis/runner/project_pre_passes.rb +318 -0
  16. data/lib/rigor/analysis/runner/run_snapshots.rb +46 -0
  17. data/lib/rigor/analysis/runner.rb +477 -1110
  18. data/lib/rigor/analysis/self_call_resolution_recorder.rb +121 -0
  19. data/lib/rigor/analysis/worker_session.rb +47 -8
  20. data/lib/rigor/builtins/static_return_refinements.rb +7 -1
  21. data/lib/rigor/cache/descriptor.rb +50 -49
  22. data/lib/rigor/cache/incremental_snapshot.rb +153 -0
  23. data/lib/rigor/cache/rbs_cache_producer.rb +34 -0
  24. data/lib/rigor/cache/rbs_class_ancestor_table.rb +2 -8
  25. data/lib/rigor/cache/rbs_class_type_param_names.rb +2 -8
  26. data/lib/rigor/cache/rbs_constant_table.rb +2 -8
  27. data/lib/rigor/cache/rbs_environment.rb +2 -8
  28. data/lib/rigor/cache/rbs_known_class_names.rb +2 -8
  29. data/lib/rigor/cache/store.rb +145 -14
  30. data/lib/rigor/cli/annotate_command.rb +2 -7
  31. data/lib/rigor/cli/baseline_command.rb +2 -7
  32. data/lib/rigor/cli/check_command.rb +705 -0
  33. data/lib/rigor/cli/ci_detector.rb +94 -0
  34. data/lib/rigor/cli/command.rb +47 -0
  35. data/lib/rigor/cli/coverage_command.rb +3 -23
  36. data/lib/rigor/cli/coverage_renderer.rb +3 -8
  37. data/lib/rigor/cli/diagnostic_formats.rb +345 -0
  38. data/lib/rigor/cli/diff_command.rb +3 -7
  39. data/lib/rigor/cli/explain_command.rb +2 -7
  40. data/lib/rigor/cli/lsp_command.rb +3 -7
  41. data/lib/rigor/cli/mcp_command.rb +3 -7
  42. data/lib/rigor/cli/options.rb +57 -0
  43. data/lib/rigor/cli/plugin_command.rb +3 -7
  44. data/lib/rigor/cli/plugins_command.rb +2 -7
  45. data/lib/rigor/cli/prism_colorizer.rb +10 -3
  46. data/lib/rigor/cli/renderable.rb +26 -0
  47. data/lib/rigor/cli/sig_gen_command.rb +2 -7
  48. data/lib/rigor/cli/skill_command.rb +3 -7
  49. data/lib/rigor/cli/trace_command.rb +143 -0
  50. data/lib/rigor/cli/trace_renderer.rb +310 -0
  51. data/lib/rigor/cli/triage_command.rb +2 -7
  52. data/lib/rigor/cli/type_of_command.rb +5 -38
  53. data/lib/rigor/cli/type_of_renderer.rb +4 -9
  54. data/lib/rigor/cli/type_scan_command.rb +3 -23
  55. data/lib/rigor/cli/type_scan_renderer.rb +4 -9
  56. data/lib/rigor/cli.rb +15 -532
  57. data/lib/rigor/configuration/dependencies.rb +18 -1
  58. data/lib/rigor/configuration/severity_profile.rb +22 -3
  59. data/lib/rigor/configuration.rb +16 -3
  60. data/lib/rigor/environment/rbs_loader.rb +129 -71
  61. data/lib/rigor/environment.rb +1 -1
  62. data/lib/rigor/inference/acceptance.rb +10 -0
  63. data/lib/rigor/inference/block_parameter_binder.rb +1 -2
  64. data/lib/rigor/inference/builtins/array_catalog.rb +2 -5
  65. data/lib/rigor/inference/builtins/comparable_catalog.rb +2 -5
  66. data/lib/rigor/inference/builtins/complex_catalog.rb +2 -5
  67. data/lib/rigor/inference/builtins/date_catalog.rb +2 -5
  68. data/lib/rigor/inference/builtins/encoding_catalog.rb +2 -5
  69. data/lib/rigor/inference/builtins/enumerable_catalog.rb +2 -5
  70. data/lib/rigor/inference/builtins/exception_catalog.rb +2 -5
  71. data/lib/rigor/inference/builtins/hash_catalog.rb +2 -5
  72. data/lib/rigor/inference/builtins/method_catalog.rb +15 -0
  73. data/lib/rigor/inference/builtins/numeric_catalog.rb +21 -93
  74. data/lib/rigor/inference/builtins/pathname_catalog.rb +2 -5
  75. data/lib/rigor/inference/builtins/proc_catalog.rb +2 -5
  76. data/lib/rigor/inference/builtins/random_catalog.rb +2 -5
  77. data/lib/rigor/inference/builtins/range_catalog.rb +2 -5
  78. data/lib/rigor/inference/builtins/rational_catalog.rb +2 -5
  79. data/lib/rigor/inference/builtins/re_catalog.rb +2 -5
  80. data/lib/rigor/inference/builtins/set_catalog.rb +2 -5
  81. data/lib/rigor/inference/builtins/string_catalog.rb +2 -5
  82. data/lib/rigor/inference/builtins/struct_catalog.rb +2 -5
  83. data/lib/rigor/inference/builtins/time_catalog.rb +2 -5
  84. data/lib/rigor/inference/expression_typer.rb +149 -63
  85. data/lib/rigor/inference/flow_tracer.rb +180 -0
  86. data/lib/rigor/inference/macro_block_self_type.rb +10 -11
  87. data/lib/rigor/inference/method_dispatcher/block_folding.rb +5 -1
  88. data/lib/rigor/inference/method_dispatcher/call_context.rb +65 -0
  89. data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +11 -10
  90. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +12 -6
  91. data/lib/rigor/inference/method_dispatcher/data_folding.rb +246 -0
  92. data/lib/rigor/inference/method_dispatcher/file_folding.rb +6 -2
  93. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +6 -2
  94. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +4 -1
  95. data/lib/rigor/inference/method_dispatcher/literal_string_folding.rb +4 -1
  96. data/lib/rigor/inference/method_dispatcher/math_folding.rb +6 -6
  97. data/lib/rigor/inference/method_dispatcher/method_folding.rb +12 -7
  98. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +33 -1
  99. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +23 -13
  100. data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +9 -9
  101. data/lib/rigor/inference/method_dispatcher/set_folding.rb +6 -6
  102. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +120 -9
  103. data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +12 -12
  104. data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +49 -0
  105. data/lib/rigor/inference/method_dispatcher/time_folding.rb +6 -6
  106. data/lib/rigor/inference/method_dispatcher/uri_folding.rb +9 -9
  107. data/lib/rigor/inference/method_dispatcher.rb +185 -84
  108. data/lib/rigor/inference/narrowing.rb +262 -5
  109. data/lib/rigor/inference/scope_indexer.rb +208 -21
  110. data/lib/rigor/inference/statement_evaluator.rb +110 -48
  111. data/lib/rigor/language_server/buffer_resolution.rb +33 -0
  112. data/lib/rigor/language_server/completion_provider.rb +4 -4
  113. data/lib/rigor/language_server/document_symbol_provider.rb +4 -4
  114. data/lib/rigor/language_server/folding_range_provider.rb +4 -4
  115. data/lib/rigor/language_server/hover_provider.rb +4 -4
  116. data/lib/rigor/language_server/selection_range_provider.rb +4 -4
  117. data/lib/rigor/language_server/signature_help_provider.rb +4 -4
  118. data/lib/rigor/plugin/additional_initializer.rb +61 -38
  119. data/lib/rigor/plugin/base.rb +302 -45
  120. data/lib/rigor/plugin/node_rule_walk.rb +147 -0
  121. data/lib/rigor/plugin/registry.rb +281 -15
  122. data/lib/rigor/plugin.rb +1 -0
  123. data/lib/rigor/rbs_extended/conformance_checker.rb +293 -0
  124. data/lib/rigor/rbs_extended.rb +39 -0
  125. data/lib/rigor/scope/discovery_index.rb +58 -0
  126. data/lib/rigor/scope.rb +150 -167
  127. data/lib/rigor/sig_gen/observation_collector.rb +6 -6
  128. data/lib/rigor/source/literals.rb +14 -0
  129. data/lib/rigor/type/acceptance_router.rb +19 -0
  130. data/lib/rigor/type/accepts_result.rb +3 -10
  131. data/lib/rigor/type/app.rb +3 -7
  132. data/lib/rigor/type/bot.rb +2 -3
  133. data/lib/rigor/type/bound_method.rb +5 -12
  134. data/lib/rigor/type/combinator.rb +22 -0
  135. data/lib/rigor/type/constant.rb +2 -3
  136. data/lib/rigor/type/data_class.rb +80 -0
  137. data/lib/rigor/type/data_instance.rb +100 -0
  138. data/lib/rigor/type/difference.rb +5 -10
  139. data/lib/rigor/type/dynamic.rb +5 -10
  140. data/lib/rigor/type/hash_shape.rb +5 -15
  141. data/lib/rigor/type/integer_range.rb +5 -10
  142. data/lib/rigor/type/intersection.rb +5 -10
  143. data/lib/rigor/type/nominal.rb +5 -10
  144. data/lib/rigor/type/refined.rb +5 -10
  145. data/lib/rigor/type/singleton.rb +5 -10
  146. data/lib/rigor/type/top.rb +2 -3
  147. data/lib/rigor/type/tuple.rb +5 -10
  148. data/lib/rigor/type/union.rb +5 -10
  149. data/lib/rigor/type.rb +2 -0
  150. data/lib/rigor/value_semantics.rb +77 -0
  151. data/lib/rigor/version.rb +1 -1
  152. data/lib/rigor.rb +1 -1
  153. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +1 -2
  154. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +2 -4
  155. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +70 -32
  156. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +3 -3
  157. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +15 -21
  158. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +1 -1
  159. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +1 -2
  160. data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +2 -2
  161. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +12 -2
  162. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +12 -2
  163. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +1 -1
  164. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +35 -18
  165. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +8 -29
  166. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +17 -1
  167. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +2 -2
  168. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +83 -36
  169. data/sig/rigor/cache.rbs +19 -0
  170. data/sig/rigor/environment.rbs +0 -2
  171. data/sig/rigor/inference.rbs +27 -0
  172. data/sig/rigor/plugin/base.rbs +1 -2
  173. data/sig/rigor/rbs_extended.rbs +2 -0
  174. data/sig/rigor/scope.rbs +42 -25
  175. data/sig/rigor/source.rbs +1 -0
  176. data/sig/rigor/type.rbs +58 -1
  177. data/sig/rigor.rbs +6 -1
  178. data/skills/rigor-ci-setup/SKILL.md +319 -0
  179. metadata +36 -2
  180. data/lib/rigor/cache/rbs_instance_definitions.rb +0 -79
@@ -6,7 +6,7 @@ module Rigor
6
6
  # Per-run table of method signatures keyed by the
7
7
  # `(class_name, method_name, kind)` triple. Built by
8
8
  # {CatalogWalker} during the plugin's lazy pre-walk; read
9
- # by {Sorbet#flow_contribution_for} at every call site.
9
+ # by the plugin's `dynamic_return` rule at every gated call site.
10
10
  #
11
11
  # The catalog is mutable while it is being built, then
12
12
  # frozen via {#freeze!} before the first read. Construction
@@ -80,6 +80,22 @@ module Rigor
80
80
  @entries.empty?
81
81
  end
82
82
 
83
+ # ADR-52 slice 4 — the distinct method names the catalog
84
+ # carries at least one signature for, across every
85
+ # `(class_name, kind)` owner. Feeds the plugin's run-time
86
+ # `dynamic_return methods:` name gate: the engine only
87
+ # consults the plugin for a call whose name appears here
88
+ # (or in the static assertion vocabulary), and the
89
+ # precise `(class, kind)` lookup stays in the rule block.
90
+ # Computed fresh per call — the plugin memoises the
91
+ # resolved set, and `freeze!` freezes the catalog itself
92
+ # so a lazy memo ivar here would raise.
93
+ #
94
+ # @return [Array<Symbol>]
95
+ def method_names
96
+ @entries.keys.map { |key| key[1] }.uniq
97
+ end
98
+
83
99
  def size
84
100
  @entries.size
85
101
  end
@@ -24,8 +24,8 @@ module Rigor
24
24
  # identically — per-call-site sigil honouring (e.g. only
25
25
  # firing `T.let` recognition in `# typed: true`+ files)
26
26
  # requires threading the file path through
27
- # `flow_contribution_for`, which lives behind a future
28
- # plugin-contract widening slice.
27
+ # the per-call recognition path, which lives behind a
28
+ # future plugin-contract widening slice.
29
29
  module SigilDetector
30
30
  # Sorbet's strictness-level names. Stored as symbols to
31
31
  # match the analyzer's existing convention for level
@@ -39,8 +39,8 @@ module Rigor
39
39
  # access by walking every configured `paths:` entry's `.rb`
40
40
  # files plus every `rbi_paths:` entry's `.rbi` files (slice
41
41
  # 4) via the plugin's `IoBoundary`. The catalog is frozen
42
- # after the first build and consulted by
43
- # `#flow_contribution_for` at every call site. RBI files
42
+ # after the first build and consulted by the `dynamic_return`
43
+ # rule at every gated call site. RBI files
44
44
  # share the catalog with project-source sigs — both produce
45
45
  # `MethodSignature` entries keyed by
46
46
  # `(class_name, method_name, kind)`. When a key collides
@@ -101,7 +101,7 @@ module Rigor
101
101
  @enforce_sigil = config.fetch("enforce_sigil")
102
102
  # ADR-11 deferred follow-up — per-call-site assertion
103
103
  # gating. Catalog harvest's `@sigil_by_path` cache is
104
- # consulted at every `flow_contribution_for` call so
104
+ # consulted at every per-call recognition so
105
105
  # `T.let` / `T.cast` / `T.must` / `T.bind` /
106
106
  # `T.assert_type!` only fire in files Sorbet itself
107
107
  # would enforce (`# typed: true` / `:strict` /
@@ -118,7 +118,7 @@ module Rigor
118
118
  @parse_errors_by_path = {}
119
119
  @catalog_built = false
120
120
  # ADR-11 slice 6 — Prism nodes for `T.absurd` calls
121
- # we observed in `flow_contribution_for` to be
121
+ # we observed in the `dynamic_return` rule to be
122
122
  # *reachable* (i.e., their discriminant didn't narrow
123
123
  # to `bot`). `diagnostics_for_file` walks the per-file
124
124
  # AST and surfaces these as `plugin.sorbet.absurd-reachable`
@@ -128,7 +128,7 @@ module Rigor
128
128
  # plugin hooks.
129
129
  @reachable_absurd_nodes = {}.compare_by_identity
130
130
  # ADR-11 light follow-up — `T.reveal_type` calls
131
- # observed in `flow_contribution_for`, paired with the
131
+ # observed in the `dynamic_return` rule, paired with the
132
132
  # display string for the inferred type at the call site.
133
133
  # Mirrors the absurd-node compare-by-identity hash;
134
134
  # `diagnostics_for_file` surfaces each entry as a
@@ -136,7 +136,7 @@ module Rigor
136
136
  @reveal_type_calls = {}.compare_by_identity
137
137
  # T.bind / T.assert_type! priority slice 1 —
138
138
  # `T.assert_type!` calls observed in
139
- # `flow_contribution_for` whose static subtype check
139
+ # the `dynamic_return` rule whose static subtype check
140
140
  # FAILED, paired with the inferred + asserted type
141
141
  # display strings. Same compare-by-identity discipline.
142
142
  # `diagnostics_for_file` walks the file AST for
@@ -160,9 +160,52 @@ module Rigor
160
160
  diagnostics
161
161
  end
162
162
 
163
- # ADR-11 slice 1 — return-type contribution from the
164
- # parsed `sig { ... }` block. Resolves the receiver in two
165
- # passes:
163
+ # ADR-52 slice 4the per-call return-type path, migrated off
164
+ # the legacy `flow_contribution_for` hook onto the
165
+ # method-name-gated `dynamic_return` DSL. The recognised name
166
+ # set is only known at run time (the catalog's `def` names come
167
+ # from the lazy catalog build), so it is declared as a
168
+ # callable: the engine `instance_exec`s it once per run on
169
+ # first dispatch (always after `#prepare`) and memoises the
170
+ # resolved Symbol Set. The gate is a safe over-approximation —
171
+ # a project method merely *named* `cast` or `find` passes it
172
+ # and is declined by the block's own `T.`-receiver / catalog
173
+ # checks, exactly as the ungated hook used to decline.
174
+ dynamic_return methods: -> { recognised_method_names } do |call_node, scope|
175
+ contribution_return_type(call_node, scope)
176
+ end
177
+
178
+ # ADR-52 slice 4 — `T.bind(self, T)`'s self-narrowing fact,
179
+ # migrated off the legacy hook's `post_return_facts` slot onto
180
+ # the method-gated `type_specifier` DSL (once
181
+ # `flow_contribution_for` is gone, the statement evaluator
182
+ # consults only this path for narrowing facts). The
183
+ # return-type half (`Constant[nil]`) flows through the
184
+ # `dynamic_return` rule above; the block re-checks the `T.`
185
+ # receiver via the recogniser, so an unrelated `bind` call
186
+ # contributes nothing.
187
+ type_specifier methods: [:bind] do |call_node, scope|
188
+ bind_post_return_facts(call_node, scope)
189
+ end
190
+
191
+ private
192
+
193
+ # ADR-52 slice 4 — the run-time method-name gate for the
194
+ # `dynamic_return` rule: the static assertion vocabulary
195
+ # (`T.let` / `T.cast` / …), `T.absurd`, and every method name
196
+ # the catalog carries a sig for.
197
+ def recognised_method_names
198
+ ensure_catalog
199
+ names = AssertionRecognizer::SORBET_ASSERTIONS.dup
200
+ names << :absurd
201
+ names.concat(@catalog.method_names)
202
+ names
203
+ end
204
+
205
+ # The migrated body of the legacy `flow_contribution_for` —
206
+ # same recognition order, but returns the bare `Rigor::Type`
207
+ # the `dynamic_return` contract expects. Resolves the receiver
208
+ # in two passes:
166
209
  #
167
210
  # 1. Constant receiver (`User.find(...)`) → singleton-side
168
211
  # catalog lookup.
@@ -173,18 +216,22 @@ module Rigor
173
216
  # Implicit-self calls (no receiver, current-class method)
174
217
  # are deferred to slice 2 — slice 1 covers the common case
175
218
  # where the sig is on the called method's own class.
176
- def flow_contribution_for(call_node:, scope:)
219
+ def contribution_return_type(call_node, scope)
177
220
  return nil unless call_node.is_a?(Prism::CallNode)
178
221
 
179
222
  # ADR-11 slice 6 — `T.absurd(x)` exhaustiveness. Always
180
- # contributes a `bot` return + raise effect (matches
181
- # Sorbet's runtime behaviour); when the discriminant
182
- # *isn't* narrowed to `bot` at this scope, also records
183
- # the call node so `diagnostics_for_file` can surface a
184
- # `plugin.sorbet.absurd-reachable` warning.
223
+ # contributes a `bot` return (matches Sorbet's runtime
224
+ # behaviour: `T.absurd` raises, so its value type is `bot`
225
+ # and the engine's flow analysis treats code after it as
226
+ # unreachable; the legacy contribution's `exceptional:
227
+ # :raises` slot was never consumed on the dispatcher path —
228
+ # only `return_type` survives the merge). When the
229
+ # discriminant *isn't* narrowed to `bot` at this scope, also
230
+ # records the call node so `diagnostics_for_file` can surface
231
+ # a `plugin.sorbet.absurd-reachable` warning.
185
232
  if AbsurdRecognizer.absurd_call?(call_node)
186
233
  @reachable_absurd_nodes[call_node] = true unless AbsurdRecognizer.exhaustive?(call_node, scope)
187
- return AbsurdRecognizer.contribution(call_node, manifest.id)
234
+ return Rigor::Type::Combinator.bot
188
235
  end
189
236
 
190
237
  # ADR-11 slice 2 — `T.let` / `T.cast` / `T.must` /
@@ -214,31 +261,31 @@ module Rigor
214
261
  if assertion
215
262
  record_reveal_type_call(call_node, assertion.return_type) if call_node.name == :reveal_type
216
263
  record_assert_type_check(call_node, scope) if call_node.name == :assert_type!
217
- return assertion
264
+ return assertion.return_type
218
265
  end
219
266
  end
220
267
 
221
268
  return nil if @catalog.nil? || @catalog.empty?
222
269
 
223
- signature = lookup_signature(call_node, scope)
224
- return nil if signature.nil?
270
+ lookup_signature(call_node, scope)&.return_type
271
+ end
225
272
 
226
- return_type = signature.return_type
227
- return nil if return_type.nil?
273
+ # The `type_specifier` body for `T.bind` — same sigil gate as
274
+ # the return-type path, then the recogniser's
275
+ # `post_return_facts` (the `Fact(target_kind: :self)` that
276
+ # narrows `scope.self_type` for the rest of the block).
277
+ def bind_post_return_facts(call_node, scope)
278
+ return nil unless call_node.is_a?(Prism::CallNode)
228
279
 
229
- Rigor::FlowContribution.new(
230
- return_type: return_type,
231
- provenance: Rigor::FlowContribution::Provenance.new(
232
- source_family: "plugin.#{manifest.id}",
233
- plugin_id: manifest.id,
234
- node: call_node,
235
- descriptor: nil
236
- )
280
+ ensure_catalog
281
+ return nil unless assertion_enforced_here?(scope)
282
+
283
+ contribution = AssertionRecognizer.recognize(
284
+ call_node: call_node, scope: scope, plugin_id: manifest.id
237
285
  )
286
+ contribution&.post_return_facts
238
287
  end
239
288
 
240
- private
241
-
242
289
  # ADR-11 deferred follow-up — per-call-site assertion
243
290
  # gating. With `enforce_sigil: false`, the gate is fully
244
291
  # open (matches the pre-feature behaviour). With
@@ -441,7 +488,7 @@ module Rigor
441
488
  # magic comment by skipping the file entirely.
442
489
  level = SigilDetector.detect(contents)
443
490
  # Per-call-site assertion gating consults this map at
444
- # `flow_contribution_for`. Recorded BEFORE the ignored
491
+ # recognition time. Recorded BEFORE the ignored
445
492
  # short-circuit so a `# typed: ignore` file still
446
493
  # reports its level to the gate (the gate then chooses
447
494
  # to suppress assertions there too — `ignore` is
@@ -481,7 +528,7 @@ module Rigor
481
528
  # nodes and emits a `plugin.sorbet.absurd-reachable`
482
529
  # warning for any whose object identity matches
483
530
  # `@reachable_absurd_nodes` (populated during the engine's
484
- # earlier pass through `flow_contribution_for`). Pops
531
+ # earlier pass through the `dynamic_return` rule). Pops
485
532
  # matched entries so a duplicate run doesn't double-emit.
486
533
  def absurd_reachable_diagnostics(path, root)
487
534
  return [] if @reachable_absurd_nodes.empty?
@@ -569,8 +616,8 @@ module Rigor
569
616
  # static subtype check at recogniser time and records the
570
617
  # call only when the inferred type is *provably
571
618
  # incompatible* with the asserted type. Gradual
572
- # consistency rules (`Inference::Acceptance.accepts(...)`
573
- # mode `:gradual`): a `Dynamic[top]` inferred type
619
+ # consistency rules (`Type#accepts` mode `:gradual`): a
620
+ # `Dynamic[top]` inferred type
574
621
  # silences the check; a definite `:no` records for
575
622
  # diagnostic emission; `:maybe` (uncertain) is treated as
576
623
  # "trust the user" and silenced — the runtime check is
@@ -582,7 +629,7 @@ module Rigor
582
629
  inferred, asserted = check
583
630
  return if inferred.nil?
584
631
 
585
- result = Rigor::Inference::Acceptance.accepts(asserted, inferred)
632
+ result = asserted.accepts(inferred)
586
633
  return unless result.no?
587
634
 
588
635
  @assert_type_mismatches[call_node] = [display_for_type(inferred), display_for_type(asserted)]
@@ -0,0 +1,19 @@
1
+ module Rigor
2
+ module Cache
3
+ # Structural interface for the RBS-derived cache producers: a class
4
+ # object that responds to `.fetch(loader:, store:)` and yields the
5
+ # cached (or freshly computed) value. A structural *interface*
6
+ # (duck-typed), not a "protocol" (reserved for ADR-28). Satisfied by
7
+ # `RbsCacheProducer` and every subclass; matches the _Type and
8
+ # _DispatchTier interfaces declared elsewhere in sig/.
9
+ interface _CacheProducer
10
+ def fetch: (loader: untyped, store: untyped) -> untyped
11
+ end
12
+
13
+ # Base owning the shared producer `fetch` wiring; subclasses add a
14
+ # PRODUCER_ID constant and a private `self.compute(loader)`.
15
+ class RbsCacheProducer
16
+ def self.fetch: (loader: untyped, store: untyped) -> untyped
17
+ end
18
+ end
19
+ end
@@ -58,10 +58,8 @@ module Rigor
58
58
  def rbs_module?: (String | Symbol name) -> bool
59
59
  def instance_definition: (String | Symbol class_name) -> untyped?
60
60
  def instance_method: (class_name: String | Symbol, method_name: String | Symbol) -> untyped?
61
- def uncached_instance_definition: (String | Symbol class_name) -> untyped?
62
61
  def singleton_definition: (String | Symbol class_name) -> untyped?
63
62
  def singleton_method: (class_name: String | Symbol, method_name: String | Symbol) -> untyped?
64
- def uncached_singleton_definition: (String | Symbol class_name) -> untyped?
65
63
  def class_type_param_names: (String | Symbol class_name) -> Array[Symbol]
66
64
  def class_ordering: (String | Symbol lhs, String | Symbol rhs) -> ordering
67
65
  def constant_type: (String name) -> Type::t?
@@ -57,6 +57,28 @@ module Rigor
57
57
  module MethodDispatcher
58
58
  def self?.dispatch: (receiver_type: Type::t?, method_name: Symbol, arg_types: Array[Type::t], ?block_type: Type::t?, ?environment: Environment?) -> Type::t?
59
59
  def self?.expected_block_param_types: (receiver_type: Type::t?, method_name: Symbol, arg_types: Array[Type::t], ?environment: Environment?) -> Array[Type::t]
60
+
61
+ # Immutable value object threaded through every dispatch tier.
62
+ class CallContext
63
+ attr_reader receiver: Type::t?
64
+ attr_reader method_name: Symbol
65
+ attr_reader args: Array[Type::t]
66
+ attr_reader block_type: Type::t?
67
+ attr_reader environment: Environment?
68
+ attr_reader call_node: untyped
69
+ attr_reader scope: untyped
70
+ attr_reader self_type_override: Type::t?
71
+ attr_reader public_only: bool
72
+
73
+ def self.build: (receiver: Type::t?, method_name: Symbol, args: Array[Type::t], ?block_type: Type::t?, ?environment: Environment?, ?call_node: untyped, ?scope: untyped, ?self_type_override: Type::t?, ?public_only: bool) -> CallContext
74
+ def with: (**untyped) -> CallContext
75
+ end
76
+
77
+ # The interface every dispatch tier observes: fold one call site,
78
+ # returning a `Type::t` or nil to defer to the next tier.
79
+ interface _DispatchTier
80
+ def try_dispatch: (CallContext) -> Type::t?
81
+ end
60
82
  end
61
83
 
62
84
  class MethodParameterBinder
@@ -87,6 +109,9 @@ module Rigor
87
109
  def self?.narrow_not_class: (Type::t type, String class_name, ?exact: bool, ?environment: Environment) -> Type::t
88
110
  def self?.narrow_not_refinement: (Type::t current_type, Type::t refinement_type) -> Type::t
89
111
  def self?.narrow_for_fact: (Type::t current, untyped fact, untyped environment) -> Type::t
112
+ def self?.predicate_certainty: (Type::t? type) -> (:truthy | :falsey | nil)
113
+ def self?.class_pattern_certainty: (Type::t subject_type, String class_name, environment: Environment) -> (:yes | :no | :maybe)
114
+ def self?.value_pattern_certainty: (Type::t subject_type, untyped pattern_value) -> (:yes | :no | :maybe)
90
115
  def self?.predicate_scopes: (untyped node, Scope scope) -> [Scope, Scope]
91
116
  def self?.case_when_scopes: (untyped subject, Array[untyped] conditions, Scope scope) -> [Scope, Scope]
92
117
  def self?.analyse: (untyped node, Scope scope) -> untyped
@@ -95,6 +120,8 @@ module Rigor
95
120
  def self?.trusted_equality_literal?: (untyped literal) -> bool
96
121
  def self?.falsey_value?: (untyped value) -> bool
97
122
  def self?.falsey_nominal?: (Type::Nominal nominal) -> bool
123
+
124
+ VALUE_EQUALITY_CLASSES: Array[Class]
98
125
  end
99
126
 
100
127
  module ClosureEscapeAnalyzer
@@ -23,7 +23,7 @@ class Rigor::Plugin::Base
23
23
  def self.node_file_context: () { (untyped root, untyped scope) -> untyped } -> untyped
24
24
  def self.node_file_context_block: () -> untyped
25
25
 
26
- def self.dynamic_return: (receivers: Array[String]) { (untyped call_node, untyped scope) -> untyped } -> nil
26
+ def self.dynamic_return: (?receivers: (Array[String] | ^() -> Array[String])?, ?methods: (Array[untyped] | ^() -> Array[untyped])?) { (untyped call_node, untyped scope) -> untyped } -> nil
27
27
  def self.dynamic_returns: () -> Array[untyped]
28
28
 
29
29
  def self.type_specifier: (methods: Array[untyped]) { (untyped call_node, untyped scope) -> untyped } -> nil
@@ -41,7 +41,6 @@ class Rigor::Plugin::Base
41
41
  # Overridable lifecycle / extension hooks (default no-ops).
42
42
  def init: (untyped services) -> nil
43
43
  def prepare: (untyped services) -> nil
44
- def flow_contribution_for: (call_node: untyped, scope: untyped) -> untyped
45
44
  def diagnostics_for_file: (path: untyped, scope: untyped, root: untyped) -> Array[untyped]
46
45
 
47
46
  # Engine-executed dispatch over the declared DSLs.
@@ -45,6 +45,8 @@ module Rigor
45
45
 
46
46
  def self?.read_flow_contribution: (untyped method_def) -> untyped?
47
47
 
48
+ def self?.parse_conforms_to_annotation: (String? string) -> String?
49
+
48
50
  class ParamOverride
49
51
  attr_reader param_name: Symbol
50
52
  attr_reader type: Type::t
data/sig/rigor/scope.rbs CHANGED
@@ -4,25 +4,52 @@ module Rigor
4
4
  attr_reader locals: Hash[Symbol, Type::t]
5
5
  attr_reader fact_store: Analysis::FactStore
6
6
  attr_reader self_type: Type::t?
7
- attr_reader declared_types: Hash[untyped, Type::t]
8
7
  attr_reader ivars: Hash[Symbol, Type::t]
9
8
  attr_reader cvars: Hash[Symbol, Type::t]
10
9
  attr_reader globals: Hash[Symbol, Type::t]
11
- attr_reader class_ivars: Hash[String, Hash[Symbol, Type::t]]
12
- attr_reader class_cvars: Hash[String, Hash[Symbol, Type::t]]
13
- attr_reader program_globals: Hash[Symbol, Type::t]
14
- attr_reader discovered_classes: Hash[String, Type::Singleton]
15
- attr_reader in_source_constants: Hash[String, Type::t]
16
- attr_reader discovered_methods: Hash[String, Hash[Symbol, Symbol]]
17
- attr_reader discovered_def_nodes: Hash[String, Hash[Symbol, untyped]]
18
- attr_reader discovered_def_sources: Hash[String, Hash[Symbol, String]]
19
- attr_reader discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]]
20
- attr_reader discovered_superclasses: Hash[String, String]
21
- attr_reader discovered_includes: Hash[String, Array[String]]
10
+ attr_reader discovery: DiscoveryIndex
22
11
  attr_reader indexed_narrowings: Hash[IndexedKey, Type::t]
23
12
  attr_reader method_chain_narrowings: Hash[ChainKey, Type::t]
24
13
  attr_reader source_path: String?
25
14
 
15
+ # ADR-53 Track A — the seed-time discovery tables live on the
16
+ # DiscoveryIndex; Scope keeps per-table readers as delegates.
17
+ def declared_types: () -> Hash[untyped, Type::t]
18
+ def class_ivars: () -> Hash[String, Hash[Symbol, Type::t]]
19
+ def class_cvars: () -> Hash[String, Hash[Symbol, Type::t]]
20
+ def program_globals: () -> Hash[Symbol, Type::t]
21
+ def discovered_classes: () -> Hash[String, Type::Singleton]
22
+ def in_source_constants: () -> Hash[String, Type::t]
23
+ def discovered_methods: () -> Hash[String, Hash[Symbol, Symbol]]
24
+ def discovered_def_nodes: () -> Hash[String, Hash[Symbol, untyped]]
25
+ def discovered_def_sources: () -> Hash[String, Hash[Symbol, String]]
26
+ def discovered_method_visibilities: () -> Hash[String, Hash[Symbol, Symbol]]
27
+ def discovered_superclasses: () -> Hash[String, String]
28
+ def discovered_includes: () -> Hash[String, Array[String]]
29
+ def discovered_class_sources: () -> Hash[String, Set[String]]
30
+ def data_member_layouts: () -> Hash[String, Array[Symbol]]
31
+
32
+ class DiscoveryIndex
33
+ attr_reader declared_types: Hash[untyped, Type::t]
34
+ attr_reader class_ivars: Hash[String, Hash[Symbol, Type::t]]
35
+ attr_reader class_cvars: Hash[String, Hash[Symbol, Type::t]]
36
+ attr_reader program_globals: Hash[Symbol, Type::t]
37
+ attr_reader discovered_classes: Hash[String, Type::Singleton]
38
+ attr_reader in_source_constants: Hash[String, Type::t]
39
+ attr_reader discovered_methods: Hash[String, Hash[Symbol, Symbol]]
40
+ attr_reader discovered_def_nodes: Hash[String, Hash[Symbol, untyped]]
41
+ attr_reader discovered_def_sources: Hash[String, Hash[Symbol, String]]
42
+ attr_reader discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]]
43
+ attr_reader discovered_superclasses: Hash[String, String]
44
+ attr_reader discovered_includes: Hash[String, Array[String]]
45
+ attr_reader discovered_class_sources: Hash[String, Set[String]]
46
+ attr_reader data_member_layouts: Hash[String, Array[Symbol]]
47
+
48
+ EMPTY: DiscoveryIndex
49
+
50
+ def with: (?declared_types: Hash[untyped, Type::t], ?class_ivars: Hash[String, Hash[Symbol, Type::t]], ?class_cvars: Hash[String, Hash[Symbol, Type::t]], ?program_globals: Hash[Symbol, Type::t], ?discovered_classes: Hash[String, Type::Singleton], ?in_source_constants: Hash[String, Type::t], ?discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?discovered_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]], ?discovered_superclasses: Hash[String, String], ?discovered_includes: Hash[String, Array[String]], ?discovered_class_sources: Hash[String, Set[String]], ?data_member_layouts: Hash[String, Array[Symbol]]) -> DiscoveryIndex
51
+ end
52
+
26
53
  class IndexedKey
27
54
  attr_reader receiver_kind: Symbol
28
55
  attr_reader receiver_name: Symbol
@@ -37,8 +64,9 @@ module Rigor
37
64
 
38
65
  def self.empty: (?environment: Environment, ?source_path: String?) -> Scope
39
66
 
40
- def initialize: (environment: Environment, locals: Hash[Symbol, Type::t], ?fact_store: Analysis::FactStore, ?self_type: Type::t?, ?declared_types: Hash[untyped, Type::t], ?ivars: Hash[Symbol, Type::t], ?cvars: Hash[Symbol, Type::t], ?globals: Hash[Symbol, Type::t], ?source_path: String?) -> void
67
+ def initialize: (environment: Environment, locals: Hash[Symbol, Type::t], ?fact_store: Analysis::FactStore, ?self_type: Type::t?, ?ivars: Hash[Symbol, Type::t], ?cvars: Hash[Symbol, Type::t], ?globals: Hash[Symbol, Type::t], ?discovery: DiscoveryIndex, ?source_path: String?) -> void
41
68
  def with_source_path: (String? path) -> Scope
69
+ def with_discovery: (DiscoveryIndex index) -> Scope
42
70
  def local: (String | Symbol name) -> Type::t?
43
71
  def ivar: (String | Symbol name) -> Type::t?
44
72
  def cvar: (String | Symbol name) -> Type::t?
@@ -48,26 +76,16 @@ module Rigor
48
76
  def with_cvar: (String | Symbol name, Type::t type) -> Scope
49
77
  def with_global: (String | Symbol name, Type::t type) -> Scope
50
78
  def class_ivars_for: (String | Symbol? class_name) -> Hash[Symbol, Type::t]
51
- def with_class_ivars: (Hash[String, Hash[Symbol, Type::t]] table) -> Scope
52
79
  def class_cvars_for: (String | Symbol? class_name) -> Hash[Symbol, Type::t]
53
- def with_class_cvars: (Hash[String, Hash[Symbol, Type::t]] table) -> Scope
54
- def with_program_globals: (Hash[Symbol, Type::t] table) -> Scope
55
- def with_discovered_classes: (Hash[String, Type::Singleton] table) -> Scope
56
- def with_in_source_constants: (Hash[String, Type::t] table) -> Scope
57
- def with_discovered_methods: (Hash[String, Hash[Symbol, Symbol]] table) -> Scope
58
80
  def discovered_method?: (String | Symbol class_name, String | Symbol method_name, Symbol kind) -> bool
59
- def with_discovered_def_nodes: (Hash[String, Hash[Symbol, untyped]] table) -> Scope
60
- def with_discovered_def_sources: (Hash[String, Hash[Symbol, String]] table) -> Scope
61
81
  def user_def_for: (String | Symbol class_name, String | Symbol method_name) -> untyped?
62
82
  def user_def_site_for: (String | Symbol class_name, String | Symbol method_name) -> String?
63
83
  def top_level_def_for: (String | Symbol method_name) -> untyped?
64
84
  def toplevel?: () -> bool
65
- def with_discovered_method_visibilities: (Hash[String, Hash[Symbol, Symbol]] table) -> Scope
66
85
  def discovered_method_visibility: (String | Symbol class_name, String | Symbol method_name) -> Symbol?
67
86
  def superclass_of: (String | Symbol class_name) -> String?
68
- def with_discovered_superclasses: (Hash[String, String] table) -> Scope
87
+ def data_member_layout: (String | Symbol class_name) -> Array[Symbol]?
69
88
  def includes_of: (String | Symbol class_name) -> Array[String]
70
- def with_discovered_includes: (Hash[String, Array[String]] table) -> Scope
71
89
  def indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key) -> Type::t?
72
90
  def with_indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key, Type::t type) -> Scope
73
91
  def without_indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key) -> Scope
@@ -78,7 +96,6 @@ module Rigor
78
96
  def without_method_chain_narrowings_for: (Symbol receiver_kind, String | Symbol receiver_name) -> Scope
79
97
  def with_fact: (Analysis::FactStore::Fact fact) -> Scope
80
98
  def with_self_type: (Type::t? type) -> Scope
81
- def with_declared_types: (Hash[untyped, Type::t] table) -> Scope
82
99
  def facts_for: (?target: Analysis::FactStore::Target?, ?bucket: Symbol?) -> Array[Analysis::FactStore::Fact]
83
100
  def local_facts: (String | Symbol name, ?bucket: Symbol?) -> Array[Analysis::FactStore::Fact]
84
101
  def type_of: (untyped node, ?tracer: Inference::FallbackTracer?) -> Type::t
data/sig/rigor/source.rbs CHANGED
@@ -16,6 +16,7 @@ module Rigor
16
16
  def self?.symbol_or_string_name: (untyped? node) -> String?
17
17
  def self?.symbol: (untyped? node) -> Symbol?
18
18
  def self?.symbol_name: (untyped? node) -> String?
19
+ def self?.symbol_named?: (untyped? node, String name) -> bool
19
20
  def self?.symbol_arguments: (untyped? call_node) -> Array[Symbol]
20
21
  def self?.symbol_arg: (untyped? call_node, Integer index) -> Symbol?
21
22
  end
data/sig/rigor/type.rbs CHANGED
@@ -1,9 +1,32 @@
1
1
  module Rigor
2
2
  module Type
3
- type t = Top | Bot | Dynamic | Constant | IntegerRange | Nominal | Singleton | Union | Difference | Tuple | HashShape
3
+ type t = Top | Bot | Dynamic | Constant | IntegerRange | Nominal | Singleton | Union | Difference | Tuple | HashShape | DataClass | DataInstance
4
4
 
5
5
  type accepts_mode = :strict | :gradual | :loose
6
6
 
7
+ # The structural interface every `Type::*` carrier satisfies — the
8
+ # internal type-object API (see
9
+ # docs/internal-spec/internal-type-api.md). A structural *interface*
10
+ # (duck-typed: satisfied by having the methods, no `implements`
11
+ # clause), not a "protocol" — that word is reserved for ADR-28
12
+ # path-scoped protocol contracts. The closed `type t` union above is
13
+ # what the engine threads day-to-day; this records the shared
14
+ # per-carrier method contract in one place. Carriers supply the
15
+ # identity trio via `Rigor::ValueSemantics` and `accepts` via
16
+ # `Rigor::Type::AcceptanceRouter`.
17
+ interface _Type
18
+ def describe: (?Symbol verbosity) -> String
19
+ def erase_to_rbs: () -> String
20
+ def top: () -> Trinary
21
+ def bot: () -> Trinary
22
+ def dynamic: () -> Trinary
23
+ def accepts: (Type::t other, ?mode: accepts_mode) -> AcceptsResult
24
+ def ==: (untyped other) -> bool
25
+ def eql?: (untyped other) -> bool
26
+ def hash: () -> Integer
27
+ def inspect: () -> String
28
+ end
29
+
7
30
  class Top
8
31
  def self.instance: () -> Top
9
32
  def describe: (?Symbol verbosity) -> String
@@ -222,6 +245,38 @@ module Rigor
222
245
  def inspect: () -> String
223
246
  end
224
247
 
248
+ class DataClass
249
+ attr_reader members: Array[Symbol]
250
+ attr_reader class_name: String?
251
+ def initialize: (Array[Symbol] members, ?String? class_name) -> void
252
+ def describe: (?Symbol verbosity) -> String
253
+ def erase_to_rbs: () -> String
254
+ def top: () -> Trinary
255
+ def bot: () -> Trinary
256
+ def dynamic: () -> Trinary
257
+ def accepts: (Type::t other, ?mode: accepts_mode) -> AcceptsResult
258
+ def ==: (untyped other) -> bool
259
+ def hash: () -> Integer
260
+ def inspect: () -> String
261
+ end
262
+
263
+ class DataInstance
264
+ attr_reader members: Hash[Symbol, Type::t]
265
+ attr_reader class_name: String?
266
+ def initialize: (Hash[Symbol, Type::t] members, ?String? class_name) -> void
267
+ def member_names: () -> Array[Symbol]
268
+ def member_type: (Symbol name) -> Type::t?
269
+ def describe: (?Symbol verbosity) -> String
270
+ def erase_to_rbs: () -> String
271
+ def top: () -> Trinary
272
+ def bot: () -> Trinary
273
+ def dynamic: () -> Trinary
274
+ def accepts: (Type::t other, ?mode: accepts_mode) -> AcceptsResult
275
+ def ==: (untyped other) -> bool
276
+ def hash: () -> Integer
277
+ def inspect: () -> String
278
+ end
279
+
225
280
  class AcceptsResult
226
281
  attr_reader trinary: Trinary
227
282
  attr_reader mode: accepts_mode
@@ -282,6 +337,8 @@ module Rigor
282
337
  def self?.universal_int: () -> IntegerRange
283
338
  def self?.tuple_of: (*Type::t elements) -> Tuple
284
339
  def self?.hash_shape_of: (?Hash[untyped, Type::t]? pairs, **untyped options) -> HashShape
340
+ def self?.data_class_of: (members: Array[Symbol], ?class_name: String?) -> DataClass
341
+ def self?.data_instance_of: (members: Hash[Symbol, Type::t], ?class_name: String?) -> DataInstance
285
342
  def self?.union: (*Type::t types) -> Type::t
286
343
  def self?.key_of: (Type::t type) -> Type::t
287
344
  def self?.value_of: (Type::t type) -> Type::t
data/sig/rigor.rbs CHANGED
@@ -113,8 +113,13 @@ module Rigor
113
113
  attr_reader cache_store: untyped
114
114
  attr_reader plugin_registry: untyped
115
115
  attr_reader buffer: untyped
116
- def initialize: (configuration: Configuration, ?explain: bool, ?cache_store: untyped, ?plugin_requirer: untyped, ?workers: Integer, ?collect_stats: bool, ?buffer: untyped, ?prebuilt: untyped, ?environment: untyped) -> void
116
+ attr_reader file_dependencies: Hash[String, untyped]
117
+ attr_reader analyzed_files: Array[String]
118
+ def initialize: (configuration: Configuration, ?explain: bool, ?cache_store: untyped, ?plugin_requirer: untyped, ?workers: Integer, ?collect_stats: bool, ?buffer: untyped, ?prebuilt: untyped, ?environment: untyped, ?record_dependencies: bool, ?analyze_only: untyped) -> void
117
119
  def run: (?Array[String] paths) -> Result
120
+ def run_source: (source: String, ?path: String) -> Result
121
+ def analysis_file_set: (?Array[String] paths) -> Array[String]
122
+ def file_dependents: () -> Hash[String, untyped]
118
123
  def prepare_project_scan: (?paths: Array[String]) -> untyped
119
124
  end
120
125
  end