rigortype 0.0.5 → 0.0.7

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.
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "prism"
4
4
 
5
+ require_relative "../reflection"
5
6
  require_relative "../type"
6
7
  require_relative "../environment"
7
8
  require_relative "../rbs_extended"
@@ -285,6 +286,8 @@ module Rigor
285
286
  complement_integer_range(current_type, refinement_type)
286
287
  when Type::Intersection
287
288
  complement_intersection(current_type, refinement_type)
289
+ when Type::Refined
290
+ complement_refined(current_type, refinement_type)
288
291
  else
289
292
  current_type
290
293
  end
@@ -526,6 +529,38 @@ module Rigor
526
529
  Type::Combinator.union(*per_member)
527
530
  end
528
531
 
532
+ # v0.0.7 — complement of a `Refined[base, predicate]`
533
+ # refinement within `current_type`. Walks the current
534
+ # type's union members; parts that are disjoint from
535
+ # the refinement's base survive unchanged; parts equal
536
+ # to the refinement itself drop entirely (they were
537
+ # exactly the negated subset); parts that overlap the
538
+ # base contribute `Difference[part, refined]` so
539
+ # downstream narrowing knows the refinement subset is
540
+ # excluded.
541
+ #
542
+ # The result is sound but imprecise: without a
543
+ # complementary carrier (e.g. `mixed-case-string` for
544
+ # `~lowercase-string`) we cannot enumerate the surviving
545
+ # values. Difference is the carrier-of-last-resort, and
546
+ # the existing `Type::Difference` consumers already
547
+ # treat it correctly.
548
+ def complement_refined(current_type, refined)
549
+ base = refined.base
550
+ parts = current_type.is_a?(Type::Union) ? current_type.members : [current_type]
551
+
552
+ survivors = parts.map do |part|
553
+ next nil if part == refined
554
+ next part if base_disjoint?(base, part)
555
+
556
+ Type::Combinator.difference(part, refined)
557
+ end.compact
558
+
559
+ return current_type if survivors.empty?
560
+
561
+ Type::Combinator.union(*survivors)
562
+ end
563
+
529
564
  def falsey_value?(value)
530
565
  value.nil? || value == false
531
566
  end
@@ -1248,18 +1283,15 @@ module Rigor
1248
1283
  end
1249
1284
 
1250
1285
  def resolve_rbs_extended_method(node, scope)
1251
- loader = scope.environment.rbs_loader
1252
- return nil if loader.nil?
1253
-
1254
1286
  receiver_type = scope.type_of(node.receiver)
1255
1287
  class_name = rbs_extended_class_name(receiver_type)
1256
1288
  return nil if class_name.nil?
1257
- return nil unless loader.class_known?(class_name)
1289
+ return nil unless Rigor::Reflection.rbs_class_known?(class_name, scope: scope)
1258
1290
 
1259
1291
  if receiver_type.is_a?(Type::Singleton)
1260
- loader.singleton_method(class_name: class_name, method_name: node.name)
1292
+ Rigor::Reflection.singleton_method_definition(class_name, node.name, scope: scope)
1261
1293
  else
1262
- loader.instance_method(class_name: class_name, method_name: node.name)
1294
+ Rigor::Reflection.instance_method_definition(class_name, node.name, scope: scope)
1263
1295
  end
1264
1296
  rescue StandardError
1265
1297
  nil
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "prism"
4
4
 
5
+ require_relative "../reflection"
5
6
  require_relative "../type"
6
7
  require_relative "../analysis/fact_store"
7
8
  require_relative "../source/node_walker"
@@ -838,7 +839,7 @@ module Rigor
838
839
  end
839
840
  end
840
841
 
841
- def resolve_call_method(call_node, current_scope) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
842
+ def resolve_call_method(call_node, current_scope) # rubocop:disable Metrics/PerceivedComplexity
842
843
  receiver_node = call_node.receiver
843
844
  receiver_type =
844
845
  if receiver_node
@@ -848,17 +849,14 @@ module Rigor
848
849
  end
849
850
  return nil if receiver_type.nil?
850
851
 
851
- loader = current_scope.environment.rbs_loader
852
- return nil if loader.nil?
853
-
854
852
  class_name = assertion_class_name(receiver_type)
855
853
  return nil if class_name.nil?
856
- return nil unless loader.class_known?(class_name)
854
+ return nil unless Rigor::Reflection.rbs_class_known?(class_name, scope: current_scope)
857
855
 
858
856
  if receiver_type.is_a?(Type::Singleton)
859
- loader.singleton_method(class_name: class_name, method_name: call_node.name)
857
+ Rigor::Reflection.singleton_method_definition(class_name, call_node.name, scope: current_scope)
860
858
  else
861
- loader.instance_method(class_name: class_name, method_name: call_node.name)
859
+ Rigor::Reflection.instance_method_definition(class_name, call_node.name, scope: current_scope)
862
860
  end
863
861
  rescue StandardError
864
862
  nil
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "type"
4
+
5
+ module Rigor
6
+ # Read-side facade over Rigor's three reflection sources:
7
+ #
8
+ # 1. **`Rigor::Environment::ClassRegistry`** — Ruby `Class` /
9
+ # `Module` objects (Integer, Float, Set, Pathname, …) registered
10
+ # at boot. Static; never changes during a `rigor check` run.
11
+ # 2. **`Rigor::Environment::RbsLoader`** — RBS-side declarations
12
+ # (instance / singleton methods, class hierarchy, constants).
13
+ # Loaded on demand from the project's `sig/` directory + the
14
+ # bundled stdlib RBS.
15
+ # 3. **`Rigor::Scope` discovered facts** — source-side discoveries
16
+ # produced by `Rigor::Inference::ScopeIndexer` (user-defined
17
+ # classes / modules, in-source constants, discovered method
18
+ # nodes, class ivar / cvar declarations).
19
+ #
20
+ # This module is the **stable read shape** that v0.1.0's plugin
21
+ # API will be designed against. ADR-2 (`docs/adr/2-extension-api.md`)
22
+ # calls out a unified reflection layer as a prerequisite for the
23
+ # extension protocols, and `docs/design/20260505-v0.1.0-readiness.md`
24
+ # nominates this module as the highest-leverage cold-start slice.
25
+ #
26
+ # The facade is **read-only and additive**. Existing call sites
27
+ # that read directly from `Rigor::Scope` or
28
+ # `Rigor::Environment::RbsLoader` continue to work unchanged;
29
+ # they migrate to the facade at their own pace. The facade
30
+ # performs no caching beyond what the underlying sources already
31
+ # provide.
32
+ #
33
+ # ## Public surface (v0.0.7 first pass)
34
+ #
35
+ # - {.class_known?} — does any source recognise this class /
36
+ # module name?
37
+ # - {.class_ordering} — `:equal` / `:subclass` / `:superclass` /
38
+ # `:disjoint` / `:unknown` ordering between two class names.
39
+ # - {.nominal_for_name} — `Rigor::Type::Nominal` for the class
40
+ # name, joining registry + RBS lookups.
41
+ # - {.singleton_for_name} — `Rigor::Type::Singleton` for the
42
+ # class name's class object.
43
+ # - {.constant_type_for} — type of a constant (joins in-source
44
+ # constants and RBS-side constants).
45
+ # - {.instance_method_definition} / {.singleton_method_definition}
46
+ # — RBS-side `RBS::Definition::Method` for the method, or
47
+ # `nil` when the method is not declared in RBS. Source-side
48
+ # discovered methods are exposed through {.discovered_method?}
49
+ # below until the unified `MethodDefinition` carrier ships.
50
+ # - {.discovered_class?} / {.discovered_method?} — has the
51
+ # ScopeIndexer pass recorded the class / method as user-
52
+ # defined in the analyzed sources?
53
+ #
54
+ # The provenance side of the API (which source family contributed
55
+ # each fact) is explicitly out of scope for the v0.0.7 first
56
+ # pass. v0.1.0's plugin API adds it as a separate concern.
57
+ module Reflection
58
+ module_function
59
+
60
+ # @param class_name [String, Symbol]
61
+ # @param scope [Rigor::Scope]
62
+ # @return [Boolean]
63
+ def class_known?(class_name, scope: Scope.empty)
64
+ return true if scope.discovered_classes.key?(class_name.to_s)
65
+
66
+ scope.environment.class_known?(class_name)
67
+ end
68
+
69
+ # RBS-only variant of {.class_known?}. Use when the caller
70
+ # needs to know specifically whether RBS has a definition
71
+ # for the class, independent of any source-discovered
72
+ # `class Foo; end` declarations. The diagnostic-rule code
73
+ # paths that walk RBS method tables to decide whether to
74
+ # flag a missing method use this variant; otherwise the
75
+ # source-discovered class would suppress the rule even
76
+ # when no RBS sig actually proves the method exists.
77
+ #
78
+ # The kwarg accepts either `scope:` or `environment:`. The
79
+ # latter is for call sites that don't carry a `Scope`
80
+ # (most are bottom-half dispatcher code paths called with
81
+ # only an environment).
82
+ def rbs_class_known?(class_name, scope: nil, environment: nil)
83
+ loader = rbs_loader_for(scope, environment)
84
+ return false if loader.nil?
85
+
86
+ loader.class_known?(class_name)
87
+ end
88
+
89
+ # @return [Symbol] one of `:equal`, `:subclass`, `:superclass`,
90
+ # `:disjoint`, `:unknown`.
91
+ def class_ordering(lhs, rhs, scope: Scope.empty)
92
+ scope.environment.class_ordering(lhs, rhs)
93
+ end
94
+
95
+ # Returns the `Rigor::Type::Nominal` for the class name, or
96
+ # nil when no source knows the class.
97
+ def nominal_for_name(class_name, scope: Scope.empty)
98
+ scope.environment.nominal_for_name(class_name)
99
+ end
100
+
101
+ # Returns the `Rigor::Type::Singleton` for the class name's
102
+ # class object, or nil when no source knows the class.
103
+ def singleton_for_name(class_name, scope: Scope.empty)
104
+ scope.environment.singleton_for_name(class_name)
105
+ end
106
+
107
+ # Returns the type of the named constant. Joins in-source
108
+ # constants (recorded by `ScopeIndexer`) and RBS-side
109
+ # constants. In-source wins on collision because the user's
110
+ # source is the authoritative declaration.
111
+ def constant_type_for(constant_name, scope: Scope.empty)
112
+ key = constant_name.to_s
113
+ in_source = scope.in_source_constants[key]
114
+ return in_source if in_source
115
+
116
+ scope.environment.constant_for_name(constant_name)
117
+ end
118
+
119
+ # Returns the RBS `RBS::Definition::Method` for the instance
120
+ # method, or nil when the class or method is not in RBS. The
121
+ # source-side discovered-method facts are reachable through
122
+ # {.discovered_method?}; a future slice will unify the two
123
+ # under a `MethodDefinition` carrier.
124
+ def instance_method_definition(class_name, method_name, scope: nil, environment: nil)
125
+ loader = rbs_loader_for(scope, environment)
126
+ return nil if loader.nil?
127
+
128
+ loader.instance_method(class_name: class_name.to_s, method_name: method_name.to_sym)
129
+ end
130
+
131
+ # Returns the RBS `RBS::Definition::Method` for the singleton
132
+ # (class-side) method, or nil.
133
+ def singleton_method_definition(class_name, method_name, scope: nil, environment: nil)
134
+ loader = rbs_loader_for(scope, environment)
135
+ return nil if loader.nil?
136
+
137
+ loader.singleton_method(class_name: class_name.to_s, method_name: method_name.to_sym)
138
+ end
139
+
140
+ # Returns the full RBS instance-side class definition
141
+ # (`RBS::Definition`), used by callers that walk the method
142
+ # table or member list. Returns nil when the class is not in
143
+ # RBS or when the loader cannot build a definition (e.g.
144
+ # constant aliases, malformed signatures).
145
+ def instance_definition(class_name, scope: nil, environment: nil)
146
+ loader = rbs_loader_for(scope, environment)
147
+ return nil if loader.nil?
148
+
149
+ loader.instance_definition(class_name.to_s)
150
+ rescue StandardError
151
+ nil
152
+ end
153
+
154
+ # Returns the full RBS singleton-side class definition.
155
+ def singleton_definition(class_name, scope: nil, environment: nil)
156
+ loader = rbs_loader_for(scope, environment)
157
+ return nil if loader.nil?
158
+
159
+ loader.singleton_definition(class_name.to_s)
160
+ rescue StandardError
161
+ nil
162
+ end
163
+
164
+ # Returns the RBS-declared type parameter names for the
165
+ # class (e.g. `[:A]` for `Array[A]`), or `[]` when the class
166
+ # is non-generic / not in RBS. Used by the dispatcher when
167
+ # binding generic method types to a concrete receiver.
168
+ def class_type_param_names(class_name, scope: nil, environment: nil)
169
+ loader = rbs_loader_for(scope, environment)
170
+ return [] if loader.nil?
171
+
172
+ loader.class_type_param_names(class_name.to_s)
173
+ end
174
+
175
+ # Internal helper — resolves the RBS loader from either the
176
+ # `scope:` or the `environment:` kwarg, defaulting to the
177
+ # empty scope's environment when neither is given. Public
178
+ # methods document both spellings; the helper centralises
179
+ # the dispatch.
180
+ def rbs_loader_for(scope, environment)
181
+ return environment.rbs_loader if environment
182
+ return scope.environment.rbs_loader if scope
183
+
184
+ Scope.empty.environment.rbs_loader
185
+ end
186
+ private_class_method :rbs_loader_for
187
+
188
+ # @return [Boolean] true when the analyzed source contains a
189
+ # class / module declaration for the given name. Does NOT
190
+ # consult the RBS loader (use {.class_known?} for the union).
191
+ def discovered_class?(class_name, scope: Scope.empty)
192
+ scope.discovered_classes.key?(class_name.to_s)
193
+ end
194
+
195
+ # @param kind [:instance, :singleton]
196
+ # @return [Boolean] true when the ScopeIndexer recorded a
197
+ # `def` for the given method on the given class with the
198
+ # matching kind.
199
+ def discovered_method?(class_name, method_name, kind: :instance, scope: Scope.empty)
200
+ scope.discovered_method?(class_name, method_name, kind)
201
+ end
202
+ end
203
+ end
@@ -219,9 +219,252 @@ module Rigor
219
219
  collapse_union(normalized_union_members(types))
220
220
  end
221
221
 
222
- class << self
222
+ # `key_of[T]` type function — projects the type-level
223
+ # union of `T`'s known keys. Recognised shapes:
224
+ #
225
+ # - `Type::HashShape{a: A, b: B}` → `Constant<:a> | Constant<:b>`.
226
+ # - `Type::Tuple[A, B, C]` → `Constant<0> | Constant<1> | Constant<2>`.
227
+ # - `Type::Nominal["Hash", [K, V]]` → `K` (untyped if absent).
228
+ # - `Type::Nominal["Array", [E]]` → `non-negative-int`.
229
+ # - `Type::Constant` whose value is a Hash / Array / Range —
230
+ # project through the literal's per-element keys.
231
+ #
232
+ # Other inputs (`Top`, `Dynamic`, untyped Nominals, `Union`,
233
+ # `Refined`, `Difference`, `Intersection`) project to `top`
234
+ # so the type function always returns a value — callers may
235
+ # narrow further when they know more.
236
+ def key_of(type)
237
+ case type
238
+ when HashShape then hash_shape_keys(type)
239
+ when Tuple then tuple_indices(type)
240
+ when Nominal then nominal_keys(type)
241
+ when Constant then constant_keys(type.value)
242
+ else top
243
+ end
244
+ end
245
+
246
+ # `value_of[T]` type function — projects the type-level
247
+ # union of `T`'s known values. Mirror of `key_of`:
248
+ #
249
+ # - `Type::HashShape{a: A, b: B}` → `A | B`.
250
+ # - `Type::Tuple[A, B, C]` → `A | B | C`.
251
+ # - `Type::Nominal["Hash", [K, V]]` → `V` (untyped if absent).
252
+ # - `Type::Nominal["Array", [E]]` → `E` (untyped if absent).
253
+ # - `Type::Constant` whose value is a Hash / Array / Range —
254
+ # union of `Constant<…>` for each element.
255
+ def value_of(type)
256
+ case type
257
+ when HashShape then hash_shape_values(type)
258
+ when Tuple then tuple_values(type)
259
+ when Nominal then nominal_values(type)
260
+ when Constant then constant_values(type.value)
261
+ else top
262
+ end
263
+ end
264
+
265
+ # `int_mask[1, 2, 4]` type function — every Integer
266
+ # representable by a bitwise OR over the listed flags,
267
+ # including 0. The closure of `[1, 2, 4]` is
268
+ # `{0, 1, 2, 3, 4, 5, 6, 7}`. Returns a `Union[Constant…]`
269
+ # for small closures and a covering `IntegerRange` once
270
+ # the cardinality exceeds `INT_MASK_UNION_LIMIT`. Returns
271
+ # `nil` when the input is malformed (non-integer flag,
272
+ # negative flag, or too many flags to compute the closure
273
+ # cheaply).
274
+ INT_MASK_FLAG_LIMIT = 6
275
+ INT_MASK_UNION_LIMIT = 16
276
+ private_constant :INT_MASK_FLAG_LIMIT, :INT_MASK_UNION_LIMIT
277
+
278
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
279
+ def int_mask(flags)
280
+ return nil unless flags.is_a?(Array) && flags.all?(Integer)
281
+ return nil if flags.any?(&:negative?)
282
+ return nil if flags.size > INT_MASK_FLAG_LIMIT
283
+
284
+ values = compute_int_mask_closure(flags)
285
+ return nil if values.nil?
286
+
287
+ if values.size <= INT_MASK_UNION_LIMIT
288
+ union(*values.map { |v| constant_of(v) })
289
+ else
290
+ integer_range(values.min, values.max)
291
+ end
292
+ end
293
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
294
+
295
+ # `int_mask_of[T]` — derives the int_mask closure from
296
+ # a finite integer-literal type:
297
+ # `Constant<n>` (single flag), `Union[Constant…]` (every
298
+ # member must be a `Constant<Integer>`). Returns nil for
299
+ # incompatible inputs (Top, Dynamic, IntegerRange, mixed
300
+ # member shapes).
301
+ def int_mask_of(type)
302
+ flags = extract_constant_int_set(type)
303
+ return nil if flags.nil?
304
+
305
+ int_mask(flags)
306
+ end
307
+
308
+ # `T[K]` indexed-access type operator — extracts the type
309
+ # at index / key `K` from a structured `T`:
310
+ #
311
+ # - `Tuple[A, B, C][Constant<i>]` → `A` / `B` / `C` (out-of-
312
+ # range indices return `Top` for safety).
313
+ # - `HashShape{a: A, b: B}[Constant<:a>]` → `A`.
314
+ # - `Nominal[Hash, [K, V]][_]` → `V` (untyped if absent).
315
+ # - `Nominal[Array, [E]][_]` → `E` (untyped if absent).
316
+ #
317
+ # Other shapes (`Top`, `Dynamic`, untyped Nominals,
318
+ # `Union`, `Refined`, `Difference`, `Intersection`)
319
+ # project to `Top`. The key argument is itself a
320
+ # `Type::t`; only `Type::Constant` keys produce a precise
321
+ # answer.
322
+ def indexed_access(type, key)
323
+ case type
324
+ when Tuple then tuple_indexed_access(type, key)
325
+ when HashShape then hash_shape_indexed_access(type, key)
326
+ when Nominal then nominal_indexed_access(type)
327
+ when Constant then constant_indexed_access(type.value, key)
328
+ else top
329
+ end
330
+ end
331
+
332
+ class << self # rubocop:disable Metrics/ClassLength
223
333
  private
224
334
 
335
+ def hash_shape_keys(shape)
336
+ return Bot.instance if shape.pairs.empty?
337
+
338
+ union(*shape.pairs.keys.map { |k| constant_of(k) })
339
+ end
340
+
341
+ def hash_shape_values(shape)
342
+ return Bot.instance if shape.pairs.empty?
343
+
344
+ union(*shape.pairs.values)
345
+ end
346
+
347
+ def tuple_indices(tuple)
348
+ return Bot.instance if tuple.elements.empty?
349
+
350
+ union(*tuple.elements.each_index.map { |i| constant_of(i) })
351
+ end
352
+
353
+ def tuple_values(tuple)
354
+ return Bot.instance if tuple.elements.empty?
355
+
356
+ union(*tuple.elements)
357
+ end
358
+
359
+ def nominal_keys(nominal)
360
+ case nominal.class_name
361
+ when "Hash"
362
+ nominal.type_args.first || untyped
363
+ when "Array"
364
+ non_negative_int
365
+ else
366
+ top
367
+ end
368
+ end
369
+
370
+ def nominal_values(nominal)
371
+ case nominal.class_name
372
+ when "Hash"
373
+ nominal.type_args[1] || untyped
374
+ when "Array"
375
+ nominal.type_args.first || untyped
376
+ else
377
+ top
378
+ end
379
+ end
380
+
381
+ # `Type::Constant` only carries scalar literals (Integer
382
+ # / Float / String / Symbol / Range / Rational / Complex
383
+ # / true / false / nil); Array and Hash literals become
384
+ # Tuple / HashShape carriers earlier in the typer. Range
385
+ # is the only scalar with meaningful key/value
386
+ # projections.
387
+ def compute_int_mask_closure(flags)
388
+ unique = flags.uniq
389
+ return [0] if unique.empty?
390
+
391
+ # Closure under bitwise OR over a set of non-negative
392
+ # integers is `0..(max_or_value)` only when the flags
393
+ # are bit-disjoint; otherwise it's a strict subset.
394
+ # Enumerate every subset's OR.
395
+ closure = Set.new([0])
396
+ unique.each do |flag|
397
+ closure |= closure.map { |c| c | flag }
398
+ end
399
+ closure.to_a.sort
400
+ end
401
+
402
+ def extract_constant_int_set(type)
403
+ case type
404
+ when Constant
405
+ type.value.is_a?(Integer) ? [type.value] : nil
406
+ when Union
407
+ type.members.all?(Constant) ? type.members.map(&:value).grep(Integer) : nil
408
+ end
409
+ end
410
+
411
+ def tuple_indexed_access(tuple, key)
412
+ return top unless key.is_a?(Constant) && key.value.is_a?(Integer)
413
+
414
+ index = key.value
415
+ return top if index.negative? || index >= tuple.elements.size
416
+
417
+ tuple.elements[index]
418
+ end
419
+
420
+ def hash_shape_indexed_access(shape, key)
421
+ return top unless key.is_a?(Constant)
422
+
423
+ shape.pairs[key.value] || top
424
+ end
425
+
426
+ def nominal_indexed_access(nominal)
427
+ case nominal.class_name
428
+ when "Hash" then nominal.type_args[1] || untyped
429
+ when "Array" then nominal.type_args.first || untyped
430
+ else top
431
+ end
432
+ end
433
+
434
+ def constant_indexed_access(value, key)
435
+ return top unless key.is_a?(Constant)
436
+
437
+ if value.is_a?(Range) && key.value.is_a?(Integer)
438
+ element = value.to_a[key.value]
439
+ return constant_of(element) unless element.nil?
440
+ end
441
+
442
+ top
443
+ end
444
+
445
+ def constant_keys(value)
446
+ return non_negative_int if value.is_a?(Range) && value.begin.is_a?(Integer)
447
+
448
+ top
449
+ end
450
+
451
+ def constant_values(value)
452
+ return range_value_of(value) if value.is_a?(Range)
453
+
454
+ top
455
+ end
456
+
457
+ def range_value_of(range)
458
+ beg = range.begin
459
+ en = range.end
460
+ return top unless beg.is_a?(Integer) && en.is_a?(Integer)
461
+
462
+ upper = range.exclude_end? ? en - 1 : en
463
+ return Bot.instance if upper < beg
464
+
465
+ integer_range(beg, upper)
466
+ end
467
+
225
468
  def normalized_union_members(types)
226
469
  flattened = []
227
470
  types.each { |t| flatten_into(flattened, t) }
@@ -22,6 +22,8 @@ module Rigor
22
22
  Range,
23
23
  Rational,
24
24
  Complex,
25
+ Regexp,
26
+ Pathname,
25
27
  TrueClass,
26
28
  FalseClass,
27
29
  NilClass
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.0.5"
4
+ VERSION = "0.0.7"
5
5
  end
data/lib/rigor.rb CHANGED
@@ -18,6 +18,7 @@ require_relative "rigor/inference/method_parameter_binder"
18
18
  require_relative "rigor/inference/closure_escape_analyzer"
19
19
  require_relative "rigor/inference/statement_evaluator"
20
20
  require_relative "rigor/scope"
21
+ require_relative "rigor/reflection"
21
22
  require_relative "rigor/source"
22
23
  require_relative "rigor/inference/scope_indexer"
23
24
  require_relative "rigor/inference/coverage_scanner"
@@ -0,0 +1,17 @@
1
+ module Rigor
2
+ module Reflection
3
+ def self?.class_known?: (String | Symbol class_name, ?scope: Scope) -> bool
4
+ def self?.rbs_class_known?: (String | Symbol class_name, ?scope: Scope) -> bool
5
+ def self?.class_ordering: (String | Symbol lhs, String | Symbol rhs, ?scope: Scope) -> Symbol
6
+ def self?.nominal_for_name: (String | Symbol class_name, ?scope: Scope) -> Type::Nominal?
7
+ def self?.singleton_for_name: (String | Symbol class_name, ?scope: Scope) -> Type::Singleton?
8
+ def self?.constant_type_for: (String | Symbol constant_name, ?scope: Scope) -> Type::t?
9
+ def self?.instance_method_definition: (String | Symbol class_name, String | Symbol method_name, ?scope: Scope) -> untyped
10
+ def self?.singleton_method_definition: (String | Symbol class_name, String | Symbol method_name, ?scope: Scope) -> untyped
11
+ def self?.instance_definition: (String | Symbol class_name, ?scope: Scope) -> untyped
12
+ def self?.singleton_definition: (String | Symbol class_name, ?scope: Scope) -> untyped
13
+ def self?.class_type_param_names: (String | Symbol class_name, ?scope: Scope) -> Array[Symbol]
14
+ def self?.discovered_class?: (String | Symbol class_name, ?scope: Scope) -> bool
15
+ def self?.discovered_method?: (String | Symbol class_name, String | Symbol method_name, ?kind: Symbol, ?scope: Scope) -> bool
16
+ end
17
+ end
data/sig/rigor/type.rbs CHANGED
@@ -256,6 +256,11 @@ module Rigor
256
256
  def self?.tuple_of: (*Type::t elements) -> Tuple
257
257
  def self?.hash_shape_of: (?Hash[untyped, Type::t]? pairs, **untyped options) -> HashShape
258
258
  def self?.union: (*Type::t types) -> Type::t
259
+ def self?.key_of: (Type::t type) -> Type::t
260
+ def self?.value_of: (Type::t type) -> Type::t
261
+ def self?.int_mask: (Array[Integer] flags) -> Type::t?
262
+ def self?.int_mask_of: (Type::t type) -> Type::t?
263
+ def self?.indexed_access: (Type::t type, Type::t key) -> Type::t
259
264
  end
260
265
  end
261
266
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rigortype
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rigor contributors
@@ -169,6 +169,7 @@ files:
169
169
  - data/builtins/ruby_core/hash.yml
170
170
  - data/builtins/ruby_core/io.yml
171
171
  - data/builtins/ruby_core/numeric.yml
172
+ - data/builtins/ruby_core/pathname.yml
172
173
  - data/builtins/ruby_core/range.yml
173
174
  - data/builtins/ruby_core/rational.yml
174
175
  - data/builtins/ruby_core/set.yml
@@ -205,6 +206,7 @@ files:
205
206
  - lib/rigor/inference/builtins/hash_catalog.rb
206
207
  - lib/rigor/inference/builtins/method_catalog.rb
207
208
  - lib/rigor/inference/builtins/numeric_catalog.rb
209
+ - lib/rigor/inference/builtins/pathname_catalog.rb
208
210
  - lib/rigor/inference/builtins/range_catalog.rb
209
211
  - lib/rigor/inference/builtins/rational_catalog.rb
210
212
  - lib/rigor/inference/builtins/set_catalog.rb
@@ -216,6 +218,7 @@ files:
216
218
  - lib/rigor/inference/fallback.rb
217
219
  - lib/rigor/inference/fallback_tracer.rb
218
220
  - lib/rigor/inference/method_dispatcher.rb
221
+ - lib/rigor/inference/method_dispatcher/block_folding.rb
219
222
  - lib/rigor/inference/method_dispatcher/constant_folding.rb
220
223
  - lib/rigor/inference/method_dispatcher/file_folding.rb
221
224
  - lib/rigor/inference/method_dispatcher/iterator_dispatch.rb
@@ -230,6 +233,7 @@ files:
230
233
  - lib/rigor/inference/scope_indexer.rb
231
234
  - lib/rigor/inference/statement_evaluator.rb
232
235
  - lib/rigor/rbs_extended.rb
236
+ - lib/rigor/reflection.rb
233
237
  - lib/rigor/scope.rb
234
238
  - lib/rigor/source.rb
235
239
  - lib/rigor/source/node_locator.rb
@@ -259,6 +263,7 @@ files:
259
263
  - sig/rigor/environment.rbs
260
264
  - sig/rigor/inference.rbs
261
265
  - sig/rigor/rbs_extended.rbs
266
+ - sig/rigor/reflection.rbs
262
267
  - sig/rigor/scope.rbs
263
268
  - sig/rigor/source.rbs
264
269
  - sig/rigor/testing.rbs