rbs 0.5.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/Gemfile +2 -0
  4. data/Rakefile +2 -3
  5. data/docs/stdlib.md +0 -2
  6. data/docs/syntax.md +6 -3
  7. data/goodcheck.yml +65 -0
  8. data/lib/rbs.rb +1 -0
  9. data/lib/rbs/ast/comment.rb +6 -0
  10. data/lib/rbs/ast/declarations.rb +44 -6
  11. data/lib/rbs/cli.rb +21 -3
  12. data/lib/rbs/constant_table.rb +1 -1
  13. data/lib/rbs/definition_builder.rb +290 -124
  14. data/lib/rbs/environment.rb +50 -37
  15. data/lib/rbs/errors.rb +68 -25
  16. data/lib/rbs/factory.rb +14 -0
  17. data/lib/rbs/location.rb +15 -0
  18. data/lib/rbs/parser.y +89 -28
  19. data/lib/rbs/prototype/rb.rb +2 -2
  20. data/lib/rbs/prototype/rbi.rb +1 -1
  21. data/lib/rbs/prototype/runtime.rb +1 -1
  22. data/lib/rbs/substitution.rb +6 -2
  23. data/lib/rbs/test.rb +82 -3
  24. data/lib/rbs/test/errors.rb +5 -1
  25. data/lib/rbs/test/hook.rb +133 -259
  26. data/lib/rbs/test/observer.rb +17 -0
  27. data/lib/rbs/test/setup.rb +37 -20
  28. data/lib/rbs/test/setup_helper.rb +29 -0
  29. data/lib/rbs/test/spy.rb +0 -321
  30. data/lib/rbs/test/tester.rb +118 -0
  31. data/lib/rbs/test/type_check.rb +42 -5
  32. data/lib/rbs/validator.rb +4 -0
  33. data/lib/rbs/version.rb +1 -1
  34. data/lib/rbs/writer.rb +2 -2
  35. data/schema/decls.json +21 -10
  36. data/stdlib/builtin/enumerable.rbs +2 -2
  37. data/stdlib/builtin/proc.rbs +1 -2
  38. data/stdlib/json/json.rbs +6 -0
  39. data/stdlib/logger/formatter.rbs +23 -0
  40. data/stdlib/logger/log_device.rbs +39 -0
  41. data/stdlib/logger/logger.rbs +507 -0
  42. data/stdlib/logger/period.rbs +7 -0
  43. data/stdlib/logger/severity.rbs +8 -0
  44. data/stdlib/pty/pty.rbs +159 -0
  45. metadata +13 -3
  46. data/lib/rbs/test/test_helper.rb +0 -180
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5318ae7911a3e7e4e1bed761e0c7b8d1fc248e698b0d53f8a39d388da5617f0
4
- data.tar.gz: d90f20d41372bcc852f49b844aa6b6b5367d9d88ec686a13ab00841f1cf1e2ed
3
+ metadata.gz: '094182e5d2602ec5ba9244068f67f854dfd5aa9c804fe48f2e943934da3e806b'
4
+ data.tar.gz: bbd2a02e2c79a092f3e3555337aebdb557301fd2dd712bc46bcfaaa3ae4f3ed5
5
5
  SHA512:
6
- metadata.gz: 702ae082267eb6a087e19c5a37a83aaaeea0f76e83eba7cc984a15cca869745d1b934231bf6910dbbba972a06301948eca740aa2a8fc49c378487a030befe909
7
- data.tar.gz: 8f467c52d50c25886965e1762f7c52f246cb90fa313c7d0a9400051f32c7f3603ada0142cf90ebfad4b56ccbaf57bacd5d1467cb8daf20247254c90937b9c599
6
+ metadata.gz: 8de689c6af71a94ef511cd5efc9b64d1277f99256e759ec58ad4185505831e3ca041a8555f454ea6700713a4f03a88caeed2104009b8915b9acf5c8b4e5ba53b
7
+ data.tar.gz: dec9ab30d0d1261897103b71c7203d3857c2cd4150ef145f3b8f3d005b7ba3f9daa947033a1db37c7f7aaf7530725f9129707d29def747fe9334a75acbcc9a16
@@ -2,6 +2,39 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.9.1 (2020-08-04)
6
+
7
+ * Ensure using Module#name [#354](https://github.com/ruby/rbs/pull/354)
8
+ * Fix runtime test setup [#353](https://github.com/ruby/rbs/pull/353)
9
+
10
+ ## 0.9.0 (2020-08-03)
11
+
12
+ * Fix signature validation [#351](https://github.com/ruby/rbs/pull/351), [#352](https://github.com/ruby/rbs/pull/352)
13
+ * Parsing performance improvement [#350](https://github.com/ruby/rbs/pull/350)
14
+
15
+ ## 0.8.0 (2020-08-01)
16
+
17
+ * Signature updates for `Enumerator` and `PTY`
18
+ * Fix prototype rb/rbi error handling [#349](https://github.com/ruby/rbs/pull/349)
19
+ * Runtime test improvements [#344](https://github.com/ruby/rbs/pull/344), [#343](https://github.com/ruby/rbs/pull/343)
20
+ * Add `...` syntax [#342](https://github.com/ruby/rbs/pull/342)
21
+
22
+ ## 0.7.0 (2020-07-20)
23
+
24
+ * Add `DefinitionBuilder#one_instance_ancestors` and `DefinitionBuilder#one_singleton_ancestors` [#341](https://github.com/ruby/rbs/pull/341)
25
+ * Bug fix in ConstantTable [#340](https://github.com/ruby/rbs/pull/340)
26
+ * Make `rbs validate` faster [#338](https://github.com/ruby/rbs/pull/338)
27
+ * Dedup methods generated by `rbs prototype rb` [#334](https://github.com/ruby/rbs/pull/334)
28
+
29
+ ## 0.6.0 (2020-07-12)
30
+
31
+ * Signature update for `Logger`.
32
+ * Clean `Environment#inspect`. [#331](https://github.com/ruby/rbs/pull/331)
33
+ * Module self type syntax update. [#329](https://github.com/ruby/rbs/pull/329)
34
+ * Better validation. [#328](https://github.com/ruby/rbs/pull/328)
35
+ * Parser performance improvement. [#327](https://github.com/ruby/rbs/pull/327)
36
+ * Runtime type checking performance improvements with sampling [#323](https://github.com/ruby/rbs/pull/323)
37
+
5
38
  ## 0.5.0 (2020-07-04)
6
39
 
7
40
  * Signature updates for `Mutex_m`, `IO`, and `Enumerable`.
data/Gemfile CHANGED
@@ -13,6 +13,8 @@ gem "minitest-reporters"
13
13
  gem "json"
14
14
  gem "json-schema"
15
15
  gem 'stackprof'
16
+ gem "goodcheck"
16
17
 
17
18
  # Test gems
18
19
  gem "rbs-amber", path: "test/assets/test-gem"
20
+
data/Rakefile CHANGED
@@ -78,11 +78,10 @@ namespace :generate do
78
78
  def call
79
79
  ERB.new(<<~ERB, trim_mode: "-").result(binding)
80
80
  require_relative "test_helper"
81
- require 'rbs/test/test_helper'
82
81
 
83
82
  <%- unless class_methods.empty? -%>
84
83
  class <%= klass %>SingletonTest < Minitest::Test
85
- include RBS::Test::TypeAssertions
84
+ include TypeAssertions
86
85
 
87
86
  # library "pathname", "set", "securerandom" # Declare library signatures to load
88
87
  testing "singleton(::<%= klass %>)"
@@ -100,7 +99,7 @@ namespace :generate do
100
99
 
101
100
  <%- unless instance_methods.empty? -%>
102
101
  class <%= klass %>Test < Minitest::Test
103
- include RBS::Test::TypeAssertions
102
+ include TypeAssertions
104
103
 
105
104
  # library "pathname", "set", "securerandom" # Declare library signatures to load
106
105
  testing "::<%= klass %>"
@@ -120,7 +120,6 @@ The test scripts would look like the following:
120
120
  ```rb
121
121
  class StringTest < StdlibTest
122
122
  target String
123
- using hook.refinement
124
123
 
125
124
  def test_gsub
126
125
  s = "string"
@@ -136,7 +135,6 @@ end
136
135
 
137
136
  You need two method calls, `target` and `using`.
138
137
  `target` method call tells which class is the subject of the class.
139
- `using hook.refinement` installs a special instrumentation for stdlib, based on refinements.
140
138
  And you write the sample programs which calls all of the patterns of overloads.
141
139
 
142
140
  Note that the instrumentation is based on refinements and you need to write all method calls in the unit class definitions.
@@ -166,7 +166,7 @@ end
166
166
 
167
167
  ### Proc type
168
168
 
169
- Proc type denots type of procedures, `Proc` instances.
169
+ Proc type denotes type of procedures, `Proc` instances.
170
170
 
171
171
  ```
172
172
  ^(Integer) -> String # A procedure with an `Integer` parameter and returns `String`
@@ -348,7 +348,7 @@ attr_reader id: Integer
348
348
  # @id: Integer
349
349
  # def id: () -> Integer
350
350
 
351
- # Defines `name=` method and `raw_name` instance variable.
351
+ # Defines `name=` method and `@raw_name` instance variable.
352
352
  attr_writer name (@raw_name) : String
353
353
  # @raw_name: String
354
354
  # def name=: (String) -> String
@@ -408,7 +408,10 @@ _class-decl_ ::= `class` _class-name_ _module-type-parameters_ _members_ `end`
408
408
  | `class` _class-name_ _module-type-parameters_ `<` _class-name_ _type-arguments_ _members_ `end`
409
409
 
410
410
  _module-decl_ ::= `module` _module-name_ _module-type-parameters_ _members_ `end`
411
- | `module` _module-name_ _module-type-parameters_ `:` _class-name_ _type-arguments_ _members_ `end`
411
+ | `module` _module-name_ _module-type-parameters_ `:` _module-self-types_ _members_ `end`
412
+
413
+ _module-self-types_ ::= _class-name_ _type-arguments_ `,` _module-self-types_ (Class instance)
414
+ | _interface-name_ _type-arguments_ `,` _module-self-types_ (Interface)
412
415
 
413
416
  _interface-decl_ ::= `interface` _interface-name_ _module-type-parameters_ _interface-members_ `end`
414
417
 
@@ -0,0 +1,65 @@
1
+ rules:
2
+ - id: rbs.no_mark
3
+ pattern: 💪👽🚨
4
+ message: Do you forget to delete `arglists` section?
5
+ glob:
6
+ - "stdlib/**/*.rbs"
7
+ fail:
8
+ - |
9
+ # arglists 💪👽🚨 << Delete this section
10
+ # File.absolute_path?(file_name) -> true or false
11
+ #
12
+
13
+ - id: rbs.no_arg
14
+ pattern:
15
+ regexp: arg\d+
16
+ message: |
17
+ Stop using parameter names like `arg0` or `arg1`
18
+
19
+ The parameter names like `arg0` or `arg1` is not informative enough.
20
+ Try finding good parameter names from documents or arglists.
21
+ If you cannot find a good name, just delete the name of the parameters.
22
+ justification:
23
+ - Documents (comments) may contain that pattern.
24
+ glob:
25
+ - "stdlib/**/*.rbs"
26
+ fail:
27
+ - "def `send`: (String | Symbol arg0, *untyped arg1) -> untyped"
28
+ pass:
29
+ - "def `send`: (String | Symbol, *untyped) -> untyped"
30
+
31
+ - id: deprecate_stdlib_test
32
+ pattern:
33
+ token: < StdlibTest
34
+ message: |
35
+ StdlibTest is deprecated
36
+
37
+ We recommend writing tests based on `TypeAssertions` and `#assert_send_type`.
38
+ justification:
39
+ - When you are updating existing tests.
40
+ - When you are writing tests for callback, which cannot be done with `#assert_send_type`.
41
+ glob:
42
+ - "test/stdlib/**/*_test.rb"
43
+ fail:
44
+ - |
45
+ class IntegerTest < StdlibTest
46
+ target Integer
47
+
48
+ def test_plus
49
+ 1 + 2
50
+ end
51
+ end
52
+ pass:
53
+ - |
54
+ class IntegerTest < Minitest::Test
55
+ include TypeAssertions
56
+
57
+ testing "Integer"
58
+
59
+ def test_plus
60
+ assert_send_type "(::Integer) -> ::Integer",
61
+ 1, :+, 2
62
+ end
63
+ end
64
+
65
+
data/lib/rbs.rb CHANGED
@@ -36,6 +36,7 @@ require "rbs/type_name_resolver"
36
36
  require "rbs/environment_walker"
37
37
  require "rbs/vendorer"
38
38
  require "rbs/validator"
39
+ require "rbs/factory"
39
40
 
40
41
  begin
41
42
  require "rbs/parser"
@@ -22,6 +22,12 @@ module RBS
22
22
  def to_json(*a)
23
23
  { string: string, location: location }.to_json(*a)
24
24
  end
25
+
26
+ def concat(string:, location:)
27
+ @string.concat string
28
+ @location.concat location
29
+ self
30
+ end
25
31
  end
26
32
  end
27
33
  end
@@ -204,6 +204,44 @@ module RBS
204
204
  end
205
205
 
206
206
  class Module < Base
207
+ class Self
208
+ attr_reader :name
209
+ attr_reader :args
210
+ attr_reader :location
211
+
212
+ def initialize(name:, args:, location:)
213
+ @name = name
214
+ @args = args
215
+ @location = location
216
+ end
217
+
218
+ def ==(other)
219
+ other.is_a?(Self) && other.name == name && other.args == args
220
+ end
221
+
222
+ alias eql? ==
223
+
224
+ def hash
225
+ self.class.hash ^ name.hash ^ args.hash ^ location.hash
226
+ end
227
+
228
+ def to_json(*a)
229
+ {
230
+ name: name,
231
+ args: args,
232
+ location: location
233
+ }.to_json(*a)
234
+ end
235
+
236
+ def to_s
237
+ if args.empty?
238
+ name.to_s
239
+ else
240
+ "#{name}[#{args.join(", ")}]"
241
+ end
242
+ end
243
+ end
244
+
207
245
  include NestedDeclarationHelper
208
246
  include MixinHelper
209
247
 
@@ -212,13 +250,13 @@ module RBS
212
250
  attr_reader :members
213
251
  attr_reader :location
214
252
  attr_reader :annotations
215
- attr_reader :self_type
253
+ attr_reader :self_types
216
254
  attr_reader :comment
217
255
 
218
- def initialize(name:, type_params:, members:, self_type:, annotations:, location:, comment:)
256
+ def initialize(name:, type_params:, members:, self_types:, annotations:, location:, comment:)
219
257
  @name = name
220
258
  @type_params = type_params
221
- @self_type = self_type
259
+ @self_types = self_types
222
260
  @members = members
223
261
  @annotations = annotations
224
262
  @location = location
@@ -229,14 +267,14 @@ module RBS
229
267
  other.is_a?(Module) &&
230
268
  other.name == name &&
231
269
  other.type_params == type_params &&
232
- other.self_type == self_type &&
270
+ other.self_types == self_types &&
233
271
  other.members == members
234
272
  end
235
273
 
236
274
  alias eql? ==
237
275
 
238
276
  def hash
239
- self.class.hash ^ name.hash ^ type_params.hash ^ self_type.hash ^ members.hash
277
+ self.class.hash ^ name.hash ^ type_params.hash ^ self_types.hash ^ members.hash
240
278
  end
241
279
 
242
280
  def to_json(*a)
@@ -245,7 +283,7 @@ module RBS
245
283
  name: name,
246
284
  type_params: type_params,
247
285
  members: members,
248
- self_type: self_type,
286
+ self_types: self_types,
249
287
  annotations: annotations,
250
288
  location: location,
251
289
  comment: comment
@@ -66,6 +66,10 @@ module RBS
66
66
  opts
67
67
  end
68
68
 
69
+ def has_parser?
70
+ defined?(RubyVM::AbstractSyntaxTree)
71
+ end
72
+
69
73
  def run(args)
70
74
  options = LibraryOptions.new
71
75
 
@@ -409,6 +413,7 @@ EOU
409
413
  env.constant_decls.each do |name, const|
410
414
  stdout.puts "Validating constant: `#{name}`..."
411
415
  validator.validate_type const.decl.type, context: const.context
416
+ builder.ensure_namespace!(name.namespace, location: const.decl.location)
412
417
  end
413
418
 
414
419
  env.global_decls.each do |name, global|
@@ -418,7 +423,9 @@ EOU
418
423
 
419
424
  env.alias_decls.each do |name, decl|
420
425
  stdout.puts "Validating alias: `#{name}`..."
421
- validator.validate_type decl.decl.type, context: decl.context
426
+ builder.expand_alias(name).tap do |type|
427
+ validator.validate_type type, context: [Namespace.root]
428
+ end
422
429
  end
423
430
  end
424
431
 
@@ -599,12 +606,18 @@ EOU
599
606
  end
600
607
 
601
608
  def run_prototype_file(format, args)
609
+ availability = unless has_parser?
610
+ "\n** This command does not work on this interpreter (#{RUBY_ENGINE}) **\n"
611
+ end
612
+
602
613
  opts = OptionParser.new
603
614
  opts.banner = <<EOU
604
615
  Usage: rbs prototype #{format} [options...] [files...]
605
-
616
+ #{availability}
606
617
  Generate RBS prototype from source code.
607
- It parses specified Ruby code and and generates RBS prototypes.
618
+ It parses specified Ruby code and and generates RBS prototypes.
619
+
620
+ It only works on MRI because it parses Ruby code with `RubyVM::AbstractSyntaxTree`.
608
621
 
609
622
  Examples:
610
623
 
@@ -613,6 +626,11 @@ Examples:
613
626
  EOU
614
627
  opts.parse!(args)
615
628
 
629
+ unless has_parser?
630
+ stdout.puts "Not supported on this interpreter (#{RUBY_ENGINE})."
631
+ exit 1
632
+ end
633
+
616
634
  if args.empty?
617
635
  stdout.puts opts
618
636
  return nil
@@ -152,7 +152,7 @@ module RBS
152
152
  constant_scopes_module name, scopes: scopes
153
153
 
154
154
  else
155
- raise "Unexpected declaration: #{name} (#{decl.class})"
155
+ raise "Unexpected declaration: #{name} (#{entry.class})"
156
156
  end
157
157
 
158
158
  scopes
@@ -13,6 +13,77 @@ module RBS
13
13
  attr_reader :instance_ancestors_cache
14
14
  attr_reader :singleton_ancestor_cache
15
15
 
16
+ attr_reader :one_instance_ancestors_cache
17
+ attr_reader :one_singleton_ancestors_cache
18
+
19
+ class OneAncestors
20
+ attr_reader :type_name
21
+ attr_reader :params
22
+ attr_reader :super_class
23
+ attr_reader :self_types
24
+ attr_reader :included_modules
25
+ attr_reader :prepended_modules
26
+ attr_reader :extended_modules
27
+
28
+ def initialize(type_name:, params:, super_class:, self_types:, included_modules:, prepended_modules:, extended_modules:)
29
+ @type_name = type_name
30
+ @params = params
31
+ @super_class = super_class
32
+ @self_types = self_types
33
+ @included_modules = included_modules
34
+ @prepended_modules = prepended_modules
35
+ @extended_modules = extended_modules
36
+ end
37
+
38
+ def each_ancestor(&block)
39
+ if block_given?
40
+ yield super_class if super_class
41
+ self_types&.each(&block)
42
+ included_modules&.each(&block)
43
+ prepended_modules&.each(&block)
44
+ extended_modules&.each(&block)
45
+ else
46
+ enum_for :each_ancestor
47
+ end
48
+ end
49
+
50
+ def self.class_instance(type_name:, params:, super_class:)
51
+ new(
52
+ type_name: type_name,
53
+ params: params,
54
+ super_class: super_class,
55
+ self_types: nil,
56
+ included_modules: [],
57
+ prepended_modules: [],
58
+ extended_modules: nil
59
+ )
60
+ end
61
+
62
+ def self.singleton(type_name:, super_class:)
63
+ new(
64
+ type_name: type_name,
65
+ params: nil,
66
+ super_class: super_class,
67
+ self_types: nil,
68
+ included_modules: nil,
69
+ prepended_modules: nil,
70
+ extended_modules: []
71
+ )
72
+ end
73
+
74
+ def self.module_instance(type_name:, params:)
75
+ new(
76
+ type_name: type_name,
77
+ params: params,
78
+ self_types: [],
79
+ included_modules: [],
80
+ prepended_modules: [],
81
+ super_class: nil,
82
+ extended_modules: nil
83
+ )
84
+ end
85
+ end
86
+
16
87
  def initialize(env:)
17
88
  @env = env
18
89
  @type_name_resolver = TypeNameResolver.from_env(env)
@@ -26,6 +97,9 @@ module RBS
26
97
 
27
98
  @instance_ancestors_cache = {}
28
99
  @singleton_ancestor_cache = {}
100
+
101
+ @one_instance_ancestors_cache = {}
102
+ @one_singleton_ancestors_cache = {}
29
103
  end
30
104
 
31
105
  def validate_super_class!(type_name, entry)
@@ -45,30 +119,19 @@ module RBS
45
119
  raise SuperclassMismatchError.new(name: type_name, super_classes: super_types, entry: entry)
46
120
  end
47
121
 
48
- def instance_ancestors(type_name, building_ancestors: [])
49
- as = instance_ancestors_cache[type_name] and return as
122
+ def one_instance_ancestors(type_name)
123
+ as = one_instance_ancestors_cache[type_name] and return as
50
124
 
51
- entry = env.class_decls[type_name]
125
+ entry = env.class_decls[type_name] or raise "Unknown name for one_instance_ancestors: #{type_name}"
52
126
  params = entry.type_params.each.map(&:name)
53
- args = Types::Variable.build(params)
54
- self_ancestor = Definition::Ancestor::Instance.new(name: type_name, args: args)
55
-
56
- RecursiveAncestorError.check!(self_ancestor,
57
- ancestors: building_ancestors,
58
- location: entry.primary.decl.location)
59
- building_ancestors.push self_ancestor
60
-
61
- ancestors = []
62
127
 
63
128
  case entry
64
129
  when Environment::ClassEntry
65
130
  validate_super_class!(type_name, entry)
131
+ primary = entry.primary
132
+ super_class = primary.decl.super_class
66
133
 
67
- # Super class comes last
68
- if self_ancestor.name != BuiltinNames::BasicObject.name
69
- primary = entry.primary
70
- super_class = primary.decl.super_class
71
-
134
+ if type_name != BuiltinNames::BasicObject.name
72
135
  if super_class
73
136
  super_name = super_class.name
74
137
  super_args = super_class.args
@@ -77,91 +140,88 @@ module RBS
77
140
  super_args = []
78
141
  end
79
142
 
80
- super_ancestors = instance_ancestors(super_name, building_ancestors: building_ancestors)
81
- ancestors.unshift(*super_ancestors.apply(super_args, location: primary.decl.location))
82
- end
83
-
84
- build_ancestors_mixin_self(self_ancestor, entry, ancestors: ancestors, building_ancestors: building_ancestors)
143
+ NoSuperclassFoundError.check!(super_name, env: env, location: primary.decl.location)
85
144
 
145
+ ancestors = OneAncestors.class_instance(
146
+ type_name: type_name,
147
+ params: params,
148
+ super_class: Definition::Ancestor::Instance.new(name: super_name, args: super_args)
149
+ )
150
+ else
151
+ ancestors = OneAncestors.class_instance(
152
+ type_name: type_name,
153
+ params: params,
154
+ super_class: nil
155
+ )
156
+ end
86
157
  when Environment::ModuleEntry
87
- build_ancestors_mixin_self(self_ancestor, entry, ancestors: ancestors, building_ancestors: building_ancestors)
158
+ ancestors = OneAncestors.module_instance(type_name: type_name, params: params)
88
159
 
160
+ entry.self_types.each do |module_self|
161
+ NoSelfTypeFoundError.check!(module_self, env: env)
162
+ ancestors.self_types.push Definition::Ancestor::Instance.new(name: module_self.name, args: module_self.args)
163
+ end
164
+ else
165
+ raise "Unexpected entry for: #{type_name}"
89
166
  end
90
167
 
91
- building_ancestors.pop
168
+ mixin_ancestors(entry,
169
+ included_modules: ancestors.included_modules,
170
+ prepended_modules: ancestors.prepended_modules,
171
+ extended_modules: nil)
92
172
 
93
- instance_ancestors_cache[type_name] = Definition::InstanceAncestors.new(
94
- type_name: type_name,
95
- params: params,
96
- ancestors: ancestors
97
- )
173
+ one_instance_ancestors_cache[type_name] = ancestors
98
174
  end
99
175
 
100
- def singleton_ancestors(type_name, building_ancestors: [])
101
- as = singleton_ancestor_cache[type_name] and return as
176
+ def one_singleton_ancestors(type_name)
177
+ as = one_singleton_ancestors_cache[type_name] and return as
102
178
 
103
- entry = env.class_decls[type_name]
104
- self_ancestor = Definition::Ancestor::Singleton.new(name: type_name)
105
-
106
- RecursiveAncestorError.check!(self_ancestor,
107
- ancestors: building_ancestors,
108
- location: entry.primary.decl.location)
109
- building_ancestors.push self_ancestor
110
-
111
- ancestors = []
179
+ entry = env.class_decls[type_name] or raise "Unknown name for one_singleton_ancestors: #{type_name}"
112
180
 
113
181
  case entry
114
182
  when Environment::ClassEntry
115
- # Super class comes last
116
- if self_ancestor.name != BuiltinNames::BasicObject.name
117
- primary = entry.primary
118
- super_class = primary.decl.super_class
183
+ validate_super_class!(type_name, entry)
184
+ primary = entry.primary
185
+ super_class = primary.decl.super_class
119
186
 
187
+ if type_name != BuiltinNames::BasicObject.name
120
188
  if super_class
121
189
  super_name = super_class.name
122
190
  else
123
191
  super_name = BuiltinNames::Object.name
124
192
  end
125
193
 
126
- super_ancestors = singleton_ancestors(super_name, building_ancestors: building_ancestors)
127
- ancestors.unshift(*super_ancestors.ancestors)
194
+ NoSuperclassFoundError.check!(super_name, env: env, location: primary.decl.location)
195
+
196
+ ancestors = OneAncestors.singleton(
197
+ type_name: type_name,
198
+ super_class: Definition::Ancestor::Singleton.new(name: super_name)
199
+ )
128
200
  else
129
- as = instance_ancestors(BuiltinNames::Class.name, building_ancestors: building_ancestors)
130
- ancestors.unshift(*as.apply([], location: entry.primary.decl.location))
201
+ ancestors = OneAncestors.singleton(
202
+ type_name: type_name,
203
+ super_class: Definition::Ancestor::Instance.new(name: BuiltinNames::Class.name, args: [])
204
+ )
131
205
  end
132
-
133
206
  when Environment::ModuleEntry
134
- as = instance_ancestors(BuiltinNames::Module.name, building_ancestors: building_ancestors)
135
- ancestors.unshift(*as.apply([], location: entry.primary.decl.location))
136
- end
137
-
138
- # Extend comes next
139
- entry.decls.each do |d|
140
- decl = d.decl
207
+ ancestors = OneAncestors.singleton(
208
+ type_name: type_name,
209
+ super_class: Definition::Ancestor::Instance.new(name: BuiltinNames::Module.name, args: [])
210
+ )
141
211
 
142
- decl.each_mixin do |member|
143
- case member
144
- when AST::Members::Extend
145
- if member.name.class?
146
- module_ancestors = instance_ancestors(member.name, building_ancestors: building_ancestors)
147
- ancestors.unshift(*module_ancestors.apply(member.args, location: member.location))
148
- end
149
- end
150
- end
212
+ else
213
+ raise "Unexpected entry for: #{type_name}"
151
214
  end
152
215
 
153
- ancestors.unshift self_ancestor
154
-
155
- building_ancestors.pop
216
+ mixin_ancestors(entry,
217
+ included_modules: nil,
218
+ prepended_modules: nil,
219
+ extended_modules: ancestors.extended_modules)
156
220
 
157
- singleton_ancestor_cache[type_name] = Definition::SingletonAncestors.new(
158
- type_name: type_name,
159
- ancestors: ancestors
160
- )
221
+ one_singleton_ancestors_cache[type_name] = ancestors
161
222
  end
162
223
 
163
- def build_ancestors_mixin_self(self_ancestor, entry, ancestors:, building_ancestors:)
164
- # Include comes next
224
+ def mixin_ancestors(entry, included_modules:, extended_modules:, prepended_modules:)
165
225
  entry.decls.each do |d|
166
226
  decl = d.decl
167
227
 
@@ -173,38 +233,143 @@ module RBS
173
233
  decl.each_mixin do |member|
174
234
  case member
175
235
  when AST::Members::Include
176
- if member.name.class?
236
+ if included_modules
237
+ NoMixinFoundError.check!(member.name, env: env, member: member)
238
+
239
+ module_name = member.name
240
+ module_args = member.args.map {|type| type.sub(align_params) }
241
+
242
+ included_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args)
243
+ end
244
+
245
+ when AST::Members::Prepend
246
+ if prepended_modules
247
+ NoMixinFoundError.check!(member.name, env: env, member: member)
248
+
177
249
  module_name = member.name
178
250
  module_args = member.args.map {|type| type.sub(align_params) }
179
251
 
180
- module_ancestors = instance_ancestors(module_name, building_ancestors: building_ancestors)
181
- ancestors.unshift(*module_ancestors.apply(module_args, location: member.location))
252
+ prepended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args)
253
+ end
254
+
255
+ when AST::Members::Extend
256
+ if extended_modules
257
+ NoMixinFoundError.check!(member.name, env: env, member: member)
258
+
259
+ module_name = member.name
260
+ module_args = member.args
261
+
262
+ extended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args)
182
263
  end
183
264
  end
184
265
  end
185
266
  end
267
+ end
268
+
269
+ def instance_ancestors(type_name, building_ancestors: [])
270
+ as = instance_ancestors_cache[type_name] and return as
271
+
272
+ entry = env.class_decls[type_name] or raise "Unknown name for instance_ancestors: #{type_name}"
273
+ params = entry.type_params.each.map(&:name)
274
+ args = Types::Variable.build(params)
275
+ self_ancestor = Definition::Ancestor::Instance.new(name: type_name, args: args)
276
+
277
+ RecursiveAncestorError.check!(self_ancestor,
278
+ ancestors: building_ancestors,
279
+ location: entry.primary.decl.location)
280
+ building_ancestors.push self_ancestor
281
+
282
+ one_ancestors = one_instance_ancestors(type_name)
283
+
284
+ ancestors = []
285
+
286
+ case entry
287
+ when Environment::ClassEntry
288
+ if one_ancestors.super_class
289
+ super_name = one_ancestors.super_class.name
290
+ super_args = one_ancestors.super_class.args
291
+
292
+ super_ancestors = instance_ancestors(super_name, building_ancestors: building_ancestors)
293
+ ancestors.unshift(*super_ancestors.apply(super_args, location: entry.primary.decl.location))
294
+ end
295
+ end
296
+
297
+ one_ancestors.included_modules.each do |mod|
298
+ if mod.name.class?
299
+ name = mod.name
300
+ args = mod.args
301
+ mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors)
302
+ ancestors.unshift(*mod_ancestors.apply(args, location: entry.primary.decl.location))
303
+ end
304
+ end
186
305
 
187
- # Self
188
306
  ancestors.unshift(self_ancestor)
189
307
 
190
- # Prepends
191
- entry.decls.each do |d|
192
- decl = d.decl
308
+ one_ancestors.prepended_modules.each do |mod|
309
+ if mod.name.class?
310
+ name = mod.name
311
+ args = mod.args
312
+ mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors)
313
+ ancestors.unshift(*mod_ancestors.apply(args, location: entry.primary.decl.location))
314
+ end
315
+ end
193
316
 
194
- align_params = Substitution.build(decl.type_params.each.map(&:name),
195
- Types::Variable.build(entry.type_params.each.map(&:name)))
317
+ building_ancestors.pop
196
318
 
197
- decl.each_mixin do |member|
198
- case member
199
- when AST::Members::Prepend
200
- module_name = member.name
201
- module_args = member.args.map {|type| type.sub(align_params) }
319
+ instance_ancestors_cache[type_name] = Definition::InstanceAncestors.new(
320
+ type_name: type_name,
321
+ params: params,
322
+ ancestors: ancestors
323
+ )
324
+ end
202
325
 
203
- module_ancestors = instance_ancestors(module_name, building_ancestors: building_ancestors)
204
- ancestors.unshift(*module_ancestors.apply(module_args))
205
- end
326
+ def singleton_ancestors(type_name, building_ancestors: [])
327
+ as = singleton_ancestor_cache[type_name] and return as
328
+
329
+ entry = env.class_decls[type_name] or raise "Unknown name for singleton_ancestors: #{type_name}"
330
+ self_ancestor = Definition::Ancestor::Singleton.new(name: type_name)
331
+
332
+ RecursiveAncestorError.check!(self_ancestor,
333
+ ancestors: building_ancestors,
334
+ location: entry.primary.decl.location)
335
+ building_ancestors.push self_ancestor
336
+
337
+ one_ancestors = one_singleton_ancestors(type_name)
338
+
339
+ ancestors = []
340
+
341
+ case one_ancestors.super_class
342
+ when Definition::Ancestor::Instance
343
+ super_name = one_ancestors.super_class.name
344
+ super_args = one_ancestors.super_class.args
345
+
346
+ super_ancestors = instance_ancestors(super_name, building_ancestors: building_ancestors)
347
+ ancestors.unshift(*super_ancestors.apply(super_args, location: entry.primary.decl.location))
348
+
349
+ when Definition::Ancestor::Singleton
350
+ super_name = one_ancestors.super_class.name
351
+
352
+ super_ancestors = singleton_ancestors(super_name, building_ancestors: [])
353
+ ancestors.unshift(*super_ancestors.ancestors)
354
+ end
355
+
356
+ one_ancestors.extended_modules.each do |mod|
357
+ if mod.name.class?
358
+ name = mod.name
359
+ args = mod.args
360
+ mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors)
361
+ ancestors.unshift(*mod_ancestors.apply(args, location: entry.primary.decl.location))
206
362
  end
207
363
  end
364
+
365
+ ancestors.unshift(self_ancestor)
366
+
367
+ building_ancestors.pop
368
+
369
+ singleton_ancestor_cache[type_name] = Definition::SingletonAncestors.new(
370
+ type_name: type_name,
371
+ ancestors: ancestors
372
+ )
208
373
  end
209
374
 
210
375
  def each_member_with_accessibility(members, accessibility: :public)
@@ -220,9 +385,18 @@ module RBS
220
385
  end
221
386
  end
222
387
 
388
+ def ensure_namespace!(namespace, location:)
389
+ namespace.ascend do |ns|
390
+ unless ns.empty?
391
+ NoTypeFoundError.check!(ns.to_type_name, env: env, location: location)
392
+ end
393
+ end
394
+ end
395
+
223
396
  def build_instance(type_name)
224
397
  try_cache type_name, cache: instance_cache do
225
- entry = env.class_decls[type_name]
398
+ entry = env.class_decls[type_name] or raise "Unknown name for build_instance: #{type_name}"
399
+ ensure_namespace!(type_name.namespace, location: entry.decls[0].decl.location)
226
400
 
227
401
  case entry
228
402
  when Environment::ClassEntry, Environment::ModuleEntry
@@ -243,11 +417,18 @@ module RBS
243
417
  end
244
418
 
245
419
  if entry.is_a?(Environment::ModuleEntry)
246
- if self_type_ancestor = module_self_ancestor(type_name, entry)
247
- definition_pairs.push [
248
- self_type_ancestor,
249
- build_interface(self_type_ancestor.name)
250
- ]
420
+ entry.self_types.each do |module_self|
421
+ ancestor = Definition::Ancestor::Instance.new(name: module_self.name, args: module_self.args)
422
+ definition_pairs.push(
423
+ [
424
+ ancestor,
425
+ if module_self.name.interface?
426
+ build_interface(module_self.name)
427
+ else
428
+ build_instance(module_self.name)
429
+ end
430
+ ]
431
+ )
251
432
  end
252
433
  end
253
434
 
@@ -259,32 +440,10 @@ module RBS
259
440
  end
260
441
  end
261
442
 
262
- def module_self_ancestor(type_name, entry)
263
- self_decls = entry.decls.select {|d| d.decl.self_type }
264
-
265
- return if self_decls.empty?
266
-
267
- selfs = self_decls.map do |d|
268
- Definition::Ancestor::Instance.new(
269
- name: d.decl.self_type.name,
270
- args: d.decl.self_type.args
271
- )
272
- end
273
-
274
- selfs.uniq!
275
-
276
- return selfs[0] if selfs.size == 1
277
-
278
- raise ModuleSelfTypeMismatchError.new(
279
- name: type_name,
280
- entry: entry,
281
- location: self_decls[0].decl.location
282
- )
283
- end
284
-
285
443
  def build_singleton(type_name)
286
444
  try_cache type_name, cache: singleton_cache do
287
- entry = env.class_decls[type_name]
445
+ entry = env.class_decls[type_name] or raise "Unknown name for build_singleton: #{type_name}"
446
+ ensure_namespace!(type_name.namespace, location: entry.decls[0].decl.location)
288
447
 
289
448
  case entry
290
449
  when Environment::ClassEntry, Environment::ModuleEntry
@@ -350,6 +509,8 @@ module RBS
350
509
  when AST::Members::Include, AST::Members::Extend
351
510
  if member.name.interface?
352
511
  if (kind == :instance && member.is_a?(AST::Members::Include)) || (kind == :singleton && member.is_a?(AST::Members::Extend))
512
+ NoMixinFoundError.check!(member.name, env: env, member: member)
513
+
353
514
  interface_name = member.name
354
515
  interface_args = member.args
355
516
 
@@ -842,7 +1003,7 @@ module RBS
842
1003
  methods[name] = Definition::Method.new(
843
1004
  super_method: super_method,
844
1005
  accessibility: method.accessibility,
845
- defs: method.defs.map {|defn| defn.update(type: defn.type.sub(sub)) }
1006
+ defs: sub.mapping.empty? ? method.defs : method.defs.map {|defn| defn.update(type: defn.type.sub(sub)) }
846
1007
  )
847
1008
  end
848
1009
 
@@ -867,8 +1028,9 @@ module RBS
867
1028
 
868
1029
  def build_interface(type_name)
869
1030
  try_cache(type_name, cache: interface_cache) do
870
- entry = env.interface_decls[type_name]
1031
+ entry = env.interface_decls[type_name] or raise "Unknown name for build_interface: #{type_name}"
871
1032
  declaration = entry.decl
1033
+ ensure_namespace!(type_name.namespace, location: declaration.location)
872
1034
 
873
1035
  self_type = Types::Interface.new(
874
1036
  name: type_name,
@@ -893,6 +1055,8 @@ module RBS
893
1055
  end
894
1056
 
895
1057
  include_members.each do |member|
1058
+ NoMixinFoundError.check!(member.name, env: env, member: member)
1059
+
896
1060
  mixin = build_interface(member.name)
897
1061
 
898
1062
  args = member.args
@@ -957,7 +1121,9 @@ module RBS
957
1121
  end
958
1122
 
959
1123
  def expand_alias(type_name)
960
- env.alias_decls[type_name].decl.type
1124
+ entry = env.alias_decls[type_name] or raise "Unknown name for expand_alias: #{type_name}"
1125
+ ensure_namespace!(type_name.namespace, location: entry.decl.location)
1126
+ entry.decl.type
961
1127
  end
962
1128
  end
963
1129
  end