rbs 1.0.0.pre → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +10 -4
- data/CHANGELOG.md +41 -6
- data/Gemfile +7 -2
- data/README.md +1 -1
- data/Rakefile +11 -4
- data/Steepfile +2 -1
- data/bin/annotate-with-rdoc +0 -4
- data/bin/test_runner.rb +4 -5
- data/core/encoding.rbs +1 -1
- data/core/file.rbs +4 -0
- data/core/io.rbs +81 -5
- data/core/kernel.rbs +56 -56
- data/core/module.rbs +43 -2
- data/core/unbound_method.rbs +16 -0
- data/docs/CONTRIBUTING.md +2 -2
- data/docs/stdlib.md +50 -12
- data/docs/syntax.md +0 -17
- data/goodcheck.yml +3 -3
- data/lib/rbs/ast/declarations.rb +0 -47
- data/lib/rbs/definition_builder.rb +102 -64
- data/lib/rbs/definition_builder/ancestor_builder.rb +52 -3
- data/lib/rbs/environment.rb +1 -7
- data/lib/rbs/environment_loader.rb +7 -3
- data/lib/rbs/errors.rb +22 -57
- data/lib/rbs/parser.rb +1003 -1027
- data/lib/rbs/parser.y +12 -21
- data/lib/rbs/prototype/rb.rb +18 -4
- data/lib/rbs/prototype/runtime.rb +30 -14
- data/lib/rbs/test/hook.rb +7 -6
- data/lib/rbs/test/setup_helper.rb +0 -1
- data/lib/rbs/types.rb +6 -2
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +4 -3
- data/rbs.gemspec +1 -0
- data/sig/ancestor_builder.rbs +98 -0
- data/sig/declarations.rbs +4 -16
- data/sig/definition_builder.rbs +17 -71
- data/sig/errors.rbs +141 -2
- data/sig/method_builder.rbs +71 -0
- data/sig/substitution.rbs +3 -0
- data/sig/types.rbs +1 -15
- data/stdlib/csv/0/csv.rbs +3 -0
- data/stdlib/fileutils/0/fileutils.rbs +585 -0
- data/stdlib/pathname/0/pathname.rbs +2 -2
- data/stdlib/prettyprint/0/prettyprint.rbs +366 -0
- data/stdlib/prime/0/prime.rbs +6 -0
- data/stdlib/securerandom/0/securerandom.rbs +2 -0
- data/stdlib/uri/0/common.rbs +1 -1
- metadata +10 -7
- data/core/data.rbs +0 -5
data/core/module.rbs
CHANGED
@@ -259,7 +259,7 @@ class Module < Object
|
|
259
259
|
# or method `code' for Thing:Class
|
260
260
|
#
|
261
261
|
def class_eval: (String arg0, ?String filename, ?Integer lineno) -> untyped
|
262
|
-
| [U]
|
262
|
+
| [U] { (self m) -> U } -> U
|
263
263
|
|
264
264
|
# Evaluates the given block in the context of the class/module. The method
|
265
265
|
# defined in the block will belong to the receiver. Any arguments passed to the
|
@@ -443,6 +443,47 @@ class Module < Object
|
|
443
443
|
#
|
444
444
|
def const_set: (Symbol | String arg0, untyped arg1) -> untyped
|
445
445
|
|
446
|
+
# Returns the Ruby source filename and line number containing first definition
|
447
|
+
# of constant specified. If the named constant is not found, `nil` is returned.
|
448
|
+
# If the constant is found, but its source location can not be extracted
|
449
|
+
# (constant is defined in C code), empty array is returned.
|
450
|
+
#
|
451
|
+
# *inherit* specifies whether to lookup in `mod.ancestors` (`true` by default).
|
452
|
+
#
|
453
|
+
# # test.rb:
|
454
|
+
# class A
|
455
|
+
# C1 = 1
|
456
|
+
# end
|
457
|
+
#
|
458
|
+
# module M
|
459
|
+
# C2 = 2
|
460
|
+
# end
|
461
|
+
#
|
462
|
+
# class B < A
|
463
|
+
# include M
|
464
|
+
# C3 = 3
|
465
|
+
# end
|
466
|
+
#
|
467
|
+
# class A # continuation of A definition
|
468
|
+
# end
|
469
|
+
#
|
470
|
+
# p B.const_source_location('C3') # => ["test.rb", 11]
|
471
|
+
# p B.const_source_location('C2') # => ["test.rb", 6]
|
472
|
+
# p B.const_source_location('C1') # => ["test.rb", 2]
|
473
|
+
#
|
474
|
+
# p B.const_source_location('C2', false) # => nil -- don't lookup in ancestors
|
475
|
+
#
|
476
|
+
# p Object.const_source_location('B') # => ["test.rb", 9]
|
477
|
+
# p Object.const_source_location('A') # => ["test.rb", 1] -- note it is first entry, not "continuation"
|
478
|
+
#
|
479
|
+
# p B.const_source_location('A') # => ["test.rb", 1] -- because Object is in ancestors
|
480
|
+
# p M.const_source_location('A') # => ["test.rb", 1] -- Object is not ancestor, but additionally checked for modules
|
481
|
+
#
|
482
|
+
# p Object.const_source_location('A::C1') # => ["test.rb", 2] -- nesting is supported
|
483
|
+
# p Object.const_source_location('String') # => [] -- constant is defined in C code
|
484
|
+
#
|
485
|
+
def const_source_location: (Symbol | String name, ?boolish inherit) -> ([String, Integer] | [ ] | nil)
|
486
|
+
|
446
487
|
# Returns an array of the names of the constants accessible in *mod*. This
|
447
488
|
# includes the names of constants in any included modules (example at start of
|
448
489
|
# section), unless the *inherit* parameter is set to `false`.
|
@@ -752,7 +793,7 @@ class Module < Object
|
|
752
793
|
# or method `code' for Thing:Class
|
753
794
|
#
|
754
795
|
def module_eval: (String arg0, ?String filename, ?Integer lineno) -> untyped
|
755
|
-
| [U]
|
796
|
+
| [U] { (self m) -> U } -> U
|
756
797
|
|
757
798
|
# Evaluates the given block in the context of the class/module. The method
|
758
799
|
# defined in the block will belong to the receiver. Any arguments passed to the
|
data/core/unbound_method.rbs
CHANGED
@@ -150,4 +150,20 @@ class UnboundMethod
|
|
150
150
|
# if there is no method on superclass.
|
151
151
|
#
|
152
152
|
def super_method: () -> UnboundMethod?
|
153
|
+
|
154
|
+
# Returns the original name of the method.
|
155
|
+
#
|
156
|
+
# class C
|
157
|
+
# def foo; end
|
158
|
+
# alias bar foo
|
159
|
+
# end
|
160
|
+
# C.instance_method(:bar).original_name # => :foo
|
161
|
+
#
|
162
|
+
def original_name: () -> Symbol
|
163
|
+
|
164
|
+
# Bind *umeth* to *recv* and then invokes the method with the specified
|
165
|
+
# arguments. This is semantically equivalent to `umeth.bind(recv).call(args,
|
166
|
+
# ...)`.
|
167
|
+
#
|
168
|
+
def bind_call: (untyped recv, *untyped args) ?{ (*untyped) -> untyped } -> untyped
|
153
169
|
end
|
data/docs/CONTRIBUTING.md
CHANGED
@@ -49,12 +49,12 @@ You may find the *Good for first contributor* column where you can find some cla
|
|
49
49
|
* `--merge` tells to use the method types in RBS if exists.
|
50
50
|
* `rbs prototype runtime --merge --method-owner=Numeric Integer`
|
51
51
|
* You can use --method-owner if you want to print method of other classes too, for documentation purpose.
|
52
|
-
* `bin/annotate-with-rdoc
|
52
|
+
* `bin/annotate-with-rdoc core/string.rbs`
|
53
53
|
* Write comments using RDoc.
|
54
54
|
* It contains arglists section, but I don't think we should have it in RBS files.
|
55
55
|
* `bin/query-rdoc String#initialize`
|
56
56
|
* Print RDoc documents in the format you can copy-and-paste to RBS.
|
57
|
-
* `bin/sort
|
57
|
+
* `bin/sort core/string.rbs`
|
58
58
|
* Sort declarations members in RBS files.
|
59
59
|
* `rbs validate -r LIB`
|
60
60
|
Validate the syntax and some of the semantics.
|
data/docs/stdlib.md
CHANGED
@@ -11,7 +11,7 @@ The typical steps of writing signatures will be like the following:
|
|
11
11
|
|
12
12
|
## Signatures
|
13
13
|
|
14
|
-
Signatures for
|
14
|
+
Signatures for builtin libraries are located in `core` directory. Also, signatures for standard libraries are located in `stdlib` directory.
|
15
15
|
|
16
16
|
To write signatures see [syntax guide](syntax.md).
|
17
17
|
|
@@ -118,23 +118,61 @@ It generates `test/stdlib/[class_name]_test.rb`.
|
|
118
118
|
The test scripts would look like the following:
|
119
119
|
|
120
120
|
```rb
|
121
|
-
class
|
122
|
-
|
121
|
+
class StringSingletonTest < Test::Unit::TestCase
|
122
|
+
include TypeAssertions
|
123
|
+
|
124
|
+
testing "singleton(::String)"
|
125
|
+
|
126
|
+
def test_initialize
|
127
|
+
assert_send_type "() -> String",
|
128
|
+
String, :new
|
129
|
+
assert_send_type "(String) -> String",
|
130
|
+
String, :new, ""
|
131
|
+
assert_send_type "(String, encoding: Encoding) -> String",
|
132
|
+
String, :new, "", encoding: Encoding::ASCII_8BIT
|
133
|
+
assert_send_type "(String, encoding: Encoding, capacity: Integer) -> String",
|
134
|
+
String, :new, "", encoding: Encoding::ASCII_8BIT, capacity: 123
|
135
|
+
assert_send_type "(encoding: Encoding, capacity: Integer) -> String",
|
136
|
+
String, :new, encoding: Encoding::ASCII_8BIT, capacity: 123
|
137
|
+
assert_send_type "(ToStr) -> String",
|
138
|
+
String, :new, ToStr.new("")
|
139
|
+
assert_send_type "(encoding: ToStr) -> String",
|
140
|
+
String, :new, encoding: ToStr.new('Shift_JIS')
|
141
|
+
assert_send_type "(capacity: ToInt) -> String",
|
142
|
+
String, :new, capacity: ToInt.new(123)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
class StringTest < Test::Unit::TestCase
|
147
|
+
include TypeAssertions
|
148
|
+
|
149
|
+
# library "pathname", "set", "securerandom" # Declare library signatures to load
|
150
|
+
testing "::String"
|
123
151
|
|
124
152
|
def test_gsub
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
153
|
+
assert_send_type "(Regexp, String) -> String",
|
154
|
+
"string", :gsub, /./, ""
|
155
|
+
assert_send_type "(String, String) -> String",
|
156
|
+
"string", :gsub, "a", "b"
|
157
|
+
assert_send_type "(Regexp) { (String) -> String } -> String",
|
158
|
+
"string", :gsub, /./ do |x| "" end
|
159
|
+
assert_send_type "(Regexp) { (String) -> ToS } -> String",
|
160
|
+
"string", :gsub, /./ do |x| ToS.new("") end
|
161
|
+
assert_send_type "(Regexp, Hash[String, String]) -> String",
|
162
|
+
"string", :gsub, /./, {"foo" => "bar"}
|
163
|
+
assert_send_type "(Regexp) -> Enumerator[String, self]",
|
164
|
+
"string", :gsub, /./
|
165
|
+
assert_send_type "(String) -> Enumerator[String, self]",
|
166
|
+
"string", :gsub, ""
|
167
|
+
assert_send_type "(ToStr, ToStr) -> String",
|
168
|
+
"string", :gsub, ToStr.new("a"), ToStr.new("b")
|
132
169
|
end
|
133
170
|
end
|
134
171
|
```
|
135
172
|
|
136
|
-
You need
|
137
|
-
`
|
173
|
+
You need include `TypeAssertions` which provide useful methods for you.
|
174
|
+
`testing` method call tells which class is the subject of the class.
|
175
|
+
`assert_send_type` method call asserts to be valid types and confirms to be able to execute without exceptions.
|
138
176
|
And you write the sample programs which calls all of the patterns of overloads.
|
139
177
|
|
140
178
|
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
@@ -531,23 +531,6 @@ interface _Foo
|
|
531
531
|
end
|
532
532
|
```
|
533
533
|
|
534
|
-
### Extension declaration
|
535
|
-
|
536
|
-
Extension is to model _open class_.
|
537
|
-
|
538
|
-
```
|
539
|
-
extension Kernel (Pathname)
|
540
|
-
def Pathname: (String) -> Pathname
|
541
|
-
end
|
542
|
-
|
543
|
-
extension Array[A] (ActiveSupport)
|
544
|
-
def to: (Integer) -> Array[A]
|
545
|
-
def from: (Integer) -> Array[A]
|
546
|
-
def second: () -> A?
|
547
|
-
def third: () -> A?
|
548
|
-
end
|
549
|
-
```
|
550
|
-
|
551
534
|
### Type alias declaration
|
552
535
|
|
553
536
|
You can declare an alias of types.
|
data/goodcheck.yml
CHANGED
@@ -3,7 +3,7 @@ rules:
|
|
3
3
|
pattern: 💪👽🚨
|
4
4
|
message: Do you forget to delete `arglists` section?
|
5
5
|
glob:
|
6
|
-
- "stdlib/**/*.rbs"
|
6
|
+
- "{core,stdlib}/**/*.rbs"
|
7
7
|
fail:
|
8
8
|
- |
|
9
9
|
# arglists 💪👽🚨 << Delete this section
|
@@ -22,7 +22,7 @@ rules:
|
|
22
22
|
justification:
|
23
23
|
- Documents (comments) may contain that pattern.
|
24
24
|
glob:
|
25
|
-
- "stdlib/**/*.rbs"
|
25
|
+
- "{core,stdlib}/**/*.rbs"
|
26
26
|
fail:
|
27
27
|
- "def `send`: (String | Symbol arg0, *untyped arg1) -> untyped"
|
28
28
|
pass:
|
@@ -71,7 +71,7 @@ rules:
|
|
71
71
|
end
|
72
72
|
pass:
|
73
73
|
- |
|
74
|
-
class IntegerTest <
|
74
|
+
class IntegerTest < Test::Unit::TestCase
|
75
75
|
include TypeAssertions
|
76
76
|
|
77
77
|
testing "Integer"
|
data/lib/rbs/ast/declarations.rb
CHANGED
@@ -300,53 +300,6 @@ module RBS
|
|
300
300
|
end
|
301
301
|
end
|
302
302
|
|
303
|
-
class Extension < Base
|
304
|
-
attr_reader :name
|
305
|
-
attr_reader :type_params
|
306
|
-
attr_reader :extension_name
|
307
|
-
attr_reader :members
|
308
|
-
attr_reader :annotations
|
309
|
-
attr_reader :location
|
310
|
-
attr_reader :comment
|
311
|
-
|
312
|
-
def initialize(name:, type_params:, extension_name:, members:, annotations:, location:, comment:)
|
313
|
-
@name = name
|
314
|
-
@type_params = type_params
|
315
|
-
@extension_name = extension_name
|
316
|
-
@members = members
|
317
|
-
@annotations = annotations
|
318
|
-
@location = location
|
319
|
-
@comment = comment
|
320
|
-
end
|
321
|
-
|
322
|
-
def ==(other)
|
323
|
-
other.is_a?(Extension) &&
|
324
|
-
other.name == name &&
|
325
|
-
other.type_params == type_params &&
|
326
|
-
other.extension_name == extension_name &&
|
327
|
-
other.members == members
|
328
|
-
end
|
329
|
-
|
330
|
-
alias eql? ==
|
331
|
-
|
332
|
-
def hash
|
333
|
-
self.class.hash ^ name.hash ^ type_params.hash ^ extension_name.hash ^ members.hash
|
334
|
-
end
|
335
|
-
|
336
|
-
def to_json(*a)
|
337
|
-
{
|
338
|
-
declaration: :extension,
|
339
|
-
name: name,
|
340
|
-
type_params: type_params,
|
341
|
-
extension_name: extension_name,
|
342
|
-
members: members,
|
343
|
-
annotations: annotations,
|
344
|
-
location: location,
|
345
|
-
comment: comment
|
346
|
-
}.to_json(*a)
|
347
|
-
end
|
348
|
-
end
|
349
|
-
|
350
303
|
class Interface < Base
|
351
304
|
attr_reader :name
|
352
305
|
attr_reader :type_params
|
@@ -44,7 +44,8 @@ module RBS
|
|
44
44
|
|
45
45
|
ancestors = ancestor_builder.interface_ancestors(type_name)
|
46
46
|
Definition.new(type_name: type_name, entry: entry, self_type: self_type, ancestors: ancestors).tap do |definition|
|
47
|
-
ancestor_builder.one_interface_ancestors(type_name).included_interfaces
|
47
|
+
included_interfaces = ancestor_builder.one_interface_ancestors(type_name).included_interfaces or raise
|
48
|
+
included_interfaces.each do |mod|
|
48
49
|
defn = build_interface(mod.name)
|
49
50
|
subst = Substitution.build(defn.type_params, mod.args)
|
50
51
|
|
@@ -54,13 +55,17 @@ module RBS
|
|
54
55
|
end
|
55
56
|
|
56
57
|
methods = method_builder.build_interface(type_name)
|
58
|
+
one_ancestors = ancestor_builder.one_interface_ancestors(type_name)
|
59
|
+
|
60
|
+
validate_type_params(definition, methods: methods, ancestors: one_ancestors)
|
61
|
+
|
57
62
|
methods.each do |defn|
|
58
|
-
method = case defn.original
|
63
|
+
method = case original = defn.original
|
59
64
|
when AST::Members::MethodDefinition
|
60
|
-
defs =
|
65
|
+
defs = original.types.map do |method_type|
|
61
66
|
Definition::Method::TypeDef.new(
|
62
67
|
type: method_type,
|
63
|
-
member:
|
68
|
+
member: original,
|
64
69
|
defined_in: type_name,
|
65
70
|
implemented_in: nil
|
66
71
|
)
|
@@ -73,15 +78,15 @@ module RBS
|
|
73
78
|
alias_of: nil
|
74
79
|
)
|
75
80
|
when AST::Members::Alias
|
76
|
-
unless definition.methods.key?(
|
81
|
+
unless definition.methods.key?(original.old_name)
|
77
82
|
raise UnknownMethodAliasError.new(
|
78
|
-
original_name:
|
79
|
-
aliased_name:
|
80
|
-
location:
|
83
|
+
original_name: original.old_name,
|
84
|
+
aliased_name: original.new_name,
|
85
|
+
location: original.location
|
81
86
|
)
|
82
87
|
end
|
83
88
|
|
84
|
-
original_method = definition.methods[
|
89
|
+
original_method = definition.methods[original.old_name]
|
85
90
|
Definition::Method.new(
|
86
91
|
super_method: nil,
|
87
92
|
defs: original_method.defs.map do |defn|
|
@@ -101,10 +106,14 @@ module RBS
|
|
101
106
|
end
|
102
107
|
|
103
108
|
definition.methods[defn.name]
|
109
|
+
|
110
|
+
when AST::Members::AttrReader, AST::Members::AttrWriter, AST::Members::AttrAccessor
|
111
|
+
raise
|
112
|
+
|
104
113
|
end
|
105
114
|
|
106
115
|
defn.overloads.each do |overload|
|
107
|
-
|
116
|
+
overload_defs = overload.types.map do |method_type|
|
108
117
|
Definition::Method::TypeDef.new(
|
109
118
|
type: method_type,
|
110
119
|
member: overload,
|
@@ -113,7 +122,7 @@ module RBS
|
|
113
122
|
)
|
114
123
|
end
|
115
124
|
|
116
|
-
method.defs.unshift(*
|
125
|
+
method.defs.unshift(*overload_defs)
|
117
126
|
end
|
118
127
|
|
119
128
|
definition.methods[defn.name] = method
|
@@ -122,8 +131,8 @@ module RBS
|
|
122
131
|
end
|
123
132
|
end
|
124
133
|
|
125
|
-
def build_instance(type_name)
|
126
|
-
try_cache(type_name, cache: instance_cache) do
|
134
|
+
def build_instance(type_name, no_self_types: false)
|
135
|
+
try_cache(type_name, cache: instance_cache, key: [type_name, no_self_types]) do
|
127
136
|
entry = env.class_decls[type_name] or raise "Unknown name for build_instance: #{type_name}"
|
128
137
|
ensure_namespace!(type_name.namespace, location: entry.decls[0].decl.location)
|
129
138
|
|
@@ -141,31 +150,39 @@ module RBS
|
|
141
150
|
validate_type_params definition, methods: methods, ancestors: one_ancestors
|
142
151
|
|
143
152
|
if super_class = one_ancestors.super_class
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
153
|
+
case super_class
|
154
|
+
when Definition::Ancestor::Instance
|
155
|
+
build_instance(super_class.name).yield_self do |defn|
|
156
|
+
merge_definition(src: defn,
|
157
|
+
dest: definition,
|
158
|
+
subst: Substitution.build(defn.type_params, super_class.args),
|
159
|
+
keep_super: true)
|
160
|
+
end
|
161
|
+
else
|
162
|
+
raise
|
163
|
+
end
|
149
164
|
end
|
150
165
|
|
151
|
-
if one_ancestors.self_types
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
166
|
+
if self_types = one_ancestors.self_types
|
167
|
+
unless no_self_types
|
168
|
+
self_types.each do |ans|
|
169
|
+
defn = if ans.name.interface?
|
170
|
+
build_interface(ans.name)
|
171
|
+
else
|
172
|
+
build_instance(ans.name)
|
173
|
+
end
|
158
174
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
175
|
+
# Successor interface method overwrites.
|
176
|
+
merge_definition(src: defn,
|
177
|
+
dest: definition,
|
178
|
+
subst: Substitution.build(defn.type_params, ans.args),
|
179
|
+
keep_super: true)
|
180
|
+
end
|
164
181
|
end
|
165
182
|
end
|
166
183
|
|
167
|
-
one_ancestors.
|
168
|
-
defn = build_instance(mod.name)
|
184
|
+
one_ancestors.each_included_module do |mod|
|
185
|
+
defn = build_instance(mod.name, no_self_types: true)
|
169
186
|
merge_definition(src: defn,
|
170
187
|
dest: definition,
|
171
188
|
subst: Substitution.build(defn.type_params, mod.args))
|
@@ -173,16 +190,20 @@ module RBS
|
|
173
190
|
|
174
191
|
interface_methods = {}
|
175
192
|
|
176
|
-
one_ancestors.
|
193
|
+
one_ancestors.each_included_interface do |mod|
|
177
194
|
defn = build_interface(mod.name)
|
178
195
|
subst = Substitution.build(defn.type_params, mod.args)
|
179
196
|
|
180
197
|
defn.methods.each do |name, method|
|
181
198
|
if interface_methods.key?(name)
|
199
|
+
include_member = mod.source
|
200
|
+
|
201
|
+
raise unless include_member.is_a?(AST::Members::Include)
|
202
|
+
|
182
203
|
raise DuplicatedInterfaceMethodDefinitionError.new(
|
183
204
|
type: self_type,
|
184
205
|
method_name: name,
|
185
|
-
member:
|
206
|
+
member: include_member
|
186
207
|
)
|
187
208
|
end
|
188
209
|
|
@@ -221,7 +242,7 @@ module RBS
|
|
221
242
|
end
|
222
243
|
end
|
223
244
|
|
224
|
-
one_ancestors.
|
245
|
+
one_ancestors.each_prepended_module do |mod|
|
225
246
|
defn = build_instance(mod.name)
|
226
247
|
merge_definition(src: defn,
|
227
248
|
dest: definition,
|
@@ -261,24 +282,28 @@ module RBS
|
|
261
282
|
end
|
262
283
|
end
|
263
284
|
|
264
|
-
one_ancestors.
|
265
|
-
|
266
|
-
merge_definition(src:
|
285
|
+
one_ancestors.each_extended_module do |mod|
|
286
|
+
mod_defn = build_instance(mod.name, no_self_types: true)
|
287
|
+
merge_definition(src: mod_defn,
|
267
288
|
dest: definition,
|
268
|
-
subst: Substitution.build(
|
289
|
+
subst: Substitution.build(mod_defn.type_params, mod.args))
|
269
290
|
end
|
270
291
|
|
271
292
|
interface_methods = {}
|
272
|
-
one_ancestors.
|
273
|
-
|
274
|
-
subst = Substitution.build(
|
293
|
+
one_ancestors.each_extended_interface do |mod|
|
294
|
+
mod_defn = build_interface(mod.name)
|
295
|
+
subst = Substitution.build(mod_defn.type_params, mod.args)
|
275
296
|
|
276
|
-
|
297
|
+
mod_defn.methods.each do |name, method|
|
277
298
|
if interface_methods.key?(name)
|
299
|
+
src_member = mod.source
|
300
|
+
|
301
|
+
raise unless src_member.is_a?(AST::Members::Extend)
|
302
|
+
|
278
303
|
raise DuplicatedInterfaceMethodDefinitionError.new(
|
279
304
|
type: self_type,
|
280
305
|
method_name: name,
|
281
|
-
member:
|
306
|
+
member: src_member
|
282
307
|
)
|
283
308
|
end
|
284
309
|
|
@@ -418,6 +443,20 @@ module RBS
|
|
418
443
|
end
|
419
444
|
end
|
420
445
|
|
446
|
+
def source_location(source, decl)
|
447
|
+
case source
|
448
|
+
when nil
|
449
|
+
decl.location
|
450
|
+
when :super
|
451
|
+
case decl
|
452
|
+
when AST::Declarations::Class
|
453
|
+
decl.super_class&.location
|
454
|
+
end
|
455
|
+
else
|
456
|
+
source.location
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
421
460
|
def validate_type_params(definition, ancestors:, methods:)
|
422
461
|
type_params = definition.type_params_decl
|
423
462
|
|
@@ -429,19 +468,17 @@ module RBS
|
|
429
468
|
when Definition::Ancestor::Instance
|
430
469
|
result = calculator.in_inherit(name: ancestor.name, args: ancestor.args, variables: param_names)
|
431
470
|
validate_params_with(type_params, result: result) do |param|
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
source.location
|
439
|
-
end
|
471
|
+
decl = case entry = definition.entry
|
472
|
+
when Environment::ModuleEntry, Environment::ClassEntry
|
473
|
+
entry.primary.decl
|
474
|
+
when Environment::SingleEntry
|
475
|
+
entry.decl
|
476
|
+
end
|
440
477
|
|
441
478
|
raise InvalidVarianceAnnotationError.new(
|
442
479
|
type_name: definition.type_name,
|
443
480
|
param: param,
|
444
|
-
location:
|
481
|
+
location: source_location(ancestor.source, decl)
|
445
482
|
)
|
446
483
|
end
|
447
484
|
end
|
@@ -481,8 +518,6 @@ module RBS
|
|
481
518
|
nil
|
482
519
|
when nil
|
483
520
|
nil
|
484
|
-
else
|
485
|
-
raise
|
486
521
|
end
|
487
522
|
|
488
523
|
if method_types
|
@@ -537,11 +572,11 @@ module RBS
|
|
537
572
|
if interface_methods.key?(method_name)
|
538
573
|
interface_method = interface_methods[method_name]
|
539
574
|
|
540
|
-
if method_def.original
|
575
|
+
if original = method_def.original
|
541
576
|
raise DuplicatedMethodDefinitionError.new(
|
542
577
|
type: definition.self_type,
|
543
578
|
method_name: method_name,
|
544
|
-
members: [
|
579
|
+
members: [original]
|
545
580
|
)
|
546
581
|
end
|
547
582
|
|
@@ -561,6 +596,7 @@ module RBS
|
|
561
596
|
)
|
562
597
|
end
|
563
598
|
|
599
|
+
# @type var accessibility: RBS::Definition::accessibility
|
564
600
|
accessibility = if method_name == :initialize
|
565
601
|
:private
|
566
602
|
else
|
@@ -640,7 +676,7 @@ module RBS
|
|
640
676
|
end
|
641
677
|
|
642
678
|
method_def.overloads.each do |overload|
|
643
|
-
|
679
|
+
type_defs = overload.types.map do |method_type|
|
644
680
|
Definition::Method::TypeDef.new(
|
645
681
|
type: method_type,
|
646
682
|
member: overload,
|
@@ -649,7 +685,7 @@ module RBS
|
|
649
685
|
)
|
650
686
|
end
|
651
687
|
|
652
|
-
method.defs.unshift(*
|
688
|
+
method.defs.unshift(*type_defs)
|
653
689
|
end
|
654
690
|
|
655
691
|
definition.methods[method_name] = method
|
@@ -717,8 +753,10 @@ module RBS
|
|
717
753
|
)
|
718
754
|
end
|
719
755
|
|
720
|
-
def try_cache(type_name, cache:)
|
721
|
-
|
756
|
+
def try_cache(type_name, cache:, key: type_name)
|
757
|
+
# @type var cc: Hash[untyped, Definition | false | nil]
|
758
|
+
cc = _ = cache
|
759
|
+
cached = cc[key]
|
722
760
|
|
723
761
|
case cached
|
724
762
|
when Definition
|
@@ -726,11 +764,11 @@ module RBS
|
|
726
764
|
when false
|
727
765
|
raise
|
728
766
|
when nil
|
729
|
-
|
767
|
+
cc[key] = false
|
730
768
|
begin
|
731
|
-
|
769
|
+
cc[key] = yield
|
732
770
|
rescue => ex
|
733
|
-
|
771
|
+
cc.delete(key)
|
734
772
|
raise ex
|
735
773
|
end
|
736
774
|
else
|