rbs 0.5.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/Gemfile +2 -0
- data/Rakefile +2 -3
- data/docs/stdlib.md +0 -2
- data/docs/syntax.md +6 -3
- data/goodcheck.yml +65 -0
- data/lib/rbs.rb +1 -0
- data/lib/rbs/ast/comment.rb +6 -0
- data/lib/rbs/ast/declarations.rb +44 -6
- data/lib/rbs/cli.rb +21 -3
- data/lib/rbs/constant_table.rb +1 -1
- data/lib/rbs/definition_builder.rb +290 -124
- data/lib/rbs/environment.rb +50 -37
- data/lib/rbs/errors.rb +68 -25
- data/lib/rbs/factory.rb +14 -0
- data/lib/rbs/location.rb +15 -0
- data/lib/rbs/parser.y +89 -28
- data/lib/rbs/prototype/rb.rb +2 -2
- data/lib/rbs/prototype/rbi.rb +1 -1
- data/lib/rbs/prototype/runtime.rb +1 -1
- data/lib/rbs/substitution.rb +6 -2
- data/lib/rbs/test.rb +82 -3
- data/lib/rbs/test/errors.rb +5 -1
- data/lib/rbs/test/hook.rb +133 -259
- data/lib/rbs/test/observer.rb +17 -0
- data/lib/rbs/test/setup.rb +37 -20
- data/lib/rbs/test/setup_helper.rb +29 -0
- data/lib/rbs/test/spy.rb +0 -321
- data/lib/rbs/test/tester.rb +118 -0
- data/lib/rbs/test/type_check.rb +42 -5
- data/lib/rbs/validator.rb +4 -0
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +2 -2
- data/schema/decls.json +21 -10
- data/stdlib/builtin/enumerable.rbs +2 -2
- data/stdlib/builtin/proc.rbs +1 -2
- data/stdlib/json/json.rbs +6 -0
- data/stdlib/logger/formatter.rbs +23 -0
- data/stdlib/logger/log_device.rbs +39 -0
- data/stdlib/logger/logger.rbs +507 -0
- data/stdlib/logger/period.rbs +7 -0
- data/stdlib/logger/severity.rbs +8 -0
- data/stdlib/pty/pty.rbs +159 -0
- metadata +13 -3
- data/lib/rbs/test/test_helper.rb +0 -180
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '094182e5d2602ec5ba9244068f67f854dfd5aa9c804fe48f2e943934da3e806b'
|
4
|
+
data.tar.gz: bbd2a02e2c79a092f3e3555337aebdb557301fd2dd712bc46bcfaaa3ae4f3ed5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8de689c6af71a94ef511cd5efc9b64d1277f99256e759ec58ad4185505831e3ca041a8555f454ea6700713a4f03a88caeed2104009b8915b9acf5c8b4e5ba53b
|
7
|
+
data.tar.gz: dec9ab30d0d1261897103b71c7203d3857c2cd4150ef145f3b8f3d005b7ba3f9daa947033a1db37c7f7aaf7530725f9129707d29def747fe9334a75acbcc9a16
|
data/CHANGELOG.md
CHANGED
@@ -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
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
|
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
|
102
|
+
include TypeAssertions
|
104
103
|
|
105
104
|
# library "pathname", "set", "securerandom" # Declare library signatures to load
|
106
105
|
testing "::<%= klass %>"
|
data/docs/stdlib.md
CHANGED
@@ -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.
|
data/docs/syntax.md
CHANGED
@@ -166,7 +166,7 @@ end
|
|
166
166
|
|
167
167
|
### Proc type
|
168
168
|
|
169
|
-
Proc type
|
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
|
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_ `:`
|
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
|
|
data/goodcheck.yml
ADDED
@@ -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
data/lib/rbs/ast/comment.rb
CHANGED
data/lib/rbs/ast/declarations.rb
CHANGED
@@ -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 :
|
253
|
+
attr_reader :self_types
|
216
254
|
attr_reader :comment
|
217
255
|
|
218
|
-
def initialize(name:, type_params:, members:,
|
256
|
+
def initialize(name:, type_params:, members:, self_types:, annotations:, location:, comment:)
|
219
257
|
@name = name
|
220
258
|
@type_params = type_params
|
221
|
-
@
|
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.
|
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 ^
|
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
|
-
|
286
|
+
self_types: self_types,
|
249
287
|
annotations: annotations,
|
250
288
|
location: location,
|
251
289
|
comment: comment
|
data/lib/rbs/cli.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/rbs/constant_table.rb
CHANGED
@@ -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
|
49
|
-
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
168
|
+
mixin_ancestors(entry,
|
169
|
+
included_modules: ancestors.included_modules,
|
170
|
+
prepended_modules: ancestors.prepended_modules,
|
171
|
+
extended_modules: nil)
|
92
172
|
|
93
|
-
|
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
|
101
|
-
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
|
-
|
116
|
-
|
117
|
-
|
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
|
-
|
127
|
-
|
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
|
-
|
130
|
-
|
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
|
-
|
135
|
-
|
136
|
-
|
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
|
-
|
143
|
-
|
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
|
-
|
154
|
-
|
155
|
-
|
216
|
+
mixin_ancestors(entry,
|
217
|
+
included_modules: nil,
|
218
|
+
prepended_modules: nil,
|
219
|
+
extended_modules: ancestors.extended_modules)
|
156
220
|
|
157
|
-
|
158
|
-
type_name: type_name,
|
159
|
-
ancestors: ancestors
|
160
|
-
)
|
221
|
+
one_singleton_ancestors_cache[type_name] = ancestors
|
161
222
|
end
|
162
223
|
|
163
|
-
def
|
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
|
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
|
-
|
181
|
-
|
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
|
-
|
191
|
-
|
192
|
-
|
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
|
-
|
195
|
-
Types::Variable.build(entry.type_params.each.map(&:name)))
|
317
|
+
building_ancestors.pop
|
196
318
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
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
|
-
|
204
|
-
|
205
|
-
|
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
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
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]
|
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
|