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.
- checksums.yaml +4 -4
- data/README.md +40 -13
- data/lib/rigor/analysis/fact_store.rb +15 -3
- data/lib/rigor/analysis/result.rb +11 -3
- data/lib/rigor/analysis/run_stats.rb +193 -0
- data/lib/rigor/analysis/runner.rb +387 -12
- data/lib/rigor/analysis/worker_session.rb +327 -0
- data/lib/rigor/builtins/imported_refinements.rb +6 -2
- data/lib/rigor/builtins/regex_refinement.rb +17 -12
- data/lib/rigor/cache/rbs_descriptor.rb +3 -1
- data/lib/rigor/cache/store.rb +40 -7
- data/lib/rigor/cli.rb +52 -2
- data/lib/rigor/configuration.rb +131 -6
- data/lib/rigor/environment/bundle_sig_discovery.rb +198 -0
- data/lib/rigor/environment/class_registry.rb +12 -3
- data/lib/rigor/environment/lockfile_resolver.rb +125 -0
- data/lib/rigor/environment/rbs_collection_discovery.rb +126 -0
- data/lib/rigor/environment/rbs_coverage_report.rb +112 -0
- data/lib/rigor/environment/rbs_loader.rb +194 -6
- data/lib/rigor/environment/reflection.rb +152 -0
- data/lib/rigor/environment.rb +78 -6
- data/lib/rigor/inference/acceptance.rb +35 -1
- data/lib/rigor/inference/builtins/method_catalog.rb +12 -5
- data/lib/rigor/inference/builtins/numeric_catalog.rb +15 -4
- data/lib/rigor/inference/expression_typer.rb +12 -2
- data/lib/rigor/inference/macro_block_self_type.rb +96 -0
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +29 -29
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +4 -4
- data/lib/rigor/inference/method_dispatcher/method_folding.rb +18 -1
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +46 -40
- data/lib/rigor/inference/method_dispatcher.rb +128 -3
- data/lib/rigor/inference/method_parameter_binder.rb +21 -11
- data/lib/rigor/inference/narrowing.rb +127 -8
- data/lib/rigor/inference/synthetic_method.rb +86 -0
- data/lib/rigor/inference/synthetic_method_index.rb +82 -0
- data/lib/rigor/inference/synthetic_method_scanner.rb +521 -0
- data/lib/rigor/plugin/blueprint.rb +60 -0
- data/lib/rigor/plugin/loader.rb +3 -1
- data/lib/rigor/plugin/macro/block_as_method.rb +131 -0
- data/lib/rigor/plugin/macro/external_file.rb +143 -0
- data/lib/rigor/plugin/macro/heredoc_template.rb +201 -0
- data/lib/rigor/plugin/macro/trait_registry.rb +198 -0
- data/lib/rigor/plugin/macro.rb +31 -0
- data/lib/rigor/plugin/manifest.rb +78 -7
- data/lib/rigor/plugin/registry.rb +32 -2
- data/lib/rigor/plugin.rb +1 -0
- data/lib/rigor/trinary.rb +15 -11
- data/lib/rigor/type/bot.rb +6 -3
- data/lib/rigor/type/combinator.rb +12 -1
- data/lib/rigor/type/integer_range.rb +7 -7
- data/lib/rigor/type/refined.rb +18 -12
- data/lib/rigor/type/top.rb +4 -3
- data/lib/rigor/type_node/generic.rb +7 -1
- data/lib/rigor/type_node/identifier.rb +9 -1
- data/lib/rigor/type_node/string_literal.rb +4 -1
- data/lib/rigor/version.rb +1 -1
- data/sig/rigor/environment.rbs +5 -2
- data/sig/rigor/plugin/blueprint.rbs +7 -0
- data/sig/rigor/plugin/manifest.rbs +1 -1
- data/sig/rigor/plugin/registry.rbs +14 -1
- data/sig/rigor.rbs +35 -2
- 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
|
-
|
|
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
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
|
-
|
|
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
|
data/lib/rigor/type/bot.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
data/lib/rigor/type/refined.rb
CHANGED
|
@@ -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
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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`
|
data/lib/rigor/type/top.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
data/sig/rigor/environment.rbs
CHANGED
|
@@ -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
|
|
@@ -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
|
-
|
|
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
|