rbs 1.0.3 → 1.1.1

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +2 -2
  3. data/CHANGELOG.md +65 -0
  4. data/Gemfile +0 -1
  5. data/Rakefile +3 -2
  6. data/Steepfile +2 -0
  7. data/bin/rbs-prof +1 -1
  8. data/core/array.rbs +10 -6
  9. data/core/complex.rbs +1 -1
  10. data/core/enumerable.rbs +15 -1
  11. data/core/enumerator.rbs +4 -0
  12. data/core/file.rbs +2 -1
  13. data/core/integer.rbs +2 -1
  14. data/core/module.rbs +1 -1
  15. data/core/rational.rbs +2 -1
  16. data/core/string.rbs +2 -1
  17. data/core/symbol.rbs +2 -1
  18. data/core/thread.rbs +14 -1
  19. data/core/time.rbs +2 -1
  20. data/docs/stdlib.md +1 -1
  21. data/lib/rbs.rb +3 -0
  22. data/lib/rbs/ancestor_graph.rb +90 -0
  23. data/lib/rbs/ast/members.rb +13 -0
  24. data/lib/rbs/char_scanner.rb +20 -0
  25. data/lib/rbs/definition_builder.rb +50 -25
  26. data/lib/rbs/definition_builder/method_builder.rb +23 -2
  27. data/lib/rbs/environment.rb +42 -5
  28. data/lib/rbs/environment_walker.rb +4 -4
  29. data/lib/rbs/errors.rb +32 -17
  30. data/lib/rbs/parser.rb +437 -416
  31. data/lib/rbs/parser.y +29 -16
  32. data/lib/rbs/test/type_check.rb +7 -3
  33. data/lib/rbs/version.rb +1 -1
  34. data/sig/ancestor_graph.rbs +40 -0
  35. data/sig/char_scanner.rbs +9 -0
  36. data/sig/definition_builder.rbs +5 -1
  37. data/sig/environment.rbs +22 -2
  38. data/sig/environment_walker.rbs +39 -0
  39. data/sig/errors.rbs +42 -17
  40. data/sig/members.rbs +2 -0
  41. data/sig/method_builder.rbs +2 -0
  42. data/sig/parser.rbs +11 -4
  43. data/sig/polyfill.rbs +0 -14
  44. data/sig/types.rbs +7 -1
  45. data/stdlib/bigdecimal/0/big_decimal.rbs +1 -1
  46. data/stdlib/cgi/0/core.rbs +595 -0
  47. data/stdlib/date/0/date.rbs +1 -1
  48. data/stdlib/json/0/json.rbs +288 -0
  49. data/stdlib/pathname/0/pathname.rbs +2 -1
  50. data/stdlib/rubygems/0/basic_specification.rbs +3 -0
  51. data/stdlib/rubygems/0/config_file.rbs +3 -0
  52. data/stdlib/rubygems/0/dependency_installer.rbs +5 -0
  53. data/stdlib/rubygems/0/installer.rbs +3 -0
  54. data/stdlib/rubygems/0/path_support.rbs +3 -0
  55. data/stdlib/rubygems/0/platform.rbs +3 -0
  56. data/stdlib/rubygems/0/request_set.rbs +7 -0
  57. data/stdlib/rubygems/0/requirement.rbs +3 -0
  58. data/stdlib/rubygems/0/rubygems.rbs +710 -0
  59. data/stdlib/rubygems/0/source_list.rbs +2 -0
  60. data/stdlib/rubygems/0/specification.rbs +3 -0
  61. data/stdlib/rubygems/0/stream_ui.rbs +3 -0
  62. data/stdlib/rubygems/0/uninstaller.rbs +3 -0
  63. data/stdlib/rubygems/0/version.rbs +228 -0
  64. data/stdlib/set/0/set.rbs +7 -0
  65. data/stdlib/strscan/0/string_scanner.rbs +582 -0
  66. data/stdlib/timeout/0/timeout.rbs +57 -0
  67. data/stdlib/uri/0/rfc2396_parser.rbs +144 -7
  68. data/steep/Gemfile.lock +17 -19
  69. metadata +24 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 036100021b0cbb49dd861874f559cf64e038d283bf6dbcb6068db71fc9900a69
4
- data.tar.gz: 9bdf796be6710ae9f9a7c1ab50e7ce1871d86e34b9712fb03fa7418652499e25
3
+ metadata.gz: 8d83588e6a5f96ce5953f7c94eaf6f745eddadd1446e91946f18d4b81efb70bc
4
+ data.tar.gz: 3d7c3148afbe2a6041de6c909ddf08d7991e17c6fa2cebd4393a920582539263
5
5
  SHA512:
6
- metadata.gz: c70a2e6caa836c06d8136806b45d307f46b40e5cb21a6d4b4eaf49850fa884be0b240e1c8617e3f5d2cca75be25d91cfb0573613fff5ad8c945d0f9f45f8bdb0
7
- data.tar.gz: fdc96f11d612bdc16672620fd135360a0ff31cb6d32d181aa70785a0b15bf63d13588be95ade7a702d1c64091f22378c1a864a80dbcdf81c129dcdbb091f5afe
6
+ metadata.gz: e8a99b1a837a8cf4c7f1ce6b148c25e66433db2800d356a51ad58cc9b41280b097d3db7a3138679bc34f3c536415473a1b5423fac44f1048359d8556c938c298
7
+ data.tar.gz: 145caea219b5fb1d209e37f03ae0d4999f788895cf6a6dc4150d9ee4864be46ee7dc1126b95d0ddb0b1f1a4576c46f502c415aef56143900be61b726f81a291f
@@ -27,10 +27,10 @@ jobs:
27
27
  run: |
28
28
  apt-get update
29
29
  apt-get install -y libdb-dev
30
- - name: Install bundler
30
+ - name: Update rubygems & bundler
31
31
  run: |
32
32
  ruby -v
33
- gem install bundler
33
+ gem update --system
34
34
  - name: bundle config set with
35
35
  run: |
36
36
  echo "NO_MINITEST=true" >> $GITHUB_ENV
data/CHANGELOG.md CHANGED
@@ -2,6 +2,71 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.1.1 (2021-03-12)
6
+
7
+ ### Signature updates
8
+
9
+ * rubygem ([#630](https://github.com/ruby/rbs/pull/630))
10
+
11
+ ## 1.1.0 (2021-03-08)
12
+
13
+ ### Summary
14
+
15
+ Errors are now organized by `RBS::BaseError`, `RBS::ParsingError`, `RBS::LoadingError`, and `RBS::DefinitionError`.
16
+ The library users can rescue RBS related errors with `RBS::BaseError`, parsing errors with `RBS::ParsingError`, and other errors with `RBS::LoadingError` and `RBS::DefinitionErrors`.
17
+
18
+ Updating a part of environments are supported. Library users can remove declarations read from a set of files, adding new declarations, running name resolution related to the new decls, and deleting `DefinitionBuilder` caches related to the changes.
19
+ See `RBS::Environment#reject`, `RBS::Environment#resolve_type_names`, `RBS::AncestorGraph`, and `RBS::DefinitionBuilder#update`.
20
+
21
+ `RBS::DefinitionBuilder#build_singleton` now returns definitions containing `instance` type, which had returned resolved class instance types. This is a breaking change, but we consider it a bug fix because `RBS::DefinitionBuilder#build_instance` has returned `instance` types and `#build_singleton` has returned `class` type.
22
+
23
+ ### Signature updates
24
+
25
+ * rubygem ([\#605](https://github.com/ruby/rbs/pull/605), [\#610](https://github.com/ruby/rbs/pull/610))
26
+ * Array ([\#612](https://github.com/ruby/rbs/pull/612), [\#614](https://github.com/ruby/rbs/pull/614))
27
+ * cgi/core ([\#599](https://github.com/ruby/rbs/pull/599))
28
+ * Thread ([\#618](https://github.com/ruby/rbs/pull/618))
29
+
30
+ ### Language updates
31
+
32
+ * Allow trailing comma for Record and Tuple types ([\#606](https://github.com/ruby/rbs/pull/606))
33
+
34
+ ### Library changes
35
+
36
+ * Allow partial update of RBS declarations ([\#608](https://github.com/ruby/rbs/pull/608), [\#621](https://github.com/ruby/rbs/pull/621))
37
+ * Let errors have `TypeName` ([\#611](https://github.com/ruby/rbs/pull/611))
38
+ * Add `Parser::LexerError` ([\#615](https://github.com/ruby/rbs/pull/615))
39
+ * Performance improvement ([\#617](https://github.com/ruby/rbs/pull/617), [\#620](https://github.com/ruby/rbs/pull/620))
40
+ * No substitute `instance` types on `#build_singleton` ([\#619](https://github.com/ruby/rbs/pull/619))
41
+
42
+ ### Miscellaneous
43
+
44
+ * Make racc name customizable by `RACC` environment variable ([\#602](https://github.com/ruby/rbs/pull/602))
45
+ * Suppress warnings ([\#624](https://github.com/ruby/rbs/pull/624))
46
+ * Remove needless `Gem::Version` polyfill ([\#622](https://github.com/ruby/rbs/pull/622))
47
+
48
+ ## 1.0.6 (2021-02-17)
49
+
50
+ * Signature Updates
51
+ * `Enumerable` ([\#595](https://github.com/ruby/rbs/pull/595), [\#596](https://github.com/ruby/rbs/pull/596), [\#601](https://github.com/ruby/rbs/pull/601))
52
+ * `#as_json` ([\#597](https://github.com/ruby/rbs/pull/597))
53
+
54
+ ## 1.0.5 (2021-02-13)
55
+
56
+ * Signature Updates
57
+ * Enumerable ([\#596](https://github.com/ruby/rbs/pull/596))
58
+ * Set ([\#595](https://github.com/ruby/rbs/pull/595))
59
+ * `#to_json` ([\#592](https://github.com/ruby/rbs/pull/592))
60
+ * `<=>` ([\#593](https://github.com/ruby/rbs/pull/593))
61
+ * Timeout ([\#586](https://github.com/ruby/rbs/pull/586))
62
+ * URI::RFC2396_Parser ([\#587](https://github.com/ruby/rbs/pull/587))
63
+ * Rename generic class parameters on re-open ([\#594](https://github.com/ruby/rbs/pull/594))
64
+ * Make `refute_send_type` check that method call doesn't match with types in RBS ([\#588](https://github.com/ruby/rbs/pull/588))
65
+
66
+ ## 1.0.4 (2021-01-31)
67
+
68
+ * Unbundle `rr` to run test in `ruby/ruby` repo ([#585](https://github.com/ruby/rbs/pull/585))
69
+
5
70
  ## 1.0.3 (2021-01-28)
6
71
 
7
72
  * Set up `#ancestors` and `#location` of `RecursiveAncestorError` ([#583](https://github.com/ruby/rbs/pull/583))
data/Gemfile CHANGED
@@ -6,7 +6,6 @@ gemspec
6
6
  # Development dependencies
7
7
  gem "rake"
8
8
  gem "test-unit"
9
- gem "test-unit-rr"
10
9
  gem "rspec"
11
10
  gem "racc"
12
11
  gem "rubocop"
data/Rakefile CHANGED
@@ -3,6 +3,7 @@ require "rake/testtask"
3
3
  require "rbconfig"
4
4
 
5
5
  ruby = ENV["RUBY"] || RbConfig.ruby
6
+ racc = ENV.fetch("RACC", "racc")
6
7
  rbs = File.join(__dir__, "exe/rbs")
7
8
  bin = File.join(__dir__, "bin")
8
9
 
@@ -67,7 +68,7 @@ task :rubocop do
67
68
  end
68
69
 
69
70
  rule ".rb" => ".y" do |t|
70
- sh "racc -v -o #{t.name} #{t.source}"
71
+ sh "#{racc} -v -o #{t.name} #{t.source}"
71
72
  end
72
73
 
73
74
  task :parser => "lib/rbs/parser.rb"
@@ -77,7 +78,7 @@ task :build => :parser
77
78
 
78
79
  task :confirm_parser do
79
80
  puts "Testing if parser.rb is updated with respect to parser.y"
80
- sh "racc -v -o lib/rbs/parser.rb lib/rbs/parser.y"
81
+ sh "#{racc} -v -o lib/rbs/parser.rb lib/rbs/parser.y"
81
82
  sh "git diff --exit-code lib/rbs/parser.rb"
82
83
  end
83
84
 
data/Steepfile CHANGED
@@ -5,6 +5,8 @@ target :lib do
5
5
  ignore "lib/rbs/prototype", "lib/rbs/test", "lib/rbs/test.rb"
6
6
 
7
7
  library "set", "pathname", "json", "logger", "monitor", "tsort"
8
+ signature "stdlib/strscan/0/"
9
+ signature "stdlib/rubygems/0/"
8
10
  end
9
11
 
10
12
  # target :lib do
data/bin/rbs-prof CHANGED
@@ -4,6 +4,6 @@ require "stackprof"
4
4
 
5
5
  out = ENV["RBS_STACKPROF_OUT"] || 'tmp/stackprof-cpu-rbs.dump'
6
6
 
7
- StackProf.run(mode: :cpu, out: out) do
7
+ StackProf.run(mode: :cpu, out: out, raw: true) do
8
8
  load File.join(__dir__, "../exe/rbs")
9
9
  end
data/core/array.rbs CHANGED
@@ -1584,8 +1584,8 @@ class Array[unchecked out Elem] < Object
1584
1584
  # a.sample(random: Random.new(1)) #=> 6
1585
1585
  # a.sample(4, random: Random.new(1)) #=> [6, 10, 9, 2]
1586
1586
  #
1587
- def sample: (?random: Random rng) -> Elem?
1588
- | (?int n, ?random: Random rng) -> ::Array[Elem]
1587
+ def sample: (?random: _Rand rng) -> Elem?
1588
+ | (?int n, ?random: _Rand rng) -> ::Array[Elem]
1589
1589
 
1590
1590
  # Returns a new array containing all elements of `ary` for which the given
1591
1591
  # `block` returns a true value.
@@ -1649,7 +1649,7 @@ class Array[unchecked out Elem] < Object
1649
1649
  #
1650
1650
  # a.shuffle(random: Random.new(1)) #=> [1, 3, 2]
1651
1651
  #
1652
- def shuffle: (?random: Random rng) -> ::Array[Elem]
1652
+ def shuffle: (?random: _Rand rng) -> ::Array[Elem]
1653
1653
 
1654
1654
  # Shuffles elements in `self` in place.
1655
1655
  #
@@ -1661,7 +1661,7 @@ class Array[unchecked out Elem] < Object
1661
1661
  #
1662
1662
  # a.shuffle!(random: Random.new(1)) #=> [1, 3, 2]
1663
1663
  #
1664
- def shuffle!: (?random: Random rng) -> self
1664
+ def shuffle!: (?random: _Rand rng) -> self
1665
1665
 
1666
1666
  alias size length
1667
1667
 
@@ -1736,7 +1736,7 @@ class Array[unchecked out Elem] < Object
1736
1736
  # See also Enumerable#sort_by.
1737
1737
  #
1738
1738
  def sort: () -> ::Array[Elem]
1739
- | () { (Elem a, Elem b) -> ::Integer? } -> ::Array[Elem]
1739
+ | () { (Elem a, Elem b) -> ::Integer } -> ::Array[Elem]
1740
1740
 
1741
1741
  # Sorts `self` in place.
1742
1742
  #
@@ -1757,7 +1757,7 @@ class Array[unchecked out Elem] < Object
1757
1757
  # See also Enumerable#sort_by.
1758
1758
  #
1759
1759
  def sort!: () -> self
1760
- | () { (Elem a, Elem b) -> ::Integer? } -> self
1760
+ | () { (Elem a, Elem b) -> ::Integer } -> self
1761
1761
 
1762
1762
  # Sorts `self` in place using a set of keys generated by mapping the values in
1763
1763
  # `self` through the given block.
@@ -1997,6 +1997,10 @@ interface _ToAry[T]
1997
1997
  def to_ary: () -> ::Array[T]
1998
1998
  end
1999
1999
 
2000
+ interface _Rand
2001
+ def rand: (::Integer max) -> ::Integer
2002
+ end
2003
+
2000
2004
  interface Array::_Pattern[T]
2001
2005
  def ===: (T) -> bool
2002
2006
  end
data/core/complex.rbs CHANGED
@@ -121,7 +121,7 @@ class Complex < Numeric
121
121
  # Complex(2) <=> 2 #=> 0
122
122
  # Complex(2) <=> 3 #=> -1
123
123
  #
124
- def <=>: (Numeric) -> Integer?
124
+ def <=>: (untyped) -> Integer?
125
125
 
126
126
  # Returns true if cmp equals object numerically.
127
127
  #
data/core/enumerable.rbs CHANGED
@@ -286,8 +286,22 @@ module Enumerable[unchecked out Elem]: _Each[Elem]
286
286
  def sort_by: () { (Elem arg0) -> (Comparable | ::Array[untyped]) } -> ::Array[Elem]
287
287
  | () -> ::Enumerator[Elem, ::Array[Elem]]
288
288
 
289
- def take: (Integer n) -> ::Array[Elem]?
289
+ # Returns first n elements from *enum*.
290
+ #
291
+ # a = [1, 2, 3, 4, 5, 0]
292
+ # a.take(3) #=> [1, 2, 3]
293
+ # a.take(30) #=> [1, 2, 3, 4, 5, 0]
294
+ #
295
+ def take: (Integer n) -> ::Array[Elem]
290
296
 
297
+ # Passes elements to the block until the block returns `nil` or `false`, then
298
+ # stops iterating and returns an array of all prior elements.
299
+ #
300
+ # If no block is given, an enumerator is returned instead.
301
+ #
302
+ # a = [1, 2, 3, 4, 5, 0]
303
+ # a.take_while { |i| i < 3 } #=> [1, 2]
304
+ #
291
305
  def take_while: () { (Elem) -> boolish } -> ::Array[Elem]
292
306
  | () -> ::Enumerator[Elem, ::Array[Elem]]
293
307
 
data/core/enumerator.rbs CHANGED
@@ -244,6 +244,8 @@ end
244
244
 
245
245
  class Enumerator::Generator[out Elem] < Object
246
246
  include Enumerable[Elem]
247
+
248
+ def each: () { (Elem) -> void } -> void
247
249
  end
248
250
 
249
251
  class Enumerator::Lazy[out Elem, out Return] < Enumerator[Elem, Return]
@@ -259,4 +261,6 @@ end
259
261
 
260
262
  class Enumerator::Chain[out Elem] < Object
261
263
  include Enumerable[Elem]
264
+
265
+ def each: () { (Elem) -> void } -> void
262
266
  end
data/core/file.rbs CHANGED
@@ -985,7 +985,8 @@ class File::Stat < Object
985
985
  include Comparable
986
986
 
987
987
  def initialize: (String file) -> Object
988
- def <=>: (File::Stat other) -> Integer?
988
+ def <=>: (File::Stat other) -> Integer
989
+ | (untyped) -> nil
989
990
 
990
991
  def atime: () -> Time
991
992
 
data/core/integer.rbs CHANGED
@@ -112,7 +112,8 @@ class Integer < Numeric
112
112
  #
113
113
  # `nil` is returned if the two values are incomparable.
114
114
  #
115
- def <=>: (Numeric) -> Integer?
115
+ def <=>: (Integer | Rational) -> Integer
116
+ | (untyped) -> Integer?
116
117
 
117
118
  # Returns `true` if `int` equals `other` numerically. Contrast this with
118
119
  # Integer#eql?, which requires `other` to be an Integer.
data/core/module.rbs CHANGED
@@ -90,7 +90,7 @@ class Module < Object
90
90
  # Returns `nil` if `module` has no relationship with `other_module`, if
91
91
  # `other_module` is not a module, or if the two values are incomparable.
92
92
  #
93
- def <=>: (Module other) -> Integer?
93
+ def <=>: (untyped other) -> Integer?
94
94
 
95
95
  # Equality --- At the Object level, #== returns `true` only if `obj` and `other`
96
96
  # are the same object. Typically, this method is overridden in descendant
data/core/rational.rbs CHANGED
@@ -125,7 +125,8 @@ class Rational < Numeric
125
125
  #
126
126
  # Rational(1, 3) <=> "0.3" #=> nil
127
127
  #
128
- def <=>: (Numeric) -> Integer?
128
+ def <=>: (Integer | Rational) -> Integer
129
+ | (untyped) -> Integer?
129
130
 
130
131
  # Returns `true` if `rat` equals `object` numerically.
131
132
  #
data/core/string.rbs CHANGED
@@ -91,7 +91,8 @@ class String
91
91
  # "abcdef" <=> "ABCDEF" #=> 1
92
92
  # "abcdef" <=> 1 #=> nil
93
93
  #
94
- def <=>: (untyped other) -> Integer?
94
+ def <=>: (string other) -> Integer
95
+ | (untyped other) -> Integer?
95
96
 
96
97
  # Equality---Returns whether `str` == `obj`, similar to Object#==.
97
98
  #
data/core/symbol.rbs CHANGED
@@ -47,7 +47,8 @@ class Symbol
47
47
  #
48
48
  # See String#<=> for more information.
49
49
  #
50
- def <=>: (untyped other) -> Integer?
50
+ def <=>: (Symbol other) -> Integer
51
+ | (untyped other) -> Integer?
51
52
 
52
53
  # Equality---If *sym* and *obj* are exactly the same symbol, returns `true`.
53
54
  #
data/core/thread.rbs CHANGED
@@ -287,7 +287,20 @@ class Thread < Object
287
287
 
288
288
  def group: () -> ThreadGroup?
289
289
 
290
- def initialize: (*untyped args) -> Thread
290
+ # Creates a new thread executing the given block.
291
+ #
292
+ # Any `args` given to ::new will be passed to the block:
293
+ #
294
+ # arr = []
295
+ # a, b, c = 1, 2, 3
296
+ # Thread.new(a,b,c) { |d,e,f| arr << d << e << f }.join
297
+ # arr #=> [1, 2, 3]
298
+ #
299
+ # A ThreadError exception is raised if ::new is called without a block.
300
+ #
301
+ # If you're going to subclass Thread, be sure to call super in your `initialize`
302
+ # method, otherwise a ThreadError will be raised.
303
+ def initialize: (*untyped) { (*untyped) -> void } -> void
291
304
 
292
305
  # The calling thread will suspend execution and run this `thr` .
293
306
  #
data/core/time.rbs CHANGED
@@ -230,7 +230,8 @@ class Time < Object
230
230
  # t2 <=> t #=> 1
231
231
  # t <=> t #=> 0
232
232
  #
233
- def <=>: (Time other) -> Integer?
233
+ def <=>: (Time other) -> Integer
234
+ | (untyped other) -> Integer?
234
235
 
235
236
  def >: (Time arg0) -> bool
236
237
 
data/docs/stdlib.md CHANGED
@@ -70,7 +70,7 @@ One non-trivial but absolutely better solution is to make a tool:
70
70
  The next step should be importing RDoc documents.
71
71
 
72
72
  ```
73
- $ bin/annotate-with-rdoc stdlib/pathname/pathname.rbs
73
+ $ bin/annotate-with-rdoc stdlib/pathname/0/pathname.rbs
74
74
  Loading store from /Users/soutaro/.rbenv/versions/2.7.0-dev/share/ri/2.7.0/system...
75
75
  Loading store from /Users/soutaro/.rbenv/versions/2.7.0-dev/share/ri/2.7.0/site...
76
76
  Opening stdlib/pathname/pathname.rbs...
data/lib/rbs.rb CHANGED
@@ -7,7 +7,9 @@ require "pp"
7
7
  require "ripper"
8
8
  require "logger"
9
9
  require "tsort"
10
+ require "strscan"
10
11
 
12
+ require "rbs/char_scanner"
11
13
  require "rbs/errors"
12
14
  require "rbs/buffer"
13
15
  require "rbs/location"
@@ -40,6 +42,7 @@ require "rbs/vendorer"
40
42
  require "rbs/validator"
41
43
  require "rbs/factory"
42
44
  require "rbs/repository"
45
+ require "rbs/ancestor_graph"
43
46
 
44
47
  begin
45
48
  require "rbs/parser"
@@ -0,0 +1,90 @@
1
+ module RBS
2
+ class AncestorGraph
3
+ InstanceNode = _ = Struct.new(:type_name, keyword_init: true)
4
+ SingletonNode = _ = Struct.new(:type_name, keyword_init: true)
5
+
6
+ attr_reader :env
7
+ attr_reader :ancestor_builder
8
+ attr_reader :parents
9
+ attr_reader :children
10
+
11
+ def initialize(env:, ancestor_builder: DefinitionBuilder::AncestorBuilder.new(env: env))
12
+ @env = env
13
+ @ancestor_builder = ancestor_builder
14
+ build()
15
+ end
16
+
17
+ def build()
18
+ @parents = {}
19
+ @children = {}
20
+
21
+ env.class_decls.each_key do |type_name|
22
+ build_ancestors(InstanceNode.new(type_name: type_name), ancestor_builder.one_instance_ancestors(type_name))
23
+ build_ancestors(SingletonNode.new(type_name: type_name), ancestor_builder.one_singleton_ancestors(type_name))
24
+ end
25
+ env.interface_decls.each_key do |type_name|
26
+ build_ancestors(InstanceNode.new(type_name: type_name), ancestor_builder.one_interface_ancestors(type_name))
27
+ end
28
+ end
29
+
30
+ def build_ancestors(node, ancestors)
31
+ ancestors.each_ancestor do |ancestor|
32
+ case ancestor
33
+ when Definition::Ancestor::Instance
34
+ register(child: node, parent: InstanceNode.new(type_name: ancestor.name))
35
+ when Definition::Ancestor::Singleton
36
+ register(child: node, parent: SingletonNode.new(type_name: ancestor.name))
37
+ end
38
+ end
39
+ end
40
+
41
+ def register(parent:, child:)
42
+ (parents[child] ||= Set[]) << parent
43
+ (children[parent] ||= Set[]) << child
44
+ end
45
+
46
+ def each_parent(node, &block)
47
+ if block
48
+ parents[node]&.each(&block)
49
+ else
50
+ enum_for :each_parent, node
51
+ end
52
+ end
53
+
54
+ def each_child(node, &block)
55
+ if block
56
+ children[node]&.each(&block)
57
+ else
58
+ enum_for :each_child, node
59
+ end
60
+ end
61
+
62
+ def each_ancestor(node, yielded: Set[], &block)
63
+ if block
64
+ each_parent(node) do |parent|
65
+ unless yielded.member?(parent)
66
+ yielded << parent
67
+ yield parent
68
+ each_ancestor(parent, yielded: yielded, &block)
69
+ end
70
+ end
71
+ else
72
+ enum_for :each_ancestor, node
73
+ end
74
+ end
75
+
76
+ def each_descendant(node, yielded: Set[], &block)
77
+ if block
78
+ each_child(node) do |child|
79
+ unless yielded.member?(child)
80
+ yielded << child
81
+ yield child
82
+ each_descendant(child, yielded: yielded, &block)
83
+ end
84
+ end
85
+ else
86
+ enum_for :each_descendant, node
87
+ end
88
+ end
89
+ end
90
+ end