rigortype 0.2.4 → 0.2.6

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/docs/handbook/09-plugins.md +5 -2
  3. data/docs/handbook/appendix-liskov.md +5 -3
  4. data/docs/handbook/appendix-phpstan.md +2 -2
  5. data/docs/install.md +1 -1
  6. data/docs/manual/02-cli-reference.md +58 -1
  7. data/docs/manual/06-baseline.md +12 -0
  8. data/docs/manual/11-ci.md +6 -6
  9. data/docs/manual/15-type-protection-coverage.md +29 -0
  10. data/docs/manual/plugins/rigor-minitest.md +1 -1
  11. data/docs/manual/plugins/rigor-rails-i18n.md +22 -3
  12. data/lib/rigor/analysis/incremental_session.rb +7 -2
  13. data/lib/rigor/cli/check_command.rb +4 -33
  14. data/lib/rigor/cli/check_runner_factory.rb +63 -0
  15. data/lib/rigor/cli/doctor_command.rb +295 -0
  16. data/lib/rigor/cli/plugins_command.rb +2 -2
  17. data/lib/rigor/cli/plugins_renderer.rb +1 -1
  18. data/lib/rigor/cli/protection_renderer.rb +32 -2
  19. data/lib/rigor/cli/protection_report.rb +32 -6
  20. data/lib/rigor/cli/upgrade_command.rb +25 -0
  21. data/lib/rigor/cli.rb +17 -1
  22. data/lib/rigor/flow_contribution/fact.rb +1 -1
  23. data/lib/rigor/inference/dynamic_origin.rb +67 -0
  24. data/lib/rigor/inference/expression_typer.rb +22 -10
  25. data/lib/rigor/inference/fallback.rb +2 -2
  26. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +16 -0
  27. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +41 -2
  28. data/lib/rigor/inference/method_dispatcher.rb +19 -4
  29. data/lib/rigor/inference/mutation_widening.rb +18 -0
  30. data/lib/rigor/inference/protection_scanner.rb +6 -3
  31. data/lib/rigor/inference/statement_evaluator.rb +5 -4
  32. data/lib/rigor/plugin/base.rb +34 -7
  33. data/lib/rigor/plugin/registry.rb +1 -1
  34. data/lib/rigor/scope.rb +16 -5
  35. data/lib/rigor/version.rb +1 -1
  36. data/lib/rigor.rb +1 -0
  37. data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +1 -1
  38. data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +1 -1
  39. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +52 -0
  40. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +123 -8
  41. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +1 -1
  42. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +3 -3
  43. data/sig/rigor/plugin/base.rbs +2 -0
  44. data/sig/rigor/scope.rbs +3 -1
  45. data/skills/rigor-plugin-author/SKILL.md +8 -5
  46. data/skills/rigor-plugin-author/references/02-walker-and-types.md +8 -4
  47. metadata +27 -3
@@ -26,6 +26,7 @@ module Rigor
26
26
  # config:
27
27
  # locale_search_paths: ["config/locales"] # default; optional
28
28
  # configured_locales: ["en"] # default; optional — locales the project ships
29
+ # view_search_paths: ["app/views"] # default; optional — view template search roots
29
30
  #
30
31
  # ## What it checks
31
32
  #
@@ -39,6 +40,11 @@ module Rigor
39
40
  # `%{var}` placeholders must match the call's keyword
40
41
  # arguments. Missing placeholders are errors; extra
41
42
  # arguments are warnings.
43
+ # 4. **View template lazy keys** — `t('.title')` inside
44
+ # `app/views/setting/index.html.erb` expands to
45
+ # `setting.index.title` and is validated against the
46
+ # locale index. ERB, Haml, and Slim templates are
47
+ # scanned under `view_search_paths`.
42
48
  #
43
49
  # ## Limitations
44
50
  #
@@ -51,6 +57,16 @@ module Rigor
51
57
  # Lazy keys in non-controller `.rb` files (models, helpers,
52
58
  # mailers, …) are silently skipped — the controller/action
53
59
  # scope cannot be statically determined there.
60
+ # - View template lazy keys (`t('.key')` inside ERB / Haml /
61
+ # Slim) are validated for key existence and per-locale
62
+ # coverage. Interpolation variable validation is skipped
63
+ # for view templates (the hash may come from controller
64
+ # instance variables not visible in the template).
65
+ # The view scan is a project-wide pass surfaced through the
66
+ # per-file diagnostic hook, so under `--workers` each
67
+ # fork-pool worker re-emits the full set (the same
68
+ # once-per-run limitation the `load-error` path carries);
69
+ # sequential `rigor check` is unaffected.
54
70
  # - Pluralization (`t('errors.messages.too_short',
55
71
  # count: n)`) is recognised at the call site but the
56
72
  # `count` key is not used to validate the locale's
@@ -61,14 +77,15 @@ module Rigor
61
77
  class RailsI18n < Rigor::Plugin::Base
62
78
  manifest(
63
79
  id: "rails-i18n",
64
- # Bumped 2026-05-28skip `unknown-key` on Rails / rails-
65
- # i18n shipped defaults (`date.order`, `time.am`,
66
- # `support.array.*`, `errors.format`, …).
67
- version: "0.2.0",
80
+ # Bumped 2026-06-23view template lazy-key scanning
81
+ # (`t('.key')` inside ERB / Haml / Slim under
82
+ # `view_search_paths`).
83
+ version: "0.3.0",
68
84
  description: "Validates I18n `t(key)` calls against `config/locales/*.yml`.",
69
85
  config_schema: {
70
86
  "locale_search_paths" => { kind: :array, default: ["config/locales"] },
71
- "configured_locales" => { kind: :array, default: ["en"] }
87
+ "configured_locales" => { kind: :array, default: ["en"] },
88
+ "view_search_paths" => { kind: :array, default: ["app/views"] }
72
89
  }
73
90
  )
74
91
 
@@ -88,22 +105,49 @@ module Rigor
88
105
  index
89
106
  end
90
107
 
108
+ # Scans view templates under `view_search_paths` for lazy
109
+ # `t('.key')` / `I18n.translate('.key')` calls and validates
110
+ # each expanded key against the locale index. Interpolation
111
+ # validation is skipped — the hash may come from controller
112
+ # instance variables not visible in the template source.
113
+ #
114
+ # Watches `**/*.{erb,haml,slim}` under each search root so
115
+ # the cache invalidates when templates are edited.
116
+ producer :view_diagnostics, watch: -> { [[@view_search_paths, "**/*.erb", "**/*.haml", "**/*.slim"]] } do |_params|
117
+ index = producer_value(:locale_index)
118
+ next [] if index.nil? || index.empty?
119
+
120
+ scan_view_files(index)
121
+ end
122
+
91
123
  def init(_services)
92
124
  @locale_search_paths = Array(config.fetch("locale_search_paths")).map(&:to_s)
125
+ @view_search_paths = Array(config.fetch("view_search_paths")).map(&:to_s)
93
126
  @configured_locales = Array(config.fetch("configured_locales")).map(&:to_s)
94
127
  @load_errors = []
95
128
  @load_errors_emitted = false
129
+ @view_diagnostics_emitted = false
96
130
  end
97
131
 
98
132
  # File-level only: the once-per-run YAML load errors + the
99
- # runtime (cache-load) error. Per-call `t('key')` validation runs
100
- # over the engine-owned walk via the node_rule below (ADR-37). The
101
- # locale index is lazily loaded + memoised by `producer_value`.
133
+ # runtime (cache-load) error + the view-template scan. Per-call
134
+ # `t('key')` validation runs over the engine-owned walk via the
135
+ # node_rule below (ADR-37). The locale index and view diagnostics
136
+ # are lazily loaded + memoised by `producer_value`.
102
137
  def diagnostics_for_file(path:, scope:, root:) # rubocop:disable Lint/UnusedMethodArgument
103
138
  index = producer_value(:locale_index)
104
139
  diagnostics = []
105
140
  diagnostics.concat(consume_load_error_diagnostics(path)) unless @load_errors.empty?
106
141
  diagnostics << runtime_error_diagnostic(path) if index.nil? && producer_error(:locale_index)
142
+ unless @view_diagnostics_emitted
143
+ view_diags = producer_value(:view_diagnostics) || []
144
+ if (view_err = producer_error(:view_diagnostics))
145
+ diagnostics << view_runtime_error_diagnostic(path, view_err)
146
+ else
147
+ diagnostics.concat(view_diags)
148
+ end
149
+ @view_diagnostics_emitted = true
150
+ end
107
151
  diagnostics
108
152
  end
109
153
 
@@ -126,6 +170,68 @@ module Rigor
126
170
 
127
171
  private
128
172
 
173
+ def scan_view_files(index)
174
+ view_files.flat_map do |view_path|
175
+ scan_view_file(view_path, index)
176
+ end
177
+ end
178
+
179
+ def scan_view_file(view_path, index)
180
+ content = read_view_template(view_path) or return []
181
+ scope = Analyzer.view_scope_from_path(view_path) or return []
182
+
183
+ display_path = relative_view_path(view_path)
184
+ Analyzer.extract_lazy_keys_from_erb(content).flat_map do |key|
185
+ full_key = "#{scope}.#{key}"
186
+ Analyzer.validate_view_key(
187
+ full_key, locale_index: index, configured_locales: @configured_locales
188
+ ).map { |v| view_diagnostic(display_path, v) }
189
+ end
190
+ rescue StandardError => e
191
+ [Rigor::Analysis::Diagnostic.new(
192
+ path: relative_view_path(view_path), line: 1, column: 1,
193
+ message: "rigor-rails-i18n: failed to scan view template: #{e.class}: #{e.message}",
194
+ severity: :warning,
195
+ rule: "load-error"
196
+ )]
197
+ end
198
+
199
+ def view_files
200
+ @view_search_paths.flat_map do |root|
201
+ absolute = File.expand_path(root)
202
+ next [] unless File.directory?(absolute)
203
+
204
+ Dir.glob(File.join(absolute, "**", "*.{erb,haml,slim}"))
205
+ end.sort
206
+ end
207
+
208
+ # Diagnostics anchor on a path relative to the working
209
+ # directory — the same base `File.expand_path` globbed the
210
+ # view files against — so view diagnostics render and match
211
+ # baselines like every other diagnostic (which carry
212
+ # project-relative paths). Falls back to the absolute path
213
+ # for a view outside the working tree.
214
+ def relative_view_path(absolute_path)
215
+ Pathname.new(absolute_path).relative_path_from(Pathname.pwd).to_s
216
+ rescue ArgumentError
217
+ absolute_path
218
+ end
219
+
220
+ def read_view_template(path)
221
+ io_boundary.read_file(path)
222
+ rescue Plugin::AccessDeniedError
223
+ nil
224
+ end
225
+
226
+ def view_diagnostic(view_path, violation)
227
+ Rigor::Analysis::Diagnostic.new(
228
+ path: view_path, line: 1, column: 1,
229
+ message: violation.message,
230
+ severity: violation.severity,
231
+ rule: violation.rule
232
+ )
233
+ end
234
+
129
235
  # The runner only invokes `diagnostics_for_file` for
130
236
  # Ruby files (`paths:` is filtered to `.rb`). YAML
131
237
  # parse errors therefore can't be anchored on the
@@ -155,6 +261,15 @@ module Rigor
155
261
  rule: "load-error"
156
262
  )
157
263
  end
264
+
265
+ def view_runtime_error_diagnostic(path, error)
266
+ Rigor::Analysis::Diagnostic.new(
267
+ path: path, line: 1, column: 1,
268
+ message: "rigor-rails-i18n: failed to scan view templates: #{error.class}: #{error.message}",
269
+ severity: :warning,
270
+ rule: "load-error"
271
+ )
272
+ end
158
273
  end
159
274
 
160
275
  Rigor::Plugin.register(RailsI18n)
@@ -110,7 +110,7 @@ module Rigor
110
110
  # ADR-37 slice 2 — matcher narrowing
111
111
  # (`expect(x).to be_a(T)` → `post_return_facts` on `x`),
112
112
  # method-gated by the engine on the expectation verbs.
113
- type_specifier methods: %i[to not_to to_not] do |call_node, scope|
113
+ narrowing_facts methods: %i[to not_to to_not] do |call_node, scope|
114
114
  MatcherAnalyzer.contribution_for(call_node, environment: scope&.environment)&.post_return_facts
115
115
  end
116
116
 
@@ -169,13 +169,13 @@ module Rigor
169
169
  end
170
170
 
171
171
  # ADR-52 slice 4 — `T.bind(self, T)`'s self-narrowing fact,
172
- # contributed via the method-gated `type_specifier` DSL. The
172
+ # contributed via the method-gated `narrowing_facts` DSL. The
173
173
  # statement evaluator consults this path for narrowing facts.
174
174
  # The return-type half (`Constant[nil]`) flows through the
175
175
  # `dynamic_return` rule above; the block re-checks the `T.`
176
176
  # receiver via the recogniser, so an unrelated `bind` call
177
177
  # contributes nothing.
178
- type_specifier methods: [:bind] do |call_node, scope|
178
+ narrowing_facts methods: [:bind] do |call_node, scope|
179
179
  bind_post_return_facts(call_node, scope)
180
180
  end
181
181
 
@@ -258,7 +258,7 @@ module Rigor
258
258
  lookup_signature(call_node, scope)&.return_type
259
259
  end
260
260
 
261
- # The `type_specifier` body for `T.bind` — same sigil gate as
261
+ # The `narrowing_facts` body for `T.bind` — same sigil gate as
262
262
  # the return-type path, then the recogniser's
263
263
  # `post_return_facts` (the `Fact(target_kind: :self)` that
264
264
  # narrows `scope.self_type` for the rest of the block).
@@ -26,6 +26,8 @@ class Rigor::Plugin::Base
26
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
+ def self.narrowing_facts: (methods: Array[untyped]) { (untyped call_node, untyped scope) -> untyped } -> nil
30
+ # Deprecating alias for `narrowing_facts` (ADR-80); removed in 0.3.0.
29
31
  def self.type_specifier: (methods: Array[untyped]) { (untyped call_node, untyped scope) -> untyped } -> nil
30
32
  def self.type_specifiers: () -> Array[untyped]
31
33
 
data/sig/rigor/scope.rbs CHANGED
@@ -8,6 +8,7 @@ module Rigor
8
8
  attr_reader cvars: Hash[Symbol, Type::t]
9
9
  attr_reader globals: Hash[Symbol, Type::t]
10
10
  attr_reader discovery: DiscoveryIndex
11
+ attr_reader dynamic_origins: Hash[untyped, Symbol]
11
12
  attr_reader indexed_narrowings: Hash[IndexedKey, Type::t]
12
13
  attr_reader method_chain_narrowings: Hash[ChainKey, Type::t]
13
14
  attr_reader source_path: String?
@@ -32,6 +33,7 @@ module Rigor
32
33
  def data_member_layouts: () -> Hash[String, Array[Symbol]]
33
34
  def struct_member_layouts: () -> Hash[String, { members: Array[Symbol], keyword_init: bool }]
34
35
  def param_inferred_types: () -> Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]]
36
+ def record_dynamic_origin: (untyped node, Symbol cause) -> Scope
35
37
 
36
38
  class DiscoveryIndex
37
39
  attr_reader declared_types: Hash[untyped, Type::t]
@@ -71,7 +73,7 @@ module Rigor
71
73
 
72
74
  def self.empty: (?environment: Environment, ?source_path: String?) -> Scope
73
75
 
74
- 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
76
+ 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?, ?dynamic_origins: Hash[untyped, Symbol]) -> void
75
77
  def with_source_path: (String? path) -> Scope
76
78
  def with_struct_fold_safe: (Set[Symbol] locals) -> Scope
77
79
  def struct_fold_safe?: (String | Symbol name) -> bool
@@ -97,19 +97,22 @@ AST walk per file — hands every matching node to the block along with a
97
97
  `scope` it can query for inferred types. The block returns an array of
98
98
  `Rigor::Analysis::Diagnostic` (built via the `diagnostic` helper).
99
99
  Optionally the plugin also declares `dynamic_return(receivers:)` /
100
- `type_specifier(methods:)` to *supply* a return type or narrowing facts
101
- for call sites the core analyzer types as `Dynamic`. `#diagnostics_for_file`
100
+ `narrowing_facts(methods:)` to *supply* a return type or narrowing facts
101
+ for call sites the core analyzer types as `Dynamic`. (`narrowing_facts`
102
+ was renamed from `type_specifier` in ADR-80; `type_specifier` remains as a
103
+ deprecating alias removed in 0.3.0 — use `narrowing_facts` in new plugins.)
104
+ `#diagnostics_for_file`
102
105
  is the file-rule surface for whole-file diagnostics a per-node walk can't
103
106
  express. (`flow_contribution_for` was removed pre-1.0 in ADR-52 WD3 —
104
107
  defining it now raises `ArgumentError`; use `dynamic_return` /
105
- `type_specifier`. See Phase 2.)
108
+ `narrowing_facts`. See Phase 2.)
106
109
 
107
110
  ## Phase outline
108
111
 
109
112
  | Phase | What | Reference |
110
113
  | --- | --- | --- |
111
114
  | 1 | Package and scaffold — gem vs project-private layout, gemspec / Gemfile, the plugin class skeleton, `.rigor.yml` activation. | [`references/01-plan-and-scaffold.md`](references/01-plan-and-scaffold.md) |
112
- | 2 | Node rules — `node_rule` (engine-owned walk), building `Diagnostic`s via `Base#diagnostic`, querying `scope.type_of`, calling the target library directly instead of reimplementing it (ADR-39: `Plugin::Inflector`, `Base.suggest`), optional `dynamic_return` / `type_specifier`, RBS for the DSL. | [`references/02-walker-and-types.md`](references/02-walker-and-types.md) |
115
+ | 2 | Node rules — `node_rule` (engine-owned walk), building `Diagnostic`s via `Base#diagnostic`, querying `scope.type_of`, calling the target library directly instead of reimplementing it (ADR-39: `Plugin::Inflector`, `Base.suggest`), optional `dynamic_return` / `narrowing_facts`, RBS for the DSL. | [`references/02-walker-and-types.md`](references/02-walker-and-types.md) |
113
116
  | 3 | Test and ship — fixture-based tests (RSpec / Minitest, no rigor internals), version pinning, README, publish or keep private. | [`references/03-test-and-ship.md`](references/03-test-and-ship.md) |
114
117
 
115
118
  ## Reading order — modules
@@ -117,5 +120,5 @@ defining it now raises `ArgumentError`; use `dynamic_return` /
117
120
  | Module | Read | Covers |
118
121
  | --- | --- | --- |
119
122
  | 1 | [`references/01-plan-and-scaffold.md`](references/01-plan-and-scaffold.md) | **Phase 1.** The gem vs project-private packaging split, directory trees for both, gemspec template, project-private path-gem / `RUBYLIB` activation, the `Rigor::Plugin::Base` skeleton, `.rigor.yml` `plugins:` wiring. |
120
- | 2 | [`references/02-walker-and-types.md`](references/02-walker-and-types.md) | **Phase 2.** The `node_rule` engine-owned AST walk over Prism nodes, the `Base#diagnostic` helper, asking the analyzer for inferred types via `scope.type_of`, two-pass / lexical context (`node_file_context` / `NodeContext`), the optional `dynamic_return` / `type_specifier` return-type hooks (`flow_contribution_for` was removed pre-1.0 in ADR-52 WD3), calling the target library's pure methods directly rather than reimplementing them (ADR-39: `Plugin::Inflector` over the real `ActiveSupport::Inflector`; `Base.suggest` for did-you-mean), and shipping `sig/*.rbs` so the DSL's types are visible. |
123
+ | 2 | [`references/02-walker-and-types.md`](references/02-walker-and-types.md) | **Phase 2.** The `node_rule` engine-owned AST walk over Prism nodes, the `Base#diagnostic` helper, asking the analyzer for inferred types via `scope.type_of`, two-pass / lexical context (`node_file_context` / `NodeContext`), the optional `dynamic_return` / `narrowing_facts` return-type hooks (`narrowing_facts` was renamed from `type_specifier` in ADR-80, alias removed in 0.3.0; `flow_contribution_for` was removed pre-1.0 in ADR-52 WD3), calling the target library's pure methods directly rather than reimplementing them (ADR-39: `Plugin::Inflector` over the real `ActiveSupport::Inflector`; `Base.suggest` for did-you-mean), and shipping `sig/*.rbs` so the DSL's types are visible. |
121
124
  | 3 | [`references/03-test-and-ship.md`](references/03-test-and-ship.md) | **Phase 3.** Testing a plugin from outside the monorepo — fixture projects driven through `rigor check --format json`, plus pure unit tests of dispatch tables — with RSpec or Minitest. Version pinning against the pre-1.0 contract. README. Publishing to RubyGems or keeping the plugin private. |
@@ -162,7 +162,7 @@ rather than hand-rolling Levenshtein:
162
162
  Rigor::Plugin::Base.suggest(typo, known_names) # nearest match, or nil
163
163
  ```
164
164
 
165
- ## Optional — contribute a return type with `dynamic_return` / `type_specifier`
165
+ ## Optional — contribute a return type with `dynamic_return` / `narrowing_facts`
166
166
 
167
167
  > **Critical — these hooks do NOT make a method "defined", so they do
168
168
  > NOT suppress `call.undefined-method`.** Method *existence* and call
@@ -197,11 +197,15 @@ end
197
197
  # Post-return NARROWING FACTS, gated on the call's method name.
198
198
  # Return an Array of facts (or nil). Used for assertion / predicate
199
199
  # narrowing (`assert_kind_of(Foo, x)` ⇒ x is Foo afterwards).
200
- type_specifier methods: [:assert_kind_of] do |call_node, scope|
200
+ narrowing_facts methods: [:assert_kind_of] do |call_node, scope|
201
201
  # ... build and return the post-return facts ...
202
202
  end
203
203
  ```
204
204
 
205
+ > **`narrowing_facts` was renamed from `type_specifier` in ADR-80.**
206
+ > `type_specifier` remains as a deprecating alias, removed in 0.3.0 — use
207
+ > `narrowing_facts` in new plugins.
208
+
205
209
  Build return types with `Rigor::Type::Combinator`:
206
210
 
207
211
  ```ruby
@@ -240,7 +244,7 @@ If the DSL introduces methods or classes that Rigor cannot see (a
240
244
  Rigor RBS declaring them so *core* inference — not just your plugin —
241
245
  treats them as **defined**. This is what removes the
242
246
  `call.undefined-method` diagnostics on those methods; nothing else
243
- (not a `node_rule`, not `dynamic_return` / `type_specifier`) makes a
247
+ (not a `node_rule`, not `dynamic_return` / `narrowing_facts`) makes a
244
248
  method exist in Rigor's view.
245
249
 
246
250
  Two ways to wire the RBS, depending on how the plugin is packaged:
@@ -288,6 +292,6 @@ They compose — many plugins ship both.
288
292
 
289
293
  A plugin whose `node_rule`(s) recognise the DSL and emit diagnostics
290
294
  with correct severities and rule ids — optionally a `dynamic_return` /
291
- `type_specifier` and a `sig/` bundle. Verify by eye with `rigor check`;
295
+ `narrowing_facts` and a `sig/` bundle. Verify by eye with `rigor check`;
292
296
  lock it down with tests in Phase 3
293
297
  ([`03-test-and-ship.md`](03-test-and-ship.md)).
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rigortype
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rigor contributors
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 1980-01-01 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: language_server-protocol
@@ -109,6 +109,26 @@ dependencies:
109
109
  - - "<"
110
110
  - !ruby/object:Gem::Version
111
111
  version: '4.0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: binpacker
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: 0.1.0
119
+ - - "<"
120
+ - !ruby/object:Gem::Version
121
+ version: '1.0'
122
+ type: :development
123
+ prerelease: false
124
+ version_requirements: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: 0.1.0
129
+ - - "<"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.0'
112
132
  - !ruby/object:Gem::Dependency
113
133
  name: parallel_tests
114
134
  requirement: !ruby/object:Gem::Requirement
@@ -440,6 +460,7 @@ files:
440
460
  - lib/rigor/cli/annotate_command.rb
441
461
  - lib/rigor/cli/baseline_command.rb
442
462
  - lib/rigor/cli/check_command.rb
463
+ - lib/rigor/cli/check_runner_factory.rb
443
464
  - lib/rigor/cli/ci_detector.rb
444
465
  - lib/rigor/cli/command.rb
445
466
  - lib/rigor/cli/coverage_command.rb
@@ -450,6 +471,7 @@ files:
450
471
  - lib/rigor/cli/diagnostic_formats.rb
451
472
  - lib/rigor/cli/diff_command.rb
452
473
  - lib/rigor/cli/docs_command.rb
474
+ - lib/rigor/cli/doctor_command.rb
453
475
  - lib/rigor/cli/explain_command.rb
454
476
  - lib/rigor/cli/fused_protection_renderer.rb
455
477
  - lib/rigor/cli/fused_protection_report.rb
@@ -478,6 +500,7 @@ files:
478
500
  - lib/rigor/cli/type_scan_command.rb
479
501
  - lib/rigor/cli/type_scan_renderer.rb
480
502
  - lib/rigor/cli/type_scan_report.rb
503
+ - lib/rigor/cli/upgrade_command.rb
481
504
  - lib/rigor/config_audit.rb
482
505
  - lib/rigor/configuration.rb
483
506
  - lib/rigor/configuration/dependencies.rb
@@ -527,6 +550,7 @@ files:
527
550
  - lib/rigor/inference/closure_escape_analyzer.rb
528
551
  - lib/rigor/inference/coverage_scanner.rb
529
552
  - lib/rigor/inference/def_return_typer.rb
553
+ - lib/rigor/inference/dynamic_origin.rb
530
554
  - lib/rigor/inference/expression_typer.rb
531
555
  - lib/rigor/inference/fallback.rb
532
556
  - lib/rigor/inference/fallback_tracer.rb
@@ -934,7 +958,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
934
958
  - !ruby/object:Gem::Version
935
959
  version: '0'
936
960
  requirements: []
937
- rubygems_version: 3.7.2
961
+ rubygems_version: 4.0.10
938
962
  specification_version: 4
939
963
  summary: Inference-first static analysis for Ruby.
940
964
  test_files: []