rigortype 0.1.4 → 0.1.5

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +40 -13
  3. data/lib/rigor/analysis/fact_store.rb +15 -3
  4. data/lib/rigor/analysis/result.rb +11 -3
  5. data/lib/rigor/analysis/run_stats.rb +193 -0
  6. data/lib/rigor/analysis/runner.rb +387 -12
  7. data/lib/rigor/analysis/worker_session.rb +327 -0
  8. data/lib/rigor/builtins/imported_refinements.rb +6 -2
  9. data/lib/rigor/builtins/regex_refinement.rb +17 -12
  10. data/lib/rigor/cache/rbs_descriptor.rb +3 -1
  11. data/lib/rigor/cache/store.rb +40 -7
  12. data/lib/rigor/cli.rb +52 -2
  13. data/lib/rigor/configuration.rb +131 -6
  14. data/lib/rigor/environment/bundle_sig_discovery.rb +198 -0
  15. data/lib/rigor/environment/class_registry.rb +12 -3
  16. data/lib/rigor/environment/lockfile_resolver.rb +125 -0
  17. data/lib/rigor/environment/rbs_collection_discovery.rb +126 -0
  18. data/lib/rigor/environment/rbs_coverage_report.rb +112 -0
  19. data/lib/rigor/environment/rbs_loader.rb +194 -6
  20. data/lib/rigor/environment/reflection.rb +152 -0
  21. data/lib/rigor/environment.rb +78 -6
  22. data/lib/rigor/inference/acceptance.rb +35 -1
  23. data/lib/rigor/inference/builtins/method_catalog.rb +12 -5
  24. data/lib/rigor/inference/builtins/numeric_catalog.rb +15 -4
  25. data/lib/rigor/inference/expression_typer.rb +12 -2
  26. data/lib/rigor/inference/macro_block_self_type.rb +96 -0
  27. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +29 -29
  28. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +4 -4
  29. data/lib/rigor/inference/method_dispatcher/method_folding.rb +18 -1
  30. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +1 -1
  31. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +46 -40
  32. data/lib/rigor/inference/method_dispatcher.rb +128 -3
  33. data/lib/rigor/inference/method_parameter_binder.rb +21 -11
  34. data/lib/rigor/inference/narrowing.rb +127 -8
  35. data/lib/rigor/inference/synthetic_method.rb +86 -0
  36. data/lib/rigor/inference/synthetic_method_index.rb +82 -0
  37. data/lib/rigor/inference/synthetic_method_scanner.rb +521 -0
  38. data/lib/rigor/plugin/blueprint.rb +60 -0
  39. data/lib/rigor/plugin/loader.rb +3 -1
  40. data/lib/rigor/plugin/macro/block_as_method.rb +131 -0
  41. data/lib/rigor/plugin/macro/external_file.rb +143 -0
  42. data/lib/rigor/plugin/macro/heredoc_template.rb +201 -0
  43. data/lib/rigor/plugin/macro/trait_registry.rb +198 -0
  44. data/lib/rigor/plugin/macro.rb +31 -0
  45. data/lib/rigor/plugin/manifest.rb +78 -7
  46. data/lib/rigor/plugin/registry.rb +32 -2
  47. data/lib/rigor/plugin.rb +1 -0
  48. data/lib/rigor/trinary.rb +15 -11
  49. data/lib/rigor/type/bot.rb +6 -3
  50. data/lib/rigor/type/combinator.rb +12 -1
  51. data/lib/rigor/type/integer_range.rb +7 -7
  52. data/lib/rigor/type/refined.rb +18 -12
  53. data/lib/rigor/type/top.rb +4 -3
  54. data/lib/rigor/type_node/generic.rb +7 -1
  55. data/lib/rigor/type_node/identifier.rb +9 -1
  56. data/lib/rigor/type_node/string_literal.rb +4 -1
  57. data/lib/rigor/version.rb +1 -1
  58. data/sig/rigor/environment.rbs +5 -2
  59. data/sig/rigor/plugin/blueprint.rbs +7 -0
  60. data/sig/rigor/plugin/manifest.rbs +1 -1
  61. data/sig/rigor/plugin/registry.rbs +14 -1
  62. data/sig/rigor.rbs +35 -2
  63. metadata +39 -1
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "macro/block_as_method"
4
+ require_relative "macro/external_file"
5
+ require_relative "macro/heredoc_template"
6
+ require_relative "macro/trait_registry"
7
+
8
+ module Rigor
9
+ module Plugin
10
+ # Substrate declarations for the macro / DSL expansion tiers
11
+ # introduced by ADR-16. Plugin authors declare entries under
12
+ # `Plugin::Manifest` slots (`block_as_methods:`,
13
+ # `trait_registries:`, `heredoc_macros:`,
14
+ # `external_file_inclusions:`) and the substrate consumes them
15
+ # to recognise the call shapes a library exposes to its users.
16
+ #
17
+ # Slice 1a (this file's first delivery) ships the Tier A value
18
+ # class only. The other tiers' value classes + their manifest
19
+ # slots arrive in subsequent slices per ADR-16 § Implementation
20
+ # slicing. The namespace is reserved here so subsequent slices
21
+ # add files alongside `block_as_method.rb` without churn.
22
+ #
23
+ # Per ADR-16 § WD13, substrate-produced output ships at a
24
+ # **floor** in v0.1.x ("substrate-affected code parses cleanly
25
+ # and has its identifiers resolved"); precise return-type
26
+ # emission is the ceiling and arrives in a later slice through
27
+ # the ADR-13 `Plugin::TypeNodeResolver` chain.
28
+ module Macro
29
+ end
30
+ end
31
+ end
@@ -38,12 +38,14 @@ module Rigor
38
38
  end
39
39
 
40
40
  attr_reader :id, :version, :description, :protocols, :config_schema, :produces, :consumes,
41
- :owns_receivers, :type_node_resolvers
41
+ :owns_receivers, :type_node_resolvers, :block_as_methods, :heredoc_templates,
42
+ :trait_registries, :external_files
42
43
 
43
44
  def initialize( # rubocop:disable Metrics/ParameterLists
44
45
  id:, version:,
45
46
  description: nil, protocols: [], config_schema: {},
46
- produces: [], consumes: [], owns_receivers: [], type_node_resolvers: []
47
+ produces: [], consumes: [], owns_receivers: [], type_node_resolvers: [],
48
+ block_as_methods: [], heredoc_templates: [], trait_registries: [], external_files: []
47
49
  )
48
50
  validate_id!(id)
49
51
  validate_version!(version)
@@ -52,17 +54,21 @@ module Rigor
52
54
  validate_produces!(produces)
53
55
  validate_owns_receivers!(owns_receivers)
54
56
  validate_type_node_resolvers!(type_node_resolvers)
57
+ validate_block_as_methods!(block_as_methods)
58
+ validate_heredoc_templates!(heredoc_templates)
59
+ validate_trait_registries!(trait_registries)
60
+ validate_external_files!(external_files)
55
61
 
56
62
  assign_fields(id, version, description, protocols, config_schema, produces, consumes, owns_receivers,
57
- type_node_resolvers)
63
+ type_node_resolvers, block_as_methods, heredoc_templates, trait_registries, external_files)
58
64
  freeze
59
65
  end
60
66
 
61
67
  private
62
68
 
63
- # rubocop:disable Metrics/ParameterLists
69
+ # rubocop:disable Metrics/ParameterLists, Metrics/AbcSize
64
70
  def assign_fields(id, version, description, protocols, config_schema, produces, consumes, owns_receivers,
65
- type_node_resolvers)
71
+ type_node_resolvers, block_as_methods, heredoc_templates, trait_registries, external_files)
66
72
  @id = id.dup.freeze
67
73
  @version = version.dup.freeze
68
74
  @description = description.nil? ? nil : description.to_s.dup.freeze
@@ -72,8 +78,12 @@ module Rigor
72
78
  @consumes = coerce_consumes(consumes)
73
79
  @owns_receivers = owns_receivers.map { |c| c.to_s.dup.freeze }.freeze
74
80
  @type_node_resolvers = type_node_resolvers.dup.freeze
81
+ @block_as_methods = block_as_methods.dup.freeze
82
+ @heredoc_templates = heredoc_templates.dup.freeze
83
+ @trait_registries = trait_registries.dup.freeze
84
+ @external_files = external_files.dup.freeze
75
85
  end
76
- # rubocop:enable Metrics/ParameterLists
86
+ # rubocop:enable Metrics/ParameterLists, Metrics/AbcSize
77
87
 
78
88
  public
79
89
 
@@ -110,7 +120,11 @@ module Rigor
110
120
  "produces" => produces.map(&:to_s),
111
121
  "consumes" => consumes.map { |c| consumption_hash(c) },
112
122
  "owns_receivers" => owns_receivers,
113
- "type_node_resolvers" => type_node_resolvers.map { |r| r.class.name }
123
+ "type_node_resolvers" => type_node_resolvers.map { |r| r.class.name },
124
+ "block_as_methods" => block_as_methods.map(&:to_h),
125
+ "heredoc_templates" => heredoc_templates.map(&:to_h),
126
+ "trait_registries" => trait_registries.map(&:to_h),
127
+ "external_files" => external_files.map(&:to_h)
114
128
  }
115
129
  end
116
130
 
@@ -208,6 +222,63 @@ module Rigor
208
222
  "Rigor::Plugin::TypeNodeResolver instances, got #{resolvers.inspect}"
209
223
  end
210
224
 
225
+ # ADR-16 slice 1a — `block_as_methods:` declares the Tier A
226
+ # substrate entries the plugin contributes. Slice 1a carries
227
+ # the declarations on the manifest; the engine hook that
228
+ # actually narrows `Scope#self_type` for matching blocks
229
+ # arrives in a subsequent slice.
230
+ def validate_block_as_methods!(entries)
231
+ return if entries.is_a?(Array) && entries.all?(Macro::BlockAsMethod)
232
+
233
+ raise ArgumentError,
234
+ "plugin manifest block_as_methods must be an Array of " \
235
+ "Rigor::Plugin::Macro::BlockAsMethod instances, got #{entries.inspect}"
236
+ end
237
+
238
+ # ADR-16 slice 2a — `heredoc_templates:` declares the Tier C
239
+ # substrate entries (heredoc-template synthesis on class-level
240
+ # DSL calls). Slice 2a carries the declarations on the
241
+ # manifest; the pre-pass + `SyntheticMethodIndex` that actually
242
+ # emit synthetic methods arrive in slice 2b.
243
+ def validate_heredoc_templates!(entries)
244
+ return if entries.is_a?(Array) && entries.all?(Macro::HeredocTemplate)
245
+
246
+ raise ArgumentError,
247
+ "plugin manifest heredoc_templates must be an Array of " \
248
+ "Rigor::Plugin::Macro::HeredocTemplate instances, got #{entries.inspect}"
249
+ end
250
+
251
+ # ADR-16 slice 3a — `trait_registries:` declares the Tier B
252
+ # substrate entries (trait-inlining via bundled module
253
+ # registry). Slice 3a carries the declarations on the
254
+ # manifest; the scanner + per-method explosion through
255
+ # `SyntheticMethodIndex` (slice 2b primitive) arrives in
256
+ # slice 3b.
257
+ def validate_trait_registries!(entries)
258
+ return if entries.is_a?(Array) && entries.all?(Macro::TraitRegistry)
259
+
260
+ raise ArgumentError,
261
+ "plugin manifest trait_registries must be an Array of " \
262
+ "Rigor::Plugin::Macro::TraitRegistry instances, got #{entries.inspect}"
263
+ end
264
+
265
+ # ADR-16 slice 5a — `external_files:` declares the Tier D
266
+ # substrate entries (external-Ruby-file inclusion under a
267
+ # declared `self`). Slice 5a carries the declarations on
268
+ # the manifest; the engine integration that walks the
269
+ # matched files + narrows their entry scope is **queued for
270
+ # slice 5b**, gated on demonstrated demand from concrete
271
+ # plugin targets (Redmine webhook payloads, tDiary plugin
272
+ # loader, etc.). Plugin authors MAY declare entries today;
273
+ # the substrate does not yet act on them.
274
+ def validate_external_files!(entries)
275
+ return if entries.is_a?(Array) && entries.all?(Macro::ExternalFile)
276
+
277
+ raise ArgumentError,
278
+ "plugin manifest external_files must be an Array of " \
279
+ "Rigor::Plugin::Macro::ExternalFile instances, got #{entries.inspect}"
280
+ end
281
+
211
282
  def coerce_consumes(consumes)
212
283
  unless consumes.is_a?(Array)
213
284
  raise ArgumentError, "plugin manifest consumes must be an Array, got #{consumes.inspect}"
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "blueprint"
4
+
3
5
  module Rigor
4
6
  module Plugin
5
7
  # Read-side query API over the plugins loaded for a single
@@ -13,20 +15,48 @@ module Rigor
13
15
  # the order in which {Rigor::Plugin::Loader} resolved
14
16
  # configuration entries, which is project-config order with
15
17
  # plugin-id alphabetical as the tie-breaker.
18
+ #
19
+ # ADR-15 Phase 3 — alongside the instantiated `plugins`, the
20
+ # registry carries `blueprints`: a frozen, Ractor-shareable
21
+ # `Array<Blueprint>` that records how to re-instantiate the
22
+ # same plugin set in a worker Ractor. The eventual Phase 4
23
+ # pool ships `blueprints` across the boundary and calls
24
+ # {.materialize} per-Ractor; the live `plugins` carriage on
25
+ # the coordinator registry stays unchanged.
16
26
  class Registry
17
- attr_reader :plugins, :load_errors
27
+ attr_reader :plugins, :load_errors, :blueprints
18
28
 
19
29
  # @param plugins [Array<Rigor::Plugin::Base>] instantiated
20
30
  # plugin instances in deterministic order.
21
31
  # @param load_errors [Array<Rigor::Plugin::LoadError>] failures
22
32
  # surfaced during loading. Each error is also turned into a
23
33
  # diagnostic by the runner.
24
- def initialize(plugins: [], load_errors: [])
34
+ # @param blueprints [Array<Rigor::Plugin::Blueprint>] frozen,
35
+ # Ractor-shareable replay descriptors aligned 1:1 with
36
+ # `plugins`. The loader fills this in; callers that
37
+ # construct Registry manually MAY pass `[]` and accept
38
+ # that {.materialize} cannot replay the set.
39
+ def initialize(plugins: [], load_errors: [], blueprints: [])
25
40
  @plugins = plugins.dup.freeze
26
41
  @load_errors = load_errors.dup.freeze
42
+ @blueprints = blueprints.dup.freeze
27
43
  freeze
28
44
  end
29
45
 
46
+ # ADR-15 Phase 3 — build a fresh Registry from the supplied
47
+ # blueprint set by replaying {Blueprint#materialize} per
48
+ # entry against `services`. The returned registry carries
49
+ # NEW plugin instances (mutable per-Ractor accumulators
50
+ # included) and the same blueprint set, so a worker can
51
+ # hand the materialised registry to Environment without
52
+ # losing the replay handle. `load_errors` is intentionally
53
+ # empty: load-time failures already surfaced in the
54
+ # coordinator registry and don't repeat per worker.
55
+ def self.materialize(blueprints:, services:)
56
+ plugins = blueprints.map { |bp| bp.materialize(services: services) }
57
+ new(plugins: plugins, blueprints: blueprints, load_errors: [])
58
+ end
59
+
30
60
  def find(id)
31
61
  id_s = id.to_s
32
62
  plugins.find { |plugin| plugin.manifest.id == id_s }
data/lib/rigor/plugin.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "plugin/type_node_resolver"
4
+ require_relative "plugin/macro"
4
5
  require_relative "plugin/manifest"
5
6
  require_relative "plugin/access_denied_error"
6
7
  require_relative "plugin/trust_policy"
data/lib/rigor/trinary.rb CHANGED
@@ -10,18 +10,16 @@ module Rigor
10
10
  class Trinary
11
11
  VALUES = %i[yes no maybe].freeze
12
12
 
13
+ # ADR-15 Phase 4b.x — eager singleton instances so the
14
+ # class-level `@yes` / `@no` / `@maybe` ivars are populated
15
+ # on the main Ractor at load time. Workers READ the ivars
16
+ # via `Trinary.yes` etc. without performing the `||=`
17
+ # write that non-main Ractors are forbidden from doing.
18
+ # The actual `@yes = new(:yes).freeze` allocation happens
19
+ # at the bottom of the file, AFTER `def initialize` is
20
+ # defined.
13
21
  class << self
14
- def yes
15
- @yes ||= new(:yes).freeze
16
- end
17
-
18
- def no
19
- @no ||= new(:no).freeze
20
- end
21
-
22
- def maybe
23
- @maybe ||= new(:maybe).freeze
24
- end
22
+ attr_reader :yes, :no, :maybe
25
23
 
26
24
  def from_symbol(symbol)
27
25
  case symbol
@@ -104,5 +102,11 @@ module Rigor
104
102
 
105
103
  raise TypeError, "expected Rigor::Trinary, got #{other.class}"
106
104
  end
105
+
106
+ # ADR-15 Phase 4b.x eager singletons (see `class << self`
107
+ # above). Allocated after `initialize` is defined.
108
+ @yes = new(:yes).freeze
109
+ @no = new(:no).freeze
110
+ @maybe = new(:maybe).freeze
107
111
  end
108
112
  end
@@ -8,10 +8,13 @@ module Rigor
8
8
  # expressions that cannot terminate normally. See
9
9
  # docs/type-specification/special-types.md.
10
10
  class Bot
11
+ # ADR-15 Phase 4b.x — eager singleton so workers READ
12
+ # `@instance` without performing the lazy `||=` write
13
+ # that non-main Ractors are forbidden from doing.
14
+ @instance = new.freeze
15
+
11
16
  class << self
12
- def instance
13
- @instance ||= new.freeze
14
- end
17
+ attr_reader :instance
15
18
 
16
19
  private :new
17
20
  end
@@ -36,8 +36,14 @@ module Rigor
36
36
  Bot.instance
37
37
  end
38
38
 
39
+ # ADR-15 Phase 4b.x — read the eagerly-allocated
40
+ # `@untyped` ivar instead of `||=`. The singleton-class
41
+ # `@untyped = Dynamic.new(top)` initializer runs at module
42
+ # body (below) on the main Ractor at load time. Workers
43
+ # READ the populated ivar without performing the lazy
44
+ # write that non-main Ractors are forbidden from doing.
39
45
  def untyped
40
- @untyped ||= Dynamic.new(top)
46
+ @untyped
41
47
  end
42
48
 
43
49
  # Wraps the static facet in a Dynamic[T] carrier. Idempotent on the
@@ -809,6 +815,11 @@ module Rigor
809
815
  members.sort_by { |m| m.describe(:short) }
810
816
  end
811
817
  end
818
+
819
+ # ADR-15 Phase 4b.x — eager-allocate the singleton
820
+ # `Dynamic[Top]` carrier on the main Ractor at load time.
821
+ # The `untyped` reader above just returns this ivar.
822
+ @untyped = Dynamic.new(Top.instance)
812
823
  end
813
824
  end
814
825
  end
@@ -78,13 +78,13 @@ module Rigor
78
78
  Float::INFINITY
79
79
  end
80
80
 
81
- ALIAS_NAMES = {
82
- [NEG_INFINITY, POS_INFINITY] => "int",
83
- [1, POS_INFINITY] => "positive-int",
84
- [0, POS_INFINITY] => "non-negative-int",
85
- [NEG_INFINITY, -1] => "negative-int",
86
- [NEG_INFINITY, 0] => "non-positive-int"
87
- }.freeze
81
+ ALIAS_NAMES = Ractor.make_shareable({
82
+ [NEG_INFINITY, POS_INFINITY] => "int",
83
+ [1, POS_INFINITY] => "positive-int",
84
+ [0, POS_INFINITY] => "non-negative-int",
85
+ [NEG_INFINITY, -1] => "negative-int",
86
+ [NEG_INFINITY, 0] => "non-positive-int"
87
+ })
88
88
 
89
89
  def describe(_verbosity = :short)
90
90
  ALIAS_NAMES[[min, max]] || generic_description
@@ -165,18 +165,24 @@ module Rigor
165
165
  # kebab-case canonical name. Registered shapes print
166
166
  # through `describe`; unregistered combinations fall back
167
167
  # to the operator form.
168
- CANONICAL_NAMES = {
169
- ["String", :lowercase] => "lowercase-string",
170
- ["String", :not_lowercase] => "non-lowercase-string",
171
- ["String", :uppercase] => "uppercase-string",
172
- ["String", :not_uppercase] => "non-uppercase-string",
173
- ["String", :numeric] => "numeric-string",
174
- ["String", :not_numeric] => "non-numeric-string",
175
- ["String", :decimal_int] => "decimal-int-string",
176
- ["String", :octal_int] => "octal-int-string",
177
- ["String", :hex_int] => "hex-int-string",
178
- ["String", :literal_string] => "literal-string"
179
- }.freeze
168
+ #
169
+ # ADR-15 Phase 4b.x — `Ractor.make_shareable` (not `.freeze`)
170
+ # because the keys are nested two-element Arrays. Plain
171
+ # `.freeze` would leave the inner arrays mutable, so a
172
+ # worker Ractor reading `CANONICAL_NAMES[[base, predicate]]`
173
+ # would trip `Ractor::IsolationError`.
174
+ CANONICAL_NAMES = Ractor.make_shareable({
175
+ ["String", :lowercase] => "lowercase-string",
176
+ ["String", :not_lowercase] => "non-lowercase-string",
177
+ ["String", :uppercase] => "uppercase-string",
178
+ ["String", :not_uppercase] => "non-uppercase-string",
179
+ ["String", :numeric] => "numeric-string",
180
+ ["String", :not_numeric] => "non-numeric-string",
181
+ ["String", :decimal_int] => "decimal-int-string",
182
+ ["String", :octal_int] => "octal-int-string",
183
+ ["String", :hex_int] => "hex-int-string",
184
+ ["String", :literal_string] => "literal-string"
185
+ })
180
186
  private_constant :CANONICAL_NAMES
181
187
 
182
188
  # Bidirectional `predicate_id ↔ complement_predicate_id`
@@ -7,10 +7,11 @@ module Rigor
7
7
  # The top of the value lattice: contains every value, including untyped
8
8
  # boundaries. See docs/type-specification/special-types.md.
9
9
  class Top
10
+ # ADR-15 Phase 4b.x — eager singleton (see Bot.rb).
11
+ @instance = new.freeze
12
+
10
13
  class << self
11
- def instance
12
- @instance ||= new.freeze
13
- end
14
+ attr_reader :instance
14
15
 
15
16
  private :new
16
17
  end
@@ -38,7 +38,13 @@ module Rigor
38
38
  "TypeNode::IntegerLiteral, got #{args.inspect}"
39
39
  end
40
40
 
41
- super(head: head, args: args.freeze)
41
+ # Freeze the String head + Array args so the Data
42
+ # object is `Ractor.shareable?`. Each `a` is already a
43
+ # shareable TypeNode value object (checked above), so
44
+ # freezing the wrapping Array is sufficient.
45
+ frozen_head = head.frozen? ? head : head.dup.freeze
46
+ frozen_args = args.frozen? ? args : args.dup.freeze
47
+ super(head: frozen_head, args: frozen_args)
42
48
  end
43
49
 
44
50
  private
@@ -23,7 +23,15 @@ module Rigor
23
23
  "got #{name.inspect}"
24
24
  end
25
25
 
26
- super
26
+ # Freeze the String field so the resulting Data object
27
+ # is `Ractor.shareable?` regardless of whether the
28
+ # caller passed a `# frozen_string_literal: true`
29
+ # constant or a dynamically built String. The same
30
+ # discipline applies to every other TypeNode value
31
+ # object — they live in the parser's hot path and are
32
+ # the natural carriers to flow through future Ractor
33
+ # boundaries (see CURRENT_WORK Open Items #8).
34
+ super(name: name.frozen? ? name : name.dup.freeze)
27
35
  end
28
36
  end
29
37
  end
@@ -22,7 +22,10 @@ module Rigor
22
22
  "got #{value.inspect}"
23
23
  end
24
24
 
25
- super
25
+ # Freeze the String field so the Data object is
26
+ # `Ractor.shareable?` regardless of caller frozen-
27
+ # string-literal state.
28
+ super(value: value.frozen? ? value : value.dup.freeze)
26
29
  end
27
30
  end
28
31
  end
data/lib/rigor/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rigor
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.5"
5
5
  end
@@ -11,16 +11,18 @@ module Rigor
11
11
  attr_reader rbs_extended_reporter: untyped?
12
12
  attr_reader boundary_cross_reporter: untyped?
13
13
  attr_reader name_scope: untyped?
14
+ attr_reader synthetic_method_index: untyped?
14
15
 
15
16
  def self.default: () -> Environment
16
- def self.for_project: (?root: String, ?libraries: Array[String], ?signature_paths: Array[String | _ToPath]?, ?cache_store: untyped?, ?plugin_registry: untyped?, ?dependency_source_index: untyped?, ?rbs_extended_reporter: untyped?, ?boundary_cross_reporter: untyped?) -> Environment
17
+ def self.for_project: (?root: String, ?libraries: Array[String], ?signature_paths: Array[String | _ToPath]?, ?cache_store: untyped?, ?plugin_registry: untyped?, ?dependency_source_index: untyped?, ?rbs_extended_reporter: untyped?, ?boundary_cross_reporter: untyped?, ?bundler_bundle_path: String?, ?bundler_auto_detect: bool, ?synthetic_method_index: untyped?) -> Environment
17
18
 
18
- def initialize: (?class_registry: ClassRegistry, ?rbs_loader: RbsLoader?, ?plugin_registry: untyped?, ?dependency_source_index: untyped?, ?rbs_extended_reporter: untyped?, ?boundary_cross_reporter: untyped?) -> void
19
+ def initialize: (?class_registry: ClassRegistry, ?rbs_loader: RbsLoader?, ?plugin_registry: untyped?, ?dependency_source_index: untyped?, ?rbs_extended_reporter: untyped?, ?boundary_cross_reporter: untyped?, ?synthetic_method_index: untyped?) -> void
19
20
  def nominal_for_name: (String | Symbol name) -> Type::Nominal?
20
21
  def singleton_for_name: (String | Symbol name) -> Type::Singleton?
21
22
  def constant_for_name: (String | Symbol name) -> Type::t?
22
23
  def class_known?: (String | Symbol name) -> bool
23
24
  def class_ordering: (String | Symbol lhs, String | Symbol rhs) -> ordering
25
+ def reflection: () -> untyped?
24
26
 
25
27
  class ClassRegistry
26
28
  def self.default: () -> ClassRegistry
@@ -42,6 +44,7 @@ module Rigor
42
44
  def self.default: () -> RbsLoader
43
45
  def self.reset_default!: () -> void
44
46
  def self.build_env_for: (libraries: Array[String], signature_paths: Array[String | _ToPath]) -> untyped
47
+ def self.vendored_gem_sig_paths: () -> Array[Pathname]
45
48
 
46
49
  def initialize: (?libraries: Array[String], ?signature_paths: Array[String | _ToPath], ?cache_store: untyped?) -> void
47
50
  def class_known?: (String | Symbol name) -> bool
@@ -0,0 +1,7 @@
1
+ class Rigor::Plugin::Blueprint
2
+ attr_reader klass_name: String
3
+ attr_reader config: Hash[untyped, untyped]
4
+
5
+ def initialize: (klass_name: String | Module, ?config: Hash[untyped, untyped]) -> void
6
+ def materialize: (services: untyped) -> Rigor::Plugin::Base
7
+ end
@@ -3,7 +3,7 @@ class Rigor::Plugin::Manifest::Consumption
3
3
  end
4
4
 
5
5
  class Rigor::Plugin::Manifest
6
- def initialize: (id: untyped, version: untyped, ?description: untyped, ?protocols: untyped, ?config_schema: untyped, ?produces: untyped, ?consumes: untyped, ?owns_receivers: untyped, ?type_node_resolvers: untyped) -> void
6
+ def initialize: (id: untyped, version: untyped, ?description: untyped, ?protocols: untyped, ?config_schema: untyped, ?produces: untyped, ?consumes: untyped, ?owns_receivers: untyped, ?type_node_resolvers: untyped, ?block_as_methods: untyped, ?heredoc_templates: untyped, ?trait_registries: untyped, ?external_files: untyped) -> void
7
7
  def validate_config: (untyped) -> Array[String]
8
8
  def to_h: () -> Hash[String, untyped]
9
9
  end
@@ -1,3 +1,16 @@
1
1
  class Rigor::Plugin::Registry
2
- def initialize: (?plugins: untyped, ?load_errors: untyped) -> void
2
+ attr_reader plugins: untyped
3
+ attr_reader load_errors: untyped
4
+ attr_reader blueprints: untyped
5
+
6
+ EMPTY: Rigor::Plugin::Registry
7
+
8
+ def self.materialize: (blueprints: untyped, services: untyped) -> Rigor::Plugin::Registry
9
+
10
+ def initialize: (?plugins: untyped, ?load_errors: untyped, ?blueprints: untyped) -> void
11
+ def find: (String | Symbol id) -> untyped
12
+ def ids: () -> Array[String]
13
+ def empty?: () -> bool
14
+ def any_load_errors?: () -> bool
15
+ def type_node_resolvers: () -> Array[untyped]
3
16
  end
data/sig/rigor.rbs CHANGED
@@ -54,13 +54,46 @@ module Rigor
54
54
 
55
55
  class Result
56
56
  attr_reader diagnostics: Array[Diagnostic]
57
+ attr_reader stats: RunStats?
57
58
 
58
- def initialize: (?diagnostics: Array[Diagnostic]) -> void
59
+ def initialize: (?diagnostics: Array[Diagnostic], ?stats: RunStats?) -> void
59
60
  def success?: () -> bool
60
61
  def error_count: () -> Integer
61
62
  def to_h: () -> Hash[String, untyped]
62
63
  end
63
64
 
65
+ class RunStats
66
+ attr_reader wall_seconds: Float
67
+ attr_reader peak_rss_bytes: Integer?
68
+ attr_reader target_files: Integer
69
+ attr_reader rbs_classes_total: Integer
70
+ attr_reader rbs_classes_project_sig: Integer
71
+ attr_reader rbs_classes_bundled: Integer
72
+ attr_reader gem_walk_classes: Integer
73
+ attr_reader gem_walk_gems: Integer
74
+ attr_reader rbs_attribution_available: bool
75
+
76
+ CACHED_SENTINEL: String
77
+
78
+ def self.peak_rss_bytes: () -> Integer?
79
+ def self.partition_classes: (class_decl_paths: Hash[String, String], signature_paths: Array[untyped]) -> [Integer, Integer]
80
+ def self.attribution_available?: (class_decl_paths: Hash[String, String]) -> bool
81
+
82
+ def initialize: (
83
+ wall_seconds: Float,
84
+ peak_rss_bytes: Integer?,
85
+ target_files: Integer,
86
+ rbs_classes_total: Integer,
87
+ rbs_classes_project_sig: Integer,
88
+ rbs_classes_bundled: Integer,
89
+ gem_walk_classes: Integer,
90
+ gem_walk_gems: Integer,
91
+ ?rbs_attribution_available: bool
92
+ ) -> void
93
+ def format: (untyped out, ?prefix: String) -> void
94
+ def to_h: () -> Hash[Symbol, untyped]
95
+ end
96
+
64
97
  class Runner
65
98
  RUBY_GLOB: String
66
99
  DEFAULT_CACHE_ROOT: String
@@ -71,7 +104,7 @@ module Rigor
71
104
  # otherwise raises `RBS::UnknownTypeName` for the named type.
72
105
  attr_reader cache_store: untyped
73
106
  attr_reader plugin_registry: untyped
74
- def initialize: (configuration: Configuration, ?explain: bool, ?cache_store: untyped, ?plugin_requirer: untyped) -> void
107
+ def initialize: (configuration: Configuration, ?explain: bool, ?cache_store: untyped, ?plugin_requirer: untyped, ?workers: Integer, ?collect_stats: bool) -> void
75
108
  def run: (?Array[String] paths) -> Result
76
109
  end
77
110
  end