rbs 4.1.0.pre.1 → 4.1.0
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/.dockerignore +37 -0
- data/.github/workflows/bundle-update.yml +1 -1
- data/.github/workflows/c-check.yml +14 -6
- data/.github/workflows/comments.yml +2 -2
- data/.github/workflows/dependabot.yml +2 -2
- data/.github/workflows/jruby.yml +79 -0
- data/.github/workflows/milestone.yml +13 -2
- data/.github/workflows/ruby.yml +16 -4
- data/.github/workflows/rust.yml +13 -8
- data/.github/workflows/truffleruby.yml +54 -0
- data/.github/workflows/typecheck.yml +5 -2
- data/.github/workflows/wasm.yml +55 -0
- data/.github/workflows/windows.yml +8 -2
- data/.gitignore +8 -0
- data/CHANGELOG.md +88 -0
- data/Dockerfile.jruby +53 -0
- data/README.md +3 -3
- data/Rakefile +103 -1
- data/Steepfile +9 -0
- data/core/array.rbs +243 -180
- data/core/builtin.rbs +6 -6
- data/core/enumerable.rbs +109 -109
- data/core/enumerator/product.rbs +5 -5
- data/core/enumerator.rbs +28 -28
- data/core/file.rbs +24 -1018
- data/core/file_constants.rbs +463 -0
- data/core/file_stat.rbs +534 -0
- data/core/float.rbs +0 -24
- data/core/hash.rbs +117 -101
- data/core/integer.rbs +21 -58
- data/core/io.rbs +25 -7
- data/core/match_data.rbs +1 -1
- data/core/module.rbs +88 -74
- data/core/numeric.rbs +3 -0
- data/core/object_space/weak_key_map.rbs +7 -7
- data/core/pathname.rbs +0 -10
- data/core/ractor.rbs +0 -10
- data/core/range.rbs +23 -23
- data/core/rbs/ops.rbs +154 -0
- data/core/rbs/unnamed/argf.rbs +3 -3
- data/core/rubygems/errors.rbs +4 -1
- data/core/rubygems/requirement.rbs +0 -10
- data/core/rubygems/rubygems.rbs +4 -1
- data/core/rubygems/specification.rbs +8 -0
- data/core/rubygems/version.rbs +0 -160
- data/core/set.rbs +3 -3
- data/core/struct.rbs +16 -16
- data/core/thread.rbs +9 -14
- data/docs/CONTRIBUTING.md +2 -1
- data/docs/inline.md +36 -6
- data/docs/rbs_by_example.md +20 -20
- data/docs/release.md +69 -0
- data/docs/syntax.md +2 -2
- data/docs/wasm_serialization.md +80 -0
- data/ext/rbs_extension/ast_translation.c +1294 -973
- data/ext/rbs_extension/ast_translation.h +4 -0
- data/ext/rbs_extension/legacy_location.c +11 -6
- data/ext/rbs_extension/main.c +139 -4
- data/include/rbs/ast.h +9 -1
- data/include/rbs/serialize.h +39 -0
- data/lib/rbs/ast/ruby/comment_block.rb +6 -4
- data/lib/rbs/ast/ruby/helpers/location_helper.rb +1 -1
- data/lib/rbs/ast/ruby/members.rb +12 -1
- data/lib/rbs/buffer.rb +48 -11
- data/lib/rbs/collection/sources/git.rb +6 -0
- data/lib/rbs/definition_builder/method_builder.rb +12 -6
- data/lib/rbs/environment.rb +4 -3
- data/lib/rbs/inline_parser.rb +5 -3
- data/lib/rbs/namespace.rb +47 -11
- data/lib/rbs/parser_aux.rb +4 -2
- data/lib/rbs/prototype/rbi.rb +193 -25
- data/lib/rbs/prototype/runtime.rb +2 -0
- data/lib/rbs/resolver/type_name_resolver.rb +12 -14
- data/lib/rbs/type_name.rb +33 -13
- data/lib/rbs/unit_test/type_assertions.rb +9 -0
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/wasm/deserializer.rb +213 -0
- data/lib/rbs/wasm/location.rb +61 -0
- data/lib/rbs/wasm/parser.rb +137 -0
- data/lib/rbs/wasm/runtime.rb +196 -0
- data/lib/rbs/wasm/serialization_schema.rb +110 -0
- data/lib/rbs.rb +13 -2
- data/lib/rbs_jars.rb +39 -0
- data/lib/rdoc_plugin/parser.rb +5 -0
- data/rbs.gemspec +32 -2
- data/sig/ast/ruby/members.rbs +6 -1
- data/sig/buffer.rbs +19 -1
- data/sig/namespace.rbs +20 -0
- data/sig/parser.rbs +10 -0
- data/sig/prototype/rbi.rbs +33 -4
- data/sig/resolver/type_name_resolver.rbs +2 -4
- data/sig/typename.rbs +15 -0
- data/sig/unit_test/type_assertions.rbs +4 -0
- data/sig/wasm/deserializer.rbs +66 -0
- data/sig/wasm/serialization_schema.rbs +13 -0
- data/src/ast.c +78 -78
- data/src/lexer.c +97 -93
- data/src/lexer.re +1 -1
- data/src/lexstate.c +9 -1
- data/src/serialize.c +958 -0
- data/src/util/rbs_allocator.c +14 -8
- data/stdlib/abbrev/0/array.rbs +1 -1
- data/stdlib/csv/0/csv.rbs +5 -5
- data/stdlib/delegate/0/delegator.rbs +2 -1
- data/stdlib/digest/0/digest.rbs +11 -5
- data/stdlib/erb/0/erb.rbs +1 -1
- data/stdlib/etc/0/etc.rbs +18 -4
- data/stdlib/fileutils/0/fileutils.rbs +21 -21
- data/stdlib/ipaddr/0/ipaddr.rbs +0 -5
- data/stdlib/json/0/json.rbs +6 -6
- data/stdlib/monitor/0/monitor.rbs +2 -2
- data/stdlib/openssl/0/openssl.rbs +44 -38
- data/stdlib/resolv/0/resolv.rbs +1 -1
- data/stdlib/shellwords/0/shellwords.rbs +1 -1
- data/stdlib/stringio/0/stringio.rbs +32 -10
- data/stdlib/strscan/0/string_scanner.rbs +74 -55
- data/stdlib/tempfile/0/manifest.yaml +3 -0
- data/stdlib/timeout/0/timeout.rbs +0 -5
- data/stdlib/tsort/0/cyclic.rbs +1 -1
- data/stdlib/tsort/0/interfaces.rbs +8 -8
- data/stdlib/tsort/0/tsort.rbs +9 -9
- data/stdlib/uri/0/generic.rbs +0 -5
- data/stdlib/zlib/0/gzip_reader.rbs +2 -2
- data/stdlib/zlib/0/zstream.rbs +0 -1
- data/wasm/README.md +60 -0
- data/wasm/rbs_wasm.c +423 -0
- metadata +26 -5
- data/.vscode/extensions.json +0 -5
- data/.vscode/settings.json +0 -19
data/lib/rbs/namespace.rb
CHANGED
|
@@ -9,30 +9,65 @@ module RBS
|
|
|
9
9
|
@absolute = absolute ? true : false
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
+
# Process-wide flyweight cache. Two tries (one per `absolute` flag)
|
|
13
|
+
# keyed on path Symbols, with the cached Namespace stored under the
|
|
14
|
+
# `INTERN_LEAF` sentinel at each path's terminal node.
|
|
15
|
+
@intern_mutex = Mutex.new
|
|
16
|
+
@intern_trie_absolute = {}
|
|
17
|
+
@intern_trie_relative = {}
|
|
18
|
+
INTERN_LEAF = Module.new
|
|
19
|
+
|
|
20
|
+
# Returns a canonical `Namespace` instance for the given `path` /
|
|
21
|
+
# `absolute` pair. Repeated calls with structurally equal arguments
|
|
22
|
+
# return the same object, so callers can rely on `equal?` for fast
|
|
23
|
+
# equality. The path Array is duplicated and frozen on insert.
|
|
24
|
+
def self.[](path, absolute)
|
|
25
|
+
absolute = absolute ? true : false
|
|
26
|
+
|
|
27
|
+
# Lock-free fast path.
|
|
28
|
+
node = absolute ? @intern_trie_absolute : @intern_trie_relative
|
|
29
|
+
path.each do |sym|
|
|
30
|
+
node = node[sym]
|
|
31
|
+
break unless node
|
|
32
|
+
end
|
|
33
|
+
if node && (cached = node[INTERN_LEAF])
|
|
34
|
+
return cached
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
@intern_mutex.synchronize do
|
|
38
|
+
node = absolute ? @intern_trie_absolute : @intern_trie_relative
|
|
39
|
+
path.each { |sym| node = (node[sym] ||= {}) }
|
|
40
|
+
node[INTERN_LEAF] ||= begin
|
|
41
|
+
frozen_path = path.frozen? ? path : path.dup.freeze
|
|
42
|
+
new(path: frozen_path, absolute: absolute)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
12
47
|
def self.empty
|
|
13
|
-
@empty ||=
|
|
48
|
+
@empty ||= self[[], false]
|
|
14
49
|
end
|
|
15
50
|
|
|
16
51
|
def self.root
|
|
17
|
-
@root ||=
|
|
52
|
+
@root ||= self[[], true]
|
|
18
53
|
end
|
|
19
54
|
|
|
20
55
|
def +(other)
|
|
21
56
|
if other.absolute?
|
|
22
57
|
other
|
|
23
58
|
else
|
|
24
|
-
|
|
59
|
+
Namespace[path + other.path, absolute?]
|
|
25
60
|
end
|
|
26
61
|
end
|
|
27
62
|
|
|
28
63
|
def append(component)
|
|
29
|
-
|
|
64
|
+
Namespace[path + [component], absolute?]
|
|
30
65
|
end
|
|
31
66
|
|
|
32
67
|
def parent
|
|
33
68
|
@parent ||= begin
|
|
34
69
|
raise "Parent with empty namespace" if empty?
|
|
35
|
-
|
|
70
|
+
Namespace[path.take(path.size - 1), absolute?]
|
|
36
71
|
end
|
|
37
72
|
end
|
|
38
73
|
|
|
@@ -45,11 +80,11 @@ module RBS
|
|
|
45
80
|
end
|
|
46
81
|
|
|
47
82
|
def absolute!
|
|
48
|
-
|
|
83
|
+
Namespace[path, true]
|
|
49
84
|
end
|
|
50
85
|
|
|
51
86
|
def relative!
|
|
52
|
-
|
|
87
|
+
Namespace[path, false]
|
|
53
88
|
end
|
|
54
89
|
|
|
55
90
|
def empty?
|
|
@@ -57,13 +92,14 @@ module RBS
|
|
|
57
92
|
end
|
|
58
93
|
|
|
59
94
|
def ==(other)
|
|
95
|
+
return true if equal?(other)
|
|
60
96
|
other.is_a?(Namespace) && other.path == path && other.absolute? == absolute?
|
|
61
97
|
end
|
|
62
98
|
|
|
63
99
|
alias eql? ==
|
|
64
100
|
|
|
65
101
|
def hash
|
|
66
|
-
path.hash ^ absolute?.hash
|
|
102
|
+
@hash ||= path.hash ^ absolute?.hash
|
|
67
103
|
end
|
|
68
104
|
|
|
69
105
|
def split
|
|
@@ -87,14 +123,14 @@ module RBS
|
|
|
87
123
|
raise unless name
|
|
88
124
|
raise unless parent
|
|
89
125
|
|
|
90
|
-
TypeName
|
|
126
|
+
TypeName[parent, name]
|
|
91
127
|
end
|
|
92
128
|
|
|
93
129
|
def self.parse(string)
|
|
94
130
|
if string.start_with?("::")
|
|
95
|
-
|
|
131
|
+
self[string.split("::").drop(1).map(&:to_sym), true]
|
|
96
132
|
else
|
|
97
|
-
|
|
133
|
+
self[string.split("::").map(&:to_sym), false]
|
|
98
134
|
end
|
|
99
135
|
end
|
|
100
136
|
|
data/lib/rbs/parser_aux.rb
CHANGED
|
@@ -121,12 +121,14 @@ module RBS
|
|
|
121
121
|
|
|
122
122
|
def self.parse_inline_leading_annotation(source, range, variables: [])
|
|
123
123
|
buf = buffer(source)
|
|
124
|
-
|
|
124
|
+
byte_range = byte_range(range, buf.content)
|
|
125
|
+
_parse_inline_leading_annotation(buf, byte_range.begin || 0, byte_range.end || buf.content.bytesize, variables)
|
|
125
126
|
end
|
|
126
127
|
|
|
127
128
|
def self.parse_inline_trailing_annotation(source, range, variables: [])
|
|
128
129
|
buf = buffer(source)
|
|
129
|
-
|
|
130
|
+
byte_range = byte_range(range, buf.content)
|
|
131
|
+
_parse_inline_trailing_annotation(buf, byte_range.begin || 0, byte_range.end || buf.content.bytesize, variables)
|
|
130
132
|
end
|
|
131
133
|
|
|
132
134
|
def self.byte_range(char_range, content)
|
data/lib/rbs/prototype/rbi.rb
CHANGED
|
@@ -9,10 +9,22 @@ module RBS
|
|
|
9
9
|
attr_reader :modules
|
|
10
10
|
attr_reader :last_sig
|
|
11
11
|
|
|
12
|
+
class Context
|
|
13
|
+
attr_accessor :singleton
|
|
14
|
+
attr_accessor :visibility
|
|
15
|
+
|
|
16
|
+
def initialize(singleton:, visibility:)
|
|
17
|
+
@singleton = singleton
|
|
18
|
+
@visibility = visibility
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
12
22
|
def initialize
|
|
13
23
|
@decls = []
|
|
14
24
|
|
|
15
25
|
@modules = []
|
|
26
|
+
@contexts = []
|
|
27
|
+
@emitted_visibility = {}
|
|
16
28
|
end
|
|
17
29
|
|
|
18
30
|
def parse(string)
|
|
@@ -20,19 +32,17 @@ module RBS
|
|
|
20
32
|
process RubyVM::AbstractSyntaxTree.parse(string), comments: comments
|
|
21
33
|
end
|
|
22
34
|
|
|
23
|
-
def
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
modules.inject(Namespace.empty) do |parent, mod|
|
|
29
|
-
parent + mod.name.to_namespace
|
|
35
|
+
def append_decl(decl)
|
|
36
|
+
if mod = current_module
|
|
37
|
+
mod.members << decl
|
|
38
|
+
else
|
|
39
|
+
decls << decl
|
|
30
40
|
end
|
|
31
41
|
end
|
|
32
42
|
|
|
33
43
|
def push_class(name, super_class, comment:)
|
|
34
44
|
class_decl = AST::Declarations::Class.new(
|
|
35
|
-
name:
|
|
45
|
+
name: const_to_name(name),
|
|
36
46
|
super_class: super_class && AST::Declarations::Class::Super.new(name: const_to_name(super_class), args: [], location: nil),
|
|
37
47
|
type_params: [],
|
|
38
48
|
members: [],
|
|
@@ -41,17 +51,20 @@ module RBS
|
|
|
41
51
|
comment: comment
|
|
42
52
|
)
|
|
43
53
|
|
|
54
|
+
append_decl class_decl
|
|
44
55
|
modules << class_decl
|
|
45
|
-
|
|
56
|
+
@contexts << Context.new(singleton: false, visibility: :public)
|
|
57
|
+
@emitted_visibility[class_decl.object_id] = :public
|
|
46
58
|
|
|
47
59
|
yield
|
|
48
60
|
ensure
|
|
61
|
+
@contexts.pop
|
|
49
62
|
modules.pop
|
|
50
63
|
end
|
|
51
64
|
|
|
52
65
|
def push_module(name, comment:)
|
|
53
66
|
module_decl = AST::Declarations::Module.new(
|
|
54
|
-
name:
|
|
67
|
+
name: const_to_name(name),
|
|
55
68
|
type_params: [],
|
|
56
69
|
members: [],
|
|
57
70
|
annotations: [],
|
|
@@ -60,11 +73,14 @@ module RBS
|
|
|
60
73
|
comment: comment
|
|
61
74
|
)
|
|
62
75
|
|
|
76
|
+
append_decl module_decl
|
|
63
77
|
modules << module_decl
|
|
64
|
-
|
|
78
|
+
@contexts << Context.new(singleton: false, visibility: :public)
|
|
79
|
+
@emitted_visibility[module_decl.object_id] = :public
|
|
65
80
|
|
|
66
81
|
yield
|
|
67
82
|
ensure
|
|
83
|
+
@contexts.pop
|
|
68
84
|
modules.pop
|
|
69
85
|
end
|
|
70
86
|
|
|
@@ -76,6 +92,47 @@ module RBS
|
|
|
76
92
|
current_module or raise
|
|
77
93
|
end
|
|
78
94
|
|
|
95
|
+
def current_context
|
|
96
|
+
@contexts.last
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def current_context!
|
|
100
|
+
current_context or raise
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Visibility of a member, given as `private def ...` in RBS
|
|
104
|
+
#
|
|
105
|
+
# Returns `nil` for members in a visibility _section_, which `sync_visibility` emits instead.
|
|
106
|
+
def member_visibility(context)
|
|
107
|
+
# RBS visibility sections don't apply to singleton members, so they need their own visibility.
|
|
108
|
+
if context.singleton && context.visibility != :public
|
|
109
|
+
:private
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def sync_visibility(visibility)
|
|
114
|
+
# Visibility sections don't apply to singleton members in RBS.
|
|
115
|
+
return if current_context!.singleton
|
|
116
|
+
|
|
117
|
+
# RBS has no protected visibility. Private is the conservative fallback.
|
|
118
|
+
visibility = :private if visibility == :protected
|
|
119
|
+
|
|
120
|
+
mod = current_module!
|
|
121
|
+
return if @emitted_visibility[mod.object_id] == visibility
|
|
122
|
+
|
|
123
|
+
member = case visibility
|
|
124
|
+
when :public
|
|
125
|
+
AST::Members::Public.new(location: nil)
|
|
126
|
+
when :private
|
|
127
|
+
AST::Members::Private.new(location: nil)
|
|
128
|
+
else
|
|
129
|
+
raise "Unexpected visibility: #{visibility}"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
mod.members << member
|
|
133
|
+
@emitted_visibility[mod.object_id] = visibility
|
|
134
|
+
end
|
|
135
|
+
|
|
79
136
|
def push_sig(node)
|
|
80
137
|
if last_sig = @last_sig
|
|
81
138
|
last_sig << node
|
|
@@ -107,6 +164,15 @@ module RBS
|
|
|
107
164
|
push_module node.children[0], comment: comment do
|
|
108
165
|
process node.children[1], outer: outer + [node], comments: comments
|
|
109
166
|
end
|
|
167
|
+
when :SCLASS
|
|
168
|
+
if node.children[0].type == :SELF
|
|
169
|
+
@contexts << Context.new(singleton: true, visibility: :public)
|
|
170
|
+
begin
|
|
171
|
+
process node.children[1], outer: outer + [node], comments: comments
|
|
172
|
+
ensure
|
|
173
|
+
@contexts.pop
|
|
174
|
+
end
|
|
175
|
+
end
|
|
110
176
|
when :FCALL
|
|
111
177
|
case node.children[0]
|
|
112
178
|
when :include
|
|
@@ -125,9 +191,9 @@ module RBS
|
|
|
125
191
|
end
|
|
126
192
|
when :extend
|
|
127
193
|
each_arg node.children[1] do |arg|
|
|
128
|
-
if arg.type == :CONST || arg.type == :COLON2
|
|
194
|
+
if arg.type == :CONST || arg.type == :COLON2 || arg.type == :COLON3
|
|
129
195
|
name = const_to_name(arg)
|
|
130
|
-
unless
|
|
196
|
+
unless ["T::Generic", "T::Helpers", "T::Sig"].include?(name.to_s.delete_prefix("::"))
|
|
131
197
|
member = AST::Members::Extend.new(
|
|
132
198
|
name: name,
|
|
133
199
|
args: [],
|
|
@@ -142,6 +208,10 @@ module RBS
|
|
|
142
208
|
when :sig
|
|
143
209
|
out = outer.last or raise
|
|
144
210
|
push_sig out.children.last.children.last
|
|
211
|
+
when :attr_reader, :attr_writer, :attr_accessor
|
|
212
|
+
process_attribute node, comments: comments
|
|
213
|
+
when :private, :protected, :public
|
|
214
|
+
process_visibility node, outer: outer, comments: comments
|
|
145
215
|
when :alias_method
|
|
146
216
|
new, old = each_arg(node.children[1]).map {|x| x.children[0] }
|
|
147
217
|
current_module!.members << AST::Members::Alias.new(
|
|
@@ -149,10 +219,15 @@ module RBS
|
|
|
149
219
|
old_name: old,
|
|
150
220
|
location: nil,
|
|
151
221
|
annotations: [],
|
|
152
|
-
kind: :instance,
|
|
222
|
+
kind: current_context!.singleton ? :singleton : :instance,
|
|
153
223
|
comment: nil
|
|
154
224
|
)
|
|
155
225
|
end
|
|
226
|
+
when :VCALL
|
|
227
|
+
case node.children[0]
|
|
228
|
+
when :private, :protected, :public
|
|
229
|
+
current_context!.visibility = node.children[0]
|
|
230
|
+
end
|
|
156
231
|
when :DEFS
|
|
157
232
|
sigs = pop_sig
|
|
158
233
|
|
|
@@ -178,6 +253,8 @@ module RBS
|
|
|
178
253
|
sigs = pop_sig
|
|
179
254
|
|
|
180
255
|
if sigs
|
|
256
|
+
context = current_context!
|
|
257
|
+
sync_visibility(context.visibility)
|
|
181
258
|
comment = join_comments(sigs, comments)
|
|
182
259
|
|
|
183
260
|
args = node.children[1]
|
|
@@ -188,10 +265,10 @@ module RBS
|
|
|
188
265
|
location: nil,
|
|
189
266
|
annotations: [],
|
|
190
267
|
overloads: types.map {|type| AST::Members::MethodDefinition::Overload.new(annotations: [], method_type: type) },
|
|
191
|
-
kind: :instance,
|
|
268
|
+
kind: context.singleton ? :singleton : :instance,
|
|
192
269
|
comment: comment,
|
|
193
270
|
overloading: false,
|
|
194
|
-
visibility:
|
|
271
|
+
visibility: member_visibility(context)
|
|
195
272
|
)
|
|
196
273
|
end
|
|
197
274
|
|
|
@@ -222,11 +299,7 @@ module RBS
|
|
|
222
299
|
end
|
|
223
300
|
else
|
|
224
301
|
name = node.children[0].yield_self do |n|
|
|
225
|
-
|
|
226
|
-
TypeName.new(namespace: current_namespace, name: n)
|
|
227
|
-
else
|
|
228
|
-
const_to_name(n)
|
|
229
|
-
end
|
|
302
|
+
n.is_a?(Symbol) ? TypeName.new(namespace: Namespace.empty, name: n) : const_to_name(n)
|
|
230
303
|
end
|
|
231
304
|
value_node = node.children.last
|
|
232
305
|
type = if value_node && value_node.type == :CALL && value_node.children[1] == :let
|
|
@@ -235,7 +308,7 @@ module RBS
|
|
|
235
308
|
else
|
|
236
309
|
Types::Bases::Any.new(location: nil)
|
|
237
310
|
end
|
|
238
|
-
|
|
311
|
+
append_decl AST::Declarations::Constant.new(
|
|
239
312
|
name: name,
|
|
240
313
|
type: type,
|
|
241
314
|
location: nil,
|
|
@@ -244,12 +317,13 @@ module RBS
|
|
|
244
317
|
)
|
|
245
318
|
end
|
|
246
319
|
when :ALIAS
|
|
320
|
+
sync_visibility(current_context!.visibility)
|
|
247
321
|
current_module!.members << AST::Members::Alias.new(
|
|
248
322
|
new_name: node.children[0].children[0],
|
|
249
323
|
old_name: node.children[1].children[0],
|
|
250
324
|
location: nil,
|
|
251
325
|
annotations: [],
|
|
252
|
-
kind: :instance,
|
|
326
|
+
kind: current_context!.singleton ? :singleton : :instance,
|
|
253
327
|
comment: nil
|
|
254
328
|
)
|
|
255
329
|
else
|
|
@@ -259,6 +333,93 @@ module RBS
|
|
|
259
333
|
end
|
|
260
334
|
end
|
|
261
335
|
|
|
336
|
+
def process_visibility(node, outer:, comments:)
|
|
337
|
+
visibility = node.children[0]
|
|
338
|
+
args = each_arg(node.children[1]).to_a
|
|
339
|
+
context = current_context!
|
|
340
|
+
|
|
341
|
+
if args.empty?
|
|
342
|
+
context.visibility = visibility
|
|
343
|
+
else
|
|
344
|
+
previous_visibility = context.visibility
|
|
345
|
+
context.visibility = visibility
|
|
346
|
+
|
|
347
|
+
begin
|
|
348
|
+
args.each do |arg|
|
|
349
|
+
if arg.type == :DEFN || arg.type == :DEFS
|
|
350
|
+
process arg, outer: outer + [node], comments: comments
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
ensure
|
|
354
|
+
context.visibility = previous_visibility
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def process_attribute(node, comments:)
|
|
360
|
+
sigs = pop_sig
|
|
361
|
+
kind = node.children[0]
|
|
362
|
+
context = current_context!
|
|
363
|
+
sync_visibility(context.visibility)
|
|
364
|
+
|
|
365
|
+
type = attribute_type(kind, sigs)
|
|
366
|
+
comment = join_comments(sigs, comments) if sigs
|
|
367
|
+
member_class = case kind
|
|
368
|
+
when :attr_reader
|
|
369
|
+
AST::Members::AttrReader
|
|
370
|
+
when :attr_writer
|
|
371
|
+
AST::Members::AttrWriter
|
|
372
|
+
when :attr_accessor
|
|
373
|
+
AST::Members::AttrAccessor
|
|
374
|
+
else
|
|
375
|
+
raise "Unexpected attribute kind: #{kind}"
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
each_arg node.children[1] do |arg|
|
|
379
|
+
if name = symbol_literal_node?(arg)
|
|
380
|
+
current_module!.members << member_class.new(
|
|
381
|
+
name: name,
|
|
382
|
+
type: type,
|
|
383
|
+
ivar_name: nil,
|
|
384
|
+
kind: context.singleton ? :singleton : :instance,
|
|
385
|
+
annotations: [],
|
|
386
|
+
location: nil,
|
|
387
|
+
comment: comment,
|
|
388
|
+
visibility: member_visibility(context)
|
|
389
|
+
)
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
def attribute_type(kind, sigs)
|
|
395
|
+
any = Types::Bases::Any.new(location: nil)
|
|
396
|
+
return any unless sigs
|
|
397
|
+
|
|
398
|
+
method_types = sigs.filter_map do |sig|
|
|
399
|
+
method_type(nil, sig, variables: current_module!.type_params, overloads: sigs.size)
|
|
400
|
+
end
|
|
401
|
+
function = method_types.last&.type
|
|
402
|
+
return any unless function.is_a?(Types::Function)
|
|
403
|
+
|
|
404
|
+
parameter_type = function.required_positionals.first&.type
|
|
405
|
+
return_type = function.return_type
|
|
406
|
+
|
|
407
|
+
case kind
|
|
408
|
+
when :attr_reader
|
|
409
|
+
return_type
|
|
410
|
+
when :attr_writer
|
|
411
|
+
parameter_type || return_type
|
|
412
|
+
when :attr_accessor
|
|
413
|
+
if return_type.is_a?(Types::Bases::Any) || return_type.is_a?(Types::Bases::Void)
|
|
414
|
+
parameter_type || any
|
|
415
|
+
else
|
|
416
|
+
return_type
|
|
417
|
+
end
|
|
418
|
+
else
|
|
419
|
+
any
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
|
|
262
423
|
def method_type(args_node, type_node, variables:, overloads:)
|
|
263
424
|
if type_node
|
|
264
425
|
if type_node.type == :CALL
|
|
@@ -463,8 +624,10 @@ module RBS
|
|
|
463
624
|
case
|
|
464
625
|
when type.is_a?(Types::ClassInstance) && type.name.name == BuiltinNames::BasicObject.name.name
|
|
465
626
|
Types::Bases::Any.new(location: nil)
|
|
466
|
-
when type.is_a?(Types::ClassInstance) && type.name.to_s == "T::Boolean"
|
|
627
|
+
when type.is_a?(Types::ClassInstance) && type.name.to_s.delete_prefix("::") == "T::Boolean"
|
|
467
628
|
Types::Bases::Bool.new(location: nil)
|
|
629
|
+
when type.is_a?(Types::ClassInstance) && type.name.to_s.delete_prefix("::") == "T::Class"
|
|
630
|
+
Types::Bases::Any.new(location: nil)
|
|
468
631
|
else
|
|
469
632
|
type
|
|
470
633
|
end
|
|
@@ -482,6 +645,11 @@ module RBS
|
|
|
482
645
|
Types::ClassInstance.new(name: const_to_name(type_node), args: [], location: nil)
|
|
483
646
|
when call_node?(type_node, name: :[], receiver: -> (_) { true })
|
|
484
647
|
# The type_node represents a type application
|
|
648
|
+
receiver = type_node.children[0]
|
|
649
|
+
if [:CONST, :COLON2, :COLON3].include?(receiver.type) && const_to_name(receiver).to_s.delete_prefix("::") == "T::Class"
|
|
650
|
+
return Types::Bases::Any.new(location: nil)
|
|
651
|
+
end
|
|
652
|
+
|
|
485
653
|
type = type_of(type_node.children[0], variables: variables)
|
|
486
654
|
type.is_a?(Types::ClassInstance) or raise
|
|
487
655
|
|
|
@@ -559,7 +727,7 @@ module RBS
|
|
|
559
727
|
|
|
560
728
|
type_name = TypeName.new(name: node.children[1], namespace: namespace)
|
|
561
729
|
|
|
562
|
-
case type_name.to_s
|
|
730
|
+
case type_name.to_s.delete_prefix("::")
|
|
563
731
|
when "T::Array"
|
|
564
732
|
BuiltinNames::Array.name
|
|
565
733
|
when "T::Hash"
|
|
@@ -77,6 +77,8 @@ module RBS
|
|
|
77
77
|
attr_accessor :outline
|
|
78
78
|
|
|
79
79
|
def initialize(patterns:, env:, merge:, todo: false, owners_included: [])
|
|
80
|
+
Kernel.warn("RBS::Prototype::Runtime is deprecated. See https://github.com/ruby/rbs/issues/2841")
|
|
81
|
+
|
|
80
82
|
@patterns = patterns
|
|
81
83
|
@decls = nil
|
|
82
84
|
@modules = {}
|
|
@@ -29,11 +29,9 @@ module RBS
|
|
|
29
29
|
new(all_names, aliases)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
def try_cache(
|
|
33
|
-
cache
|
|
34
|
-
|
|
35
|
-
cache[query] = result
|
|
36
|
-
end
|
|
32
|
+
def try_cache(type_name, context)
|
|
33
|
+
inner = cache[context] ||= {}
|
|
34
|
+
inner.fetch(type_name) { inner[type_name] = yield }
|
|
37
35
|
end
|
|
38
36
|
|
|
39
37
|
def resolve(type_name, context:)
|
|
@@ -41,7 +39,7 @@ module RBS
|
|
|
41
39
|
return type_name
|
|
42
40
|
end
|
|
43
41
|
|
|
44
|
-
try_cache(
|
|
42
|
+
try_cache(type_name, context) do
|
|
45
43
|
if type_name.class?
|
|
46
44
|
resolve_namespace0(type_name, context, Set.new) || nil
|
|
47
45
|
else
|
|
@@ -51,7 +49,7 @@ module RBS
|
|
|
51
49
|
resolve_type_name(type_name.name, context)
|
|
52
50
|
else
|
|
53
51
|
if namespace = resolve_namespace0(namespace.to_type_name, context, Set.new)
|
|
54
|
-
type_name = TypeName.
|
|
52
|
+
type_name = TypeName[namespace.to_namespace, type_name.name]
|
|
55
53
|
has_type_name?(type_name)
|
|
56
54
|
end
|
|
57
55
|
end
|
|
@@ -68,7 +66,7 @@ module RBS
|
|
|
68
66
|
raise "Type name must be a class name: #{type_name}"
|
|
69
67
|
end
|
|
70
68
|
|
|
71
|
-
try_cache(
|
|
69
|
+
try_cache(type_name, context) do
|
|
72
70
|
ns = resolve_namespace0(type_name, context, Set.new) or return ns
|
|
73
71
|
end
|
|
74
72
|
end
|
|
@@ -93,10 +91,10 @@ module RBS
|
|
|
93
91
|
resolve_type_name(type_name, outer)
|
|
94
92
|
else
|
|
95
93
|
has_type_name?(inner) or raise "Context must be normalized: #{inner.inspect}"
|
|
96
|
-
has_type_name?(TypeName.
|
|
94
|
+
has_type_name?(TypeName[inner.to_namespace, type_name]) || resolve_type_name(type_name, outer)
|
|
97
95
|
end
|
|
98
96
|
else
|
|
99
|
-
type_name = TypeName.
|
|
97
|
+
type_name = TypeName[Namespace.root, type_name]
|
|
100
98
|
has_type_name?(type_name)
|
|
101
99
|
end
|
|
102
100
|
end
|
|
@@ -109,11 +107,11 @@ module RBS
|
|
|
109
107
|
resolve_head_namespace(head, outer)
|
|
110
108
|
when TypeName
|
|
111
109
|
has_type_name?(inner) or raise "Context must be normalized: #{inner.inspect}"
|
|
112
|
-
type_name = TypeName.
|
|
110
|
+
type_name = TypeName[inner.to_namespace, head]
|
|
113
111
|
has_type_name?(type_name) || aliased_name?(type_name) || resolve_head_namespace(head, outer)
|
|
114
112
|
end
|
|
115
113
|
else
|
|
116
|
-
type_name = TypeName.
|
|
114
|
+
type_name = TypeName[Namespace.root, head]
|
|
117
115
|
has_type_name?(type_name) || aliased_name?(type_name)
|
|
118
116
|
end
|
|
119
117
|
end
|
|
@@ -140,7 +138,7 @@ module RBS
|
|
|
140
138
|
|
|
141
139
|
head =
|
|
142
140
|
if type_name.absolute?
|
|
143
|
-
root_name = TypeName.
|
|
141
|
+
root_name = TypeName[Namespace.root, head]
|
|
144
142
|
has_type_name?(root_name) || aliased_name?(root_name)
|
|
145
143
|
else
|
|
146
144
|
resolve_head_namespace(head, context)
|
|
@@ -152,7 +150,7 @@ module RBS
|
|
|
152
150
|
end
|
|
153
151
|
|
|
154
152
|
tail.inject(head) do |namespace, name|
|
|
155
|
-
type_name = TypeName.
|
|
153
|
+
type_name = TypeName[namespace.to_namespace, name]
|
|
156
154
|
case
|
|
157
155
|
when has_type_name?(type_name)
|
|
158
156
|
type_name
|
data/lib/rbs/type_name.rb
CHANGED
|
@@ -22,14 +22,40 @@ module RBS
|
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
# Process-wide flyweight cache. Two-level Hash keyed by canonical
|
|
26
|
+
# Namespace identity (outer uses `compare_by_identity`) and name
|
|
27
|
+
# Symbol.
|
|
28
|
+
@intern_mutex = Mutex.new
|
|
29
|
+
@intern_cache = {} #: Hash[Namespace, Hash[Symbol, TypeName]]
|
|
30
|
+
@intern_cache.compare_by_identity
|
|
31
|
+
|
|
32
|
+
# Returns a canonical `TypeName` instance for the given `namespace` /
|
|
33
|
+
# `name` pair. The namespace is canonicalized through `Namespace.[]`
|
|
34
|
+
# so identity-based lookup works regardless of the caller passing a
|
|
35
|
+
# fresh `Namespace.new` or an already-interned instance.
|
|
36
|
+
def self.[](namespace, name)
|
|
37
|
+
ns = Namespace[namespace.path, namespace.absolute?]
|
|
38
|
+
|
|
39
|
+
inner = @intern_cache[ns]
|
|
40
|
+
if inner && (cached = inner[name])
|
|
41
|
+
return cached
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
@intern_mutex.synchronize do
|
|
45
|
+
inner = (@intern_cache[ns] ||= {})
|
|
46
|
+
inner[name] ||= new(namespace: ns, name: name)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
25
50
|
def ==(other)
|
|
51
|
+
return true if equal?(other)
|
|
26
52
|
other.is_a?(self.class) && other.namespace == namespace && other.name == name
|
|
27
53
|
end
|
|
28
54
|
|
|
29
55
|
alias eql? ==
|
|
30
56
|
|
|
31
57
|
def hash
|
|
32
|
-
namespace.hash ^ name.hash
|
|
58
|
+
@hash ||= namespace.hash ^ name.hash
|
|
33
59
|
end
|
|
34
60
|
|
|
35
61
|
def to_s
|
|
@@ -53,7 +79,7 @@ module RBS
|
|
|
53
79
|
end
|
|
54
80
|
|
|
55
81
|
def absolute!
|
|
56
|
-
|
|
82
|
+
TypeName[namespace.absolute!, name]
|
|
57
83
|
end
|
|
58
84
|
|
|
59
85
|
def absolute?
|
|
@@ -61,7 +87,7 @@ module RBS
|
|
|
61
87
|
end
|
|
62
88
|
|
|
63
89
|
def relative!
|
|
64
|
-
|
|
90
|
+
TypeName[namespace.relative!, name]
|
|
65
91
|
end
|
|
66
92
|
|
|
67
93
|
def interface?
|
|
@@ -69,7 +95,7 @@ module RBS
|
|
|
69
95
|
end
|
|
70
96
|
|
|
71
97
|
def with_prefix(namespace)
|
|
72
|
-
|
|
98
|
+
TypeName[namespace + self.namespace, name]
|
|
73
99
|
end
|
|
74
100
|
|
|
75
101
|
def split
|
|
@@ -80,23 +106,17 @@ module RBS
|
|
|
80
106
|
if other.absolute?
|
|
81
107
|
other
|
|
82
108
|
else
|
|
83
|
-
TypeName.
|
|
84
|
-
namespace: self.to_namespace + other.namespace,
|
|
85
|
-
name: other.name
|
|
86
|
-
)
|
|
109
|
+
TypeName[self.to_namespace + other.namespace, other.name]
|
|
87
110
|
end
|
|
88
111
|
end
|
|
89
|
-
|
|
112
|
+
|
|
90
113
|
def self.parse(string)
|
|
91
114
|
absolute = string.start_with?("::")
|
|
92
115
|
|
|
93
116
|
*path, name = string.delete_prefix("::").split("::").map(&:to_sym)
|
|
94
117
|
raise unless name
|
|
95
118
|
|
|
96
|
-
TypeName
|
|
97
|
-
name: name,
|
|
98
|
-
namespace: RBS::Namespace.new(path: path, absolute: absolute)
|
|
99
|
-
)
|
|
119
|
+
TypeName[Namespace[path, absolute], name]
|
|
100
120
|
end
|
|
101
121
|
end
|
|
102
122
|
end
|