rbs 4.0.3 → 4.1.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/.dockerignore +37 -0
- data/.github/dependabot.yml +1 -1
- data/.github/workflows/bundle-update.yml +2 -2
- 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 +74 -0
- data/.github/workflows/release-gems.yml +235 -0
- data/.github/workflows/ruby.yml +43 -3
- data/.github/workflows/rust.yml +13 -10
- 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 +5 -2
- data/.gitignore +8 -0
- data/CHANGELOG.md +113 -0
- data/Dockerfile.jruby +53 -0
- data/README.md +4 -4
- data/Rakefile +512 -82
- data/Steepfile +9 -0
- data/config.yml +26 -0
- data/core/array.rbs +243 -180
- data/core/builtin.rbs +7 -6
- data/core/class.rbs +5 -3
- 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/kernel.rbs +26 -11
- 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/ruby_vm.rbs +40 -0
- 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 +65 -7
- data/docs/rbs_by_example.md +20 -20
- data/docs/release.md +247 -0
- data/docs/syntax.md +2 -2
- data/docs/wasm_serialization.md +80 -0
- data/ext/rbs_extension/ast_translation.c +1298 -956
- data/ext/rbs_extension/ast_translation.h +4 -0
- data/ext/rbs_extension/class_constants.c +2 -0
- data/ext/rbs_extension/class_constants.h +1 -0
- data/ext/rbs_extension/extconf.rb +1 -0
- data/ext/rbs_extension/legacy_location.c +11 -6
- data/ext/rbs_extension/main.c +139 -4
- data/include/rbs/ast.h +323 -298
- data/include/rbs/defines.h +18 -0
- data/include/rbs/lexer.h +1 -0
- data/include/rbs/serialize.h +39 -0
- data/lib/rbs/annotate/rdoc_annotator.rb +27 -31
- data/lib/rbs/ast/ruby/annotations.rb +42 -0
- data/lib/rbs/ast/ruby/comment_block.rb +6 -4
- data/lib/rbs/ast/ruby/declarations.rb +11 -1
- data/lib/rbs/ast/ruby/helpers/location_helper.rb +1 -1
- data/lib/rbs/ast/ruby/members.rb +40 -1
- data/lib/rbs/buffer.rb +48 -11
- data/lib/rbs/cli.rb +3 -5
- data/lib/rbs/collection/config/lockfile_generator.rb +14 -1
- data/lib/rbs/collection/sources/git.rb +6 -0
- data/lib/rbs/definition_builder/method_builder.rb +12 -6
- data/lib/rbs/environment.rb +10 -3
- data/lib/rbs/inline_parser.rb +54 -28
- 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/rewriter.rb +70 -0
- data/lib/rbs/test/type_check.rb +6 -1
- data/lib/rbs/type_name.rb +33 -13
- data/lib/rbs/unit_test/type_assertions.rb +14 -5
- 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 +14 -2
- data/lib/rbs_jars.rb +39 -0
- data/lib/rdoc_plugin/parser.rb +5 -0
- data/rbs.gemspec +32 -2
- data/sig/annotate/rdoc_annotater.rbs +12 -9
- data/sig/ast/ruby/annotations.rbs +49 -0
- data/sig/ast/ruby/members.rbs +21 -1
- data/sig/buffer.rbs +19 -1
- data/sig/collection/config/lockfile_generator.rbs +2 -0
- data/sig/inline_parser.rbs +2 -0
- data/sig/manifest.yaml +0 -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/rewriter.rbs +45 -0
- data/sig/typename.rbs +15 -0
- data/sig/unit_test/type_assertions.rbs +6 -2
- data/sig/wasm/deserializer.rbs +66 -0
- data/sig/wasm/serialization_schema.rbs +13 -0
- data/src/ast.c +186 -162
- data/src/lexer.c +220 -193
- data/src/lexer.re +2 -1
- data/src/lexstate.c +10 -1
- data/src/parser.c +61 -8
- 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 +46 -40
- 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 +93 -0
- data/wasm/rbs_wasm.c +423 -0
- metadata +29 -6
- data/.github/workflows/milestone.yml +0 -80
- data/.vscode/extensions.json +0 -5
- data/.vscode/settings.json +0 -19
data/lib/rbs/inline_parser.rb
CHANGED
|
@@ -119,7 +119,53 @@ module RBS
|
|
|
119
119
|
|
|
120
120
|
class_decl = AST::Ruby::Declarations::ClassDecl.new(buffer, class_name, node, super_class)
|
|
121
121
|
insert_declaration(class_decl)
|
|
122
|
-
|
|
122
|
+
visit_class_or_module_body(class_decl, node)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def visit_module_node(node)
|
|
126
|
+
return if skip_node?(node)
|
|
127
|
+
|
|
128
|
+
unless module_name = constant_as_type_name(node.constant_path)
|
|
129
|
+
diagnostics << Diagnostic::NonConstantModuleName.new(
|
|
130
|
+
rbs_location(node.constant_path.location),
|
|
131
|
+
"Module name must be a constant"
|
|
132
|
+
)
|
|
133
|
+
return
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
module_decl = AST::Ruby::Declarations::ModuleDecl.new(buffer, module_name, node)
|
|
137
|
+
|
|
138
|
+
if leading_ref = comments.leading_block(node)
|
|
139
|
+
unused_annotations = [] #: Array[AST::Ruby::CommentBlock::AnnotationSyntaxError | AST::Ruby::Annotations::leading_annotation]
|
|
140
|
+
|
|
141
|
+
leading_ref.block.each_paragraph([]) do |paragraph|
|
|
142
|
+
case paragraph
|
|
143
|
+
when AST::Ruby::Annotations::ModuleSelfAnnotation
|
|
144
|
+
module_decl.members << AST::Ruby::Members::ModuleSelfMember.new(buffer, paragraph)
|
|
145
|
+
when Location
|
|
146
|
+
# Skip
|
|
147
|
+
when AST::Ruby::CommentBlock::AnnotationSyntaxError
|
|
148
|
+
unused_annotations << paragraph
|
|
149
|
+
when AST::Ruby::Annotations::SkipAnnotation
|
|
150
|
+
# Already handled by skip_node?
|
|
151
|
+
else
|
|
152
|
+
unused_annotations << paragraph
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
unless unused_annotations.empty?
|
|
157
|
+
report_unused_annotation(*unused_annotations)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
leading_ref.associate!
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
insert_declaration(module_decl)
|
|
164
|
+
visit_class_or_module_body(module_decl, node)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def visit_class_or_module_body(decl, node)
|
|
168
|
+
push_module_nesting(decl) do
|
|
123
169
|
visit_child_nodes(node)
|
|
124
170
|
|
|
125
171
|
node.child_nodes.each do |child_node|
|
|
@@ -137,7 +183,7 @@ module RBS
|
|
|
137
183
|
block.each_paragraph([]) do |paragraph|
|
|
138
184
|
case paragraph
|
|
139
185
|
when AST::Ruby::Annotations::InstanceVariableAnnotation
|
|
140
|
-
|
|
186
|
+
decl.members << AST::Ruby::Members::InstanceVariableMember.new(buffer, paragraph)
|
|
141
187
|
when Location
|
|
142
188
|
# Skip
|
|
143
189
|
when AST::Ruby::CommentBlock::AnnotationSyntaxError
|
|
@@ -150,42 +196,22 @@ module RBS
|
|
|
150
196
|
report_unused_annotation(*unused_annotations)
|
|
151
197
|
end
|
|
152
198
|
|
|
153
|
-
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def visit_module_node(node)
|
|
157
|
-
return if skip_node?(node)
|
|
158
|
-
|
|
159
|
-
unless module_name = constant_as_type_name(node.constant_path)
|
|
160
|
-
diagnostics << Diagnostic::NonConstantModuleName.new(
|
|
161
|
-
rbs_location(node.constant_path.location),
|
|
162
|
-
"Module name must be a constant"
|
|
163
|
-
)
|
|
164
|
-
return
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
module_decl = AST::Ruby::Declarations::ModuleDecl.new(buffer, module_name, node)
|
|
168
|
-
insert_declaration(module_decl)
|
|
169
|
-
push_module_nesting(module_decl) do
|
|
170
|
-
visit_child_nodes(node)
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
comments.each_enclosed_block(node) do |block|
|
|
174
|
-
report_unused_block(block)
|
|
175
|
-
end
|
|
199
|
+
decl.members.sort_by! { _1.location.start_line }
|
|
176
200
|
end
|
|
177
201
|
|
|
178
202
|
def visit_def_node(node)
|
|
179
203
|
return if skip_node?(node)
|
|
180
204
|
|
|
181
|
-
if node.receiver
|
|
205
|
+
if node.receiver && !node.receiver.is_a?(Prism::SelfNode)
|
|
182
206
|
diagnostics << Diagnostic::NotImplementedYet.new(
|
|
183
207
|
rbs_location(node.receiver.location),
|
|
184
|
-
"
|
|
208
|
+
"Method definition with non-self receiver is not supported"
|
|
185
209
|
)
|
|
186
210
|
return
|
|
187
211
|
end
|
|
188
212
|
|
|
213
|
+
kind = node.receiver ? :singleton : :instance #: :singleton | :instance
|
|
214
|
+
|
|
189
215
|
case current = current_module
|
|
190
216
|
when AST::Ruby::Declarations::ClassDecl, AST::Ruby::Declarations::ModuleDecl
|
|
191
217
|
leading_block = comments.leading_block!(node)
|
|
@@ -199,7 +225,7 @@ module RBS
|
|
|
199
225
|
method_type, leading_unuseds, trailing_unused = AST::Ruby::Members::MethodTypeAnnotation.build(leading_block, trailing_block, [], node)
|
|
200
226
|
report_unused_annotation(trailing_unused, *leading_unuseds)
|
|
201
227
|
|
|
202
|
-
defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type, leading_block)
|
|
228
|
+
defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type, leading_block, kind: kind)
|
|
203
229
|
current.members << defn
|
|
204
230
|
|
|
205
231
|
# Skip other comments in `def` node
|
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 = {}
|