rbs 4.0.0.dev.4 → 4.1.0.pre.2
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/.clang-format +1 -0
- data/.github/dependabot.yml +16 -14
- data/.github/workflows/bundle-update.yml +63 -0
- data/.github/workflows/c-check.yml +21 -11
- data/.github/workflows/comments.yml +5 -3
- data/.github/workflows/dependabot.yml +2 -2
- data/.github/workflows/jruby.yml +67 -0
- data/.github/workflows/milestone.yml +83 -0
- data/.github/workflows/ruby.yml +63 -24
- data/.github/workflows/rust.yml +184 -0
- data/.github/workflows/truffleruby.yml +54 -0
- data/.github/workflows/typecheck.yml +5 -2
- data/.github/workflows/wasm.yml +53 -0
- data/.github/workflows/windows.yml +8 -2
- data/.gitignore +11 -0
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +357 -0
- data/README.md +4 -4
- data/Rakefile +365 -33
- data/Steepfile +8 -0
- data/config.yml +450 -24
- data/core/array.rbs +443 -363
- data/core/basic_object.rbs +9 -8
- data/core/binding.rbs +0 -2
- data/core/builtin.rbs +9 -8
- data/core/class.rbs +11 -8
- data/core/comparable.rbs +55 -34
- data/core/complex.rbs +104 -78
- data/core/dir.rbs +61 -49
- data/core/encoding.rbs +12 -15
- data/core/enumerable.rbs +288 -196
- data/core/enumerator/arithmetic_sequence.rbs +70 -0
- data/core/enumerator/product.rbs +5 -5
- data/core/enumerator.rbs +91 -28
- data/core/errno.rbs +11 -2
- data/core/errors.rbs +58 -29
- data/core/exception.rbs +13 -13
- data/core/fiber.rbs +74 -54
- data/core/file.rbs +260 -1151
- data/core/file_constants.rbs +463 -0
- data/core/file_stat.rbs +534 -0
- data/core/file_test.rbs +3 -3
- data/core/float.rbs +257 -92
- data/core/gc.rbs +425 -281
- data/core/hash.rbs +1151 -829
- data/core/integer.rbs +156 -195
- data/core/io/buffer.rbs +53 -42
- data/core/io/wait.rbs +13 -35
- data/core/io.rbs +216 -150
- data/core/kernel.rbs +239 -163
- data/core/marshal.rbs +4 -4
- data/core/match_data.rbs +15 -13
- data/core/math.rbs +107 -66
- data/core/method.rbs +69 -33
- data/core/module.rbs +302 -150
- data/core/nil_class.rbs +7 -6
- data/core/numeric.rbs +77 -63
- data/core/object.rbs +9 -11
- data/core/object_space/weak_key_map.rbs +7 -7
- data/core/object_space.rbs +30 -23
- data/core/pathname.rbs +1322 -0
- data/core/proc.rbs +95 -58
- data/core/process.rbs +222 -202
- data/core/ractor.rbs +371 -515
- data/core/random.rbs +21 -3
- data/core/range.rbs +181 -79
- data/core/rational.rbs +60 -89
- data/core/rbs/ops.rbs +154 -0
- data/core/rbs/unnamed/argf.rbs +63 -56
- data/core/rbs/unnamed/env_class.rbs +19 -14
- data/core/rbs/unnamed/main_class.rbs +123 -0
- data/core/rbs/unnamed/random.rbs +11 -118
- data/core/regexp.rbs +258 -214
- data/core/ruby.rbs +53 -0
- data/core/ruby_vm.rbs +78 -34
- data/core/rubygems/config_file.rbs +5 -5
- data/core/rubygems/errors.rbs +4 -71
- data/core/rubygems/requirement.rbs +5 -5
- data/core/rubygems/rubygems.rbs +16 -82
- data/core/rubygems/version.rbs +2 -3
- data/core/set.rbs +493 -363
- data/core/signal.rbs +26 -16
- data/core/string.rbs +3234 -1285
- data/core/struct.rbs +43 -42
- data/core/symbol.rbs +41 -34
- data/core/thread.rbs +141 -73
- data/core/time.rbs +81 -50
- data/core/trace_point.rbs +41 -35
- data/core/true_class.rbs +2 -2
- data/core/unbound_method.rbs +24 -16
- data/core/warning.rbs +7 -7
- data/docs/CONTRIBUTING.md +2 -1
- data/docs/aliases.md +79 -0
- data/docs/collection.md +3 -3
- data/docs/config.md +171 -0
- data/docs/encoding.md +56 -0
- data/docs/gem.md +0 -1
- data/docs/inline.md +634 -0
- data/docs/rbs_by_example.md +20 -20
- data/docs/rust.md +96 -0
- data/docs/sigs.md +3 -3
- data/docs/syntax.md +48 -18
- data/docs/type_fingerprint.md +21 -0
- data/docs/wasm_serialization.md +80 -0
- data/exe/rbs +1 -1
- data/ext/rbs_extension/ast_translation.c +1441 -671
- data/ext/rbs_extension/ast_translation.h +7 -0
- data/ext/rbs_extension/class_constants.c +18 -2
- data/ext/rbs_extension/class_constants.h +9 -0
- data/ext/rbs_extension/extconf.rb +6 -1
- data/ext/rbs_extension/legacy_location.c +33 -56
- data/ext/rbs_extension/legacy_location.h +37 -0
- data/ext/rbs_extension/main.c +183 -39
- data/include/rbs/ast.h +597 -297
- data/include/rbs/defines.h +40 -0
- data/include/rbs/lexer.h +31 -11
- data/include/rbs/location.h +25 -44
- data/include/rbs/parser.h +6 -6
- data/include/rbs/serialize.h +39 -0
- data/include/rbs/string.h +0 -2
- data/include/rbs/util/rbs_allocator.h +34 -13
- data/include/rbs/util/rbs_assert.h +12 -1
- data/include/rbs/util/rbs_constant_pool.h +0 -3
- data/include/rbs/util/rbs_encoding.h +2 -0
- data/include/rbs/util/rbs_unescape.h +2 -1
- data/include/rbs.h +8 -0
- data/lib/rbs/annotate/rdoc_annotator.rb +27 -31
- data/lib/rbs/ast/annotation.rb +1 -1
- data/lib/rbs/ast/comment.rb +1 -1
- data/lib/rbs/ast/declarations.rb +10 -10
- data/lib/rbs/ast/members.rb +14 -14
- data/lib/rbs/ast/ruby/annotations.rb +335 -3
- data/lib/rbs/ast/ruby/comment_block.rb +30 -4
- data/lib/rbs/ast/ruby/declarations.rb +209 -4
- data/lib/rbs/ast/ruby/helpers/constant_helper.rb +4 -0
- data/lib/rbs/ast/ruby/helpers/location_helper.rb +1 -1
- data/lib/rbs/ast/ruby/members.rb +571 -22
- data/lib/rbs/ast/type_param.rb +24 -4
- data/lib/rbs/buffer.rb +66 -24
- data/lib/rbs/cli/diff.rb +16 -15
- data/lib/rbs/cli/validate.rb +38 -106
- data/lib/rbs/cli.rb +55 -24
- data/lib/rbs/collection/config/lockfile_generator.rb +28 -3
- data/lib/rbs/collection/sources/git.rb +7 -0
- data/lib/rbs/definition.rb +1 -1
- data/lib/rbs/definition_builder/ancestor_builder.rb +62 -9
- data/lib/rbs/definition_builder/method_builder.rb +32 -6
- data/lib/rbs/definition_builder.rb +147 -25
- data/lib/rbs/diff.rb +7 -1
- data/lib/rbs/environment.rb +235 -75
- data/lib/rbs/environment_loader.rb +0 -6
- data/lib/rbs/errors.rb +27 -18
- data/lib/rbs/inline_parser.rb +377 -15
- data/lib/rbs/location_aux.rb +1 -1
- data/lib/rbs/locator.rb +5 -1
- data/lib/rbs/method_type.rb +5 -3
- data/lib/rbs/namespace.rb +47 -11
- data/lib/rbs/parser_aux.rb +20 -7
- data/lib/rbs/prototype/helpers.rb +57 -0
- data/lib/rbs/prototype/rb.rb +3 -28
- data/lib/rbs/prototype/rbi.rb +3 -20
- data/lib/rbs/prototype/runtime.rb +10 -0
- data/lib/rbs/resolver/constant_resolver.rb +2 -2
- data/lib/rbs/resolver/type_name_resolver.rb +120 -44
- data/lib/rbs/rewriter.rb +70 -0
- data/lib/rbs/subtractor.rb +3 -1
- data/lib/rbs/test/type_check.rb +25 -3
- data/lib/rbs/type_name.rb +34 -14
- data/lib/rbs/types.rb +88 -78
- data/lib/rbs/unit_test/type_assertions.rb +44 -8
- data/lib/rbs/validator.rb +2 -2
- 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 +217 -0
- data/lib/rbs/wasm/serialization_schema.rb +110 -0
- data/lib/rbs.rb +13 -2
- data/lib/rdoc/discover.rb +1 -1
- data/lib/rdoc_plugin/parser.rb +1 -1
- data/rbs.gemspec +24 -6
- data/schema/typeParam.json +17 -1
- data/sig/annotate/rdoc_annotater.rbs +12 -9
- data/sig/ast/ruby/annotations.rbs +364 -4
- data/sig/ast/ruby/comment_block.rbs +8 -0
- data/sig/ast/ruby/declarations.rbs +102 -4
- data/sig/ast/ruby/members.rbs +128 -2
- data/sig/buffer.rbs +19 -1
- data/sig/cli/diff.rbs +5 -11
- data/sig/cli/validate.rbs +12 -8
- data/sig/cli.rbs +18 -18
- data/sig/collection/config/lockfile_generator.rbs +2 -0
- data/sig/definition.rbs +6 -1
- data/sig/definition_builder.rbs +2 -0
- data/sig/environment.rbs +70 -12
- data/sig/errors.rbs +13 -14
- data/sig/inline_parser.rbs +41 -2
- data/sig/locator.rbs +0 -2
- data/sig/manifest.yaml +0 -2
- data/sig/method_builder.rbs +3 -1
- data/sig/namespace.rbs +20 -0
- data/sig/parser.rbs +41 -13
- data/sig/prototype/helpers.rbs +2 -0
- data/sig/resolver/type_name_resolver.rbs +36 -10
- data/sig/rewriter.rbs +45 -0
- data/sig/source.rbs +3 -3
- data/sig/type_param.rbs +13 -8
- data/sig/typename.rbs +15 -0
- data/sig/types.rbs +6 -7
- data/sig/unit_test/spy.rbs +0 -8
- data/sig/unit_test/type_assertions.rbs +15 -0
- data/sig/wasm/deserializer.rbs +66 -0
- data/sig/wasm/serialization_schema.rbs +13 -0
- data/src/ast.c +443 -162
- data/src/lexer.c +1415 -1313
- data/src/lexer.re +4 -0
- data/src/lexstate.c +63 -37
- data/src/location.c +7 -47
- data/src/parser.c +1032 -521
- data/src/serialize.c +958 -0
- data/src/string.c +0 -48
- data/src/util/rbs_allocator.c +89 -74
- data/src/util/rbs_assert.c +1 -1
- data/src/util/rbs_buffer.c +2 -2
- data/src/util/rbs_constant_pool.c +10 -14
- data/src/util/rbs_encoding.c +4 -8
- data/src/util/rbs_unescape.c +56 -20
- data/stdlib/abbrev/0/array.rbs +1 -1
- data/stdlib/bigdecimal/0/big_decimal.rbs +116 -98
- data/stdlib/bigdecimal-math/0/big_math.rbs +169 -8
- data/stdlib/cgi/0/core.rbs +9 -393
- data/stdlib/cgi/0/manifest.yaml +1 -0
- data/stdlib/cgi-escape/0/escape.rbs +171 -0
- data/stdlib/coverage/0/coverage.rbs +7 -4
- data/stdlib/csv/0/csv.rbs +5 -5
- data/stdlib/date/0/date.rbs +92 -79
- data/stdlib/date/0/date_time.rbs +25 -24
- data/stdlib/delegate/0/delegator.rbs +10 -7
- data/stdlib/did_you_mean/0/did_you_mean.rbs +17 -16
- data/stdlib/digest/0/digest.rbs +111 -1
- data/stdlib/erb/0/erb.rbs +748 -347
- data/stdlib/etc/0/etc.rbs +73 -54
- data/stdlib/fileutils/0/fileutils.rbs +179 -160
- data/stdlib/forwardable/0/forwardable.rbs +13 -10
- data/stdlib/io-console/0/io-console.rbs +2 -2
- data/stdlib/json/0/json.rbs +223 -142
- data/stdlib/monitor/0/monitor.rbs +3 -3
- data/stdlib/net-http/0/net-http.rbs +162 -134
- data/stdlib/objspace/0/objspace.rbs +17 -34
- data/stdlib/open-uri/0/open-uri.rbs +48 -8
- data/stdlib/open3/0/open3.rbs +469 -10
- data/stdlib/openssl/0/openssl.rbs +482 -364
- data/stdlib/optparse/0/optparse.rbs +26 -17
- data/stdlib/pathname/0/pathname.rbs +11 -1381
- data/stdlib/pp/0/pp.rbs +9 -8
- data/stdlib/prettyprint/0/prettyprint.rbs +7 -7
- data/stdlib/pstore/0/pstore.rbs +35 -30
- data/stdlib/psych/0/psych.rbs +65 -12
- data/stdlib/psych/0/store.rbs +2 -4
- data/stdlib/pty/0/pty.rbs +9 -6
- data/stdlib/random-formatter/0/random-formatter.rbs +277 -0
- data/stdlib/rdoc/0/code_object.rbs +2 -1
- data/stdlib/rdoc/0/parser.rbs +1 -1
- data/stdlib/rdoc/0/rdoc.rbs +1 -1
- data/stdlib/rdoc/0/store.rbs +1 -1
- data/stdlib/resolv/0/resolv.rbs +26 -69
- data/stdlib/ripper/0/ripper.rbs +22 -19
- data/stdlib/securerandom/0/manifest.yaml +2 -0
- data/stdlib/securerandom/0/securerandom.rbs +7 -20
- data/stdlib/shellwords/0/shellwords.rbs +3 -3
- data/stdlib/singleton/0/singleton.rbs +3 -0
- data/stdlib/socket/0/addrinfo.rbs +7 -7
- data/stdlib/socket/0/basic_socket.rbs +3 -3
- data/stdlib/socket/0/ip_socket.rbs +10 -8
- data/stdlib/socket/0/socket.rbs +23 -10
- data/stdlib/socket/0/tcp_server.rbs +1 -1
- data/stdlib/socket/0/tcp_socket.rbs +11 -3
- data/stdlib/socket/0/udp_socket.rbs +1 -1
- data/stdlib/socket/0/unix_server.rbs +1 -1
- data/stdlib/stringio/0/stringio.rbs +1209 -95
- data/stdlib/strscan/0/string_scanner.rbs +101 -80
- data/stdlib/tempfile/0/tempfile.rbs +25 -21
- data/stdlib/time/0/time.rbs +8 -6
- data/stdlib/timeout/0/timeout.rbs +63 -7
- data/stdlib/tsort/0/cyclic.rbs +4 -1
- data/stdlib/tsort/0/interfaces.rbs +8 -8
- data/stdlib/tsort/0/tsort.rbs +16 -15
- data/stdlib/uri/0/common.rbs +42 -20
- data/stdlib/uri/0/file.rbs +3 -3
- data/stdlib/uri/0/generic.rbs +26 -18
- data/stdlib/uri/0/http.rbs +2 -2
- data/stdlib/uri/0/ldap.rbs +2 -2
- data/stdlib/uri/0/mailto.rbs +3 -3
- data/stdlib/uri/0/rfc2396_parser.rbs +12 -12
- data/stdlib/zlib/0/deflate.rbs +4 -3
- data/stdlib/zlib/0/gzip_reader.rbs +8 -8
- data/stdlib/zlib/0/gzip_writer.rbs +14 -12
- data/stdlib/zlib/0/inflate.rbs +1 -1
- data/stdlib/zlib/0/need_dict.rbs +1 -1
- data/stdlib/zlib/0/zstream.rbs +1 -0
- data/wasm/README.md +59 -0
- data/wasm/rbs_wasm.c +411 -0
- metadata +56 -8
- data/.vscode/extensions.json +0 -5
- data/.vscode/settings.json +0 -19
data/lib/rbs/inline_parser.rb
CHANGED
|
@@ -11,6 +11,10 @@ module RBS
|
|
|
11
11
|
@declarations = []
|
|
12
12
|
@diagnostics = []
|
|
13
13
|
end
|
|
14
|
+
|
|
15
|
+
def type_fingerprint
|
|
16
|
+
declarations.map(&:type_fingerprint)
|
|
17
|
+
end
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
module Diagnostic
|
|
@@ -26,15 +30,26 @@ module RBS
|
|
|
26
30
|
NotImplementedYet = _ = Class.new(Base)
|
|
27
31
|
NonConstantClassName = _ = Class.new(Base)
|
|
28
32
|
NonConstantModuleName = _ = Class.new(Base)
|
|
33
|
+
NonConstantSuperClassName = _ = Class.new(Base)
|
|
29
34
|
TopLevelMethodDefinition = _ = Class.new(Base)
|
|
35
|
+
TopLevelAttributeDefinition = _ = Class.new(Base)
|
|
36
|
+
NonConstantConstantDeclaration = _ = Class.new(Base)
|
|
30
37
|
UnusedInlineAnnotation = _ = Class.new(Base)
|
|
31
38
|
AnnotationSyntaxError = _ = Class.new(Base)
|
|
39
|
+
MixinMultipleArguments = _ = Class.new(Base)
|
|
40
|
+
MixinNonConstantModule = _ = Class.new(Base)
|
|
41
|
+
AttributeNonSymbolName = _ = Class.new(Base)
|
|
42
|
+
ClassModuleAliasDeclarationMissingTypeName = _ = Class.new(Base)
|
|
32
43
|
end
|
|
33
44
|
|
|
34
45
|
def self.parse(buffer, prism)
|
|
35
46
|
result = Result.new(buffer, prism)
|
|
36
47
|
|
|
37
|
-
Parser.new(result)
|
|
48
|
+
parser = Parser.new(result)
|
|
49
|
+
parser.visit(prism.value)
|
|
50
|
+
parser.comments.each_unassociated_block do |block|
|
|
51
|
+
parser.report_unused_block(block)
|
|
52
|
+
end
|
|
38
53
|
|
|
39
54
|
result
|
|
40
55
|
end
|
|
@@ -96,15 +111,15 @@ module RBS
|
|
|
96
111
|
return
|
|
97
112
|
end
|
|
98
113
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
114
|
+
# Parse super class if present
|
|
115
|
+
super_class = if node.superclass
|
|
116
|
+
node.inheritance_operator_loc or raise
|
|
117
|
+
parse_super_class(node.superclass, node.inheritance_operator_loc)
|
|
103
118
|
end
|
|
104
119
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
120
|
+
class_decl = AST::Ruby::Declarations::ClassDecl.new(buffer, class_name, node, super_class)
|
|
121
|
+
insert_declaration(class_decl)
|
|
122
|
+
visit_class_or_module_body(class_decl, node)
|
|
108
123
|
end
|
|
109
124
|
|
|
110
125
|
def visit_module_node(node)
|
|
@@ -119,27 +134,84 @@ module RBS
|
|
|
119
134
|
end
|
|
120
135
|
|
|
121
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
|
+
|
|
122
163
|
insert_declaration(module_decl)
|
|
123
|
-
|
|
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
|
|
124
169
|
visit_child_nodes(node)
|
|
170
|
+
|
|
171
|
+
node.child_nodes.each do |child_node|
|
|
172
|
+
if child_node
|
|
173
|
+
comments.each_enclosed_block(child_node) do |block|
|
|
174
|
+
report_unused_block(block)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
125
178
|
end
|
|
126
179
|
|
|
127
180
|
comments.each_enclosed_block(node) do |block|
|
|
128
|
-
|
|
181
|
+
unused_annotations = [] #: Array[AST::Ruby::CommentBlock::AnnotationSyntaxError | AST::Ruby::Annotations::leading_annotation]
|
|
182
|
+
|
|
183
|
+
block.each_paragraph([]) do |paragraph|
|
|
184
|
+
case paragraph
|
|
185
|
+
when AST::Ruby::Annotations::InstanceVariableAnnotation
|
|
186
|
+
decl.members << AST::Ruby::Members::InstanceVariableMember.new(buffer, paragraph)
|
|
187
|
+
when Location
|
|
188
|
+
# Skip
|
|
189
|
+
when AST::Ruby::CommentBlock::AnnotationSyntaxError
|
|
190
|
+
unused_annotations << paragraph
|
|
191
|
+
else
|
|
192
|
+
unused_annotations << paragraph
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
report_unused_annotation(*unused_annotations)
|
|
129
197
|
end
|
|
198
|
+
|
|
199
|
+
decl.members.sort_by! { _1.location.start_line }
|
|
130
200
|
end
|
|
131
201
|
|
|
132
202
|
def visit_def_node(node)
|
|
133
203
|
return if skip_node?(node)
|
|
134
204
|
|
|
135
|
-
if node.receiver
|
|
205
|
+
if node.receiver && !node.receiver.is_a?(Prism::SelfNode)
|
|
136
206
|
diagnostics << Diagnostic::NotImplementedYet.new(
|
|
137
207
|
rbs_location(node.receiver.location),
|
|
138
|
-
"
|
|
208
|
+
"Method definition with non-self receiver is not supported"
|
|
139
209
|
)
|
|
140
210
|
return
|
|
141
211
|
end
|
|
142
212
|
|
|
213
|
+
kind = node.receiver ? :singleton : :instance #: :singleton | :instance
|
|
214
|
+
|
|
143
215
|
case current = current_module
|
|
144
216
|
when AST::Ruby::Declarations::ClassDecl, AST::Ruby::Declarations::ModuleDecl
|
|
145
217
|
leading_block = comments.leading_block!(node)
|
|
@@ -150,15 +222,15 @@ module RBS
|
|
|
150
222
|
trailing_block = comments.trailing_block!(end_loc)
|
|
151
223
|
end
|
|
152
224
|
|
|
153
|
-
method_type, leading_unuseds, trailing_unused = AST::Ruby::Members::MethodTypeAnnotation.build(leading_block, trailing_block, [])
|
|
225
|
+
method_type, leading_unuseds, trailing_unused = AST::Ruby::Members::MethodTypeAnnotation.build(leading_block, trailing_block, [], node)
|
|
154
226
|
report_unused_annotation(trailing_unused, *leading_unuseds)
|
|
155
227
|
|
|
156
|
-
defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type)
|
|
228
|
+
defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type, leading_block, kind: kind)
|
|
157
229
|
current.members << defn
|
|
158
230
|
|
|
159
231
|
# Skip other comments in `def` node
|
|
160
232
|
comments.each_enclosed_block(node) do |block|
|
|
161
|
-
|
|
233
|
+
report_unused_block(block)
|
|
162
234
|
end
|
|
163
235
|
else
|
|
164
236
|
diagnostics << Diagnostic::TopLevelMethodDefinition.new(
|
|
@@ -168,6 +240,261 @@ module RBS
|
|
|
168
240
|
end
|
|
169
241
|
end
|
|
170
242
|
|
|
243
|
+
def visit_call_node(node)
|
|
244
|
+
return unless node.receiver.nil? # Only handle top-level calls like include, extend, prepend, attr_*
|
|
245
|
+
|
|
246
|
+
case node.name
|
|
247
|
+
when :include, :extend, :prepend
|
|
248
|
+
return if skip_node?(node)
|
|
249
|
+
|
|
250
|
+
case current = current_module
|
|
251
|
+
when AST::Ruby::Declarations::ClassDecl, AST::Ruby::Declarations::ModuleDecl
|
|
252
|
+
parse_mixin_call(node)
|
|
253
|
+
end
|
|
254
|
+
when :attr_reader, :attr_writer, :attr_accessor
|
|
255
|
+
return if skip_node?(node)
|
|
256
|
+
|
|
257
|
+
case current = current_module
|
|
258
|
+
when AST::Ruby::Declarations::ClassDecl, AST::Ruby::Declarations::ModuleDecl
|
|
259
|
+
parse_attribute_call(node)
|
|
260
|
+
when nil
|
|
261
|
+
# Top-level attribute definition
|
|
262
|
+
diagnostics << Diagnostic::TopLevelAttributeDefinition.new(
|
|
263
|
+
rbs_location(node.message_loc || node.location),
|
|
264
|
+
"Top-level attribute definition is not supported"
|
|
265
|
+
)
|
|
266
|
+
end
|
|
267
|
+
else
|
|
268
|
+
visit_child_nodes(node)
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def visit_constant_write_node(node)
|
|
273
|
+
return if skip_node?(node)
|
|
274
|
+
|
|
275
|
+
# Parse constant declaration (both top-level and in classes/modules)
|
|
276
|
+
parse_constant_declaration(node)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def visit_constant_path_write_node(node)
|
|
280
|
+
return if skip_node?(node)
|
|
281
|
+
|
|
282
|
+
parse_constant_declaration(node)
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def parse_mixin_call(node)
|
|
286
|
+
# Check for multiple arguments
|
|
287
|
+
if node.arguments && node.arguments.arguments.length > 1
|
|
288
|
+
diagnostics << Diagnostic::MixinMultipleArguments.new(
|
|
289
|
+
rbs_location(node.location),
|
|
290
|
+
"Mixing multiple modules with one call is not supported"
|
|
291
|
+
)
|
|
292
|
+
return
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# Check for missing arguments
|
|
296
|
+
unless node.arguments && node.arguments.arguments.length == 1
|
|
297
|
+
# This shouldn't happen in valid Ruby code, but handle it gracefully
|
|
298
|
+
return
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
first_arg = node.arguments.arguments.first
|
|
302
|
+
|
|
303
|
+
# Check if the argument is a constant
|
|
304
|
+
unless module_name = constant_as_type_name(first_arg)
|
|
305
|
+
diagnostics << Diagnostic::MixinNonConstantModule.new(
|
|
306
|
+
rbs_location(first_arg.location),
|
|
307
|
+
"Module name must be a constant"
|
|
308
|
+
)
|
|
309
|
+
return
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
# Look for type application annotation in trailing comments
|
|
313
|
+
# For single-line calls like "include Bar #[String]", the annotation is trailing
|
|
314
|
+
trailing_block = comments.trailing_block!(node.location)
|
|
315
|
+
annotation = nil
|
|
316
|
+
|
|
317
|
+
if trailing_block
|
|
318
|
+
case trailing_annotation = trailing_block.trailing_annotation([])
|
|
319
|
+
when AST::Ruby::Annotations::TypeApplicationAnnotation
|
|
320
|
+
annotation = trailing_annotation
|
|
321
|
+
else
|
|
322
|
+
report_unused_annotation(trailing_annotation)
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
# Create the appropriate member based on the method name
|
|
327
|
+
member = case node.name
|
|
328
|
+
when :include
|
|
329
|
+
AST::Ruby::Members::IncludeMember.new(buffer, node, module_name, annotation)
|
|
330
|
+
when :extend
|
|
331
|
+
AST::Ruby::Members::ExtendMember.new(buffer, node, module_name, annotation)
|
|
332
|
+
when :prepend
|
|
333
|
+
AST::Ruby::Members::PrependMember.new(buffer, node, module_name, annotation)
|
|
334
|
+
else
|
|
335
|
+
raise "Unexpected mixin method: #{node.name}"
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
current_module!.members << member
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def parse_attribute_call(node)
|
|
342
|
+
# Get the name nodes (arguments to attr_*)
|
|
343
|
+
unless node.arguments && !node.arguments.arguments.empty?
|
|
344
|
+
return # No arguments, nothing to do
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
name_nodes = [] #: Array[Prism::SymbolNode]
|
|
348
|
+
node.arguments.arguments.each do |arg|
|
|
349
|
+
case arg
|
|
350
|
+
when Prism::SymbolNode
|
|
351
|
+
name_nodes << arg
|
|
352
|
+
else
|
|
353
|
+
# Non-symbol argument, report error
|
|
354
|
+
diagnostics << Diagnostic::AttributeNonSymbolName.new(
|
|
355
|
+
rbs_location(arg.location),
|
|
356
|
+
"Attribute name must be a symbol"
|
|
357
|
+
)
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
return if name_nodes.empty?
|
|
362
|
+
|
|
363
|
+
# Look for leading comment block
|
|
364
|
+
leading_block = comments.leading_block!(node)
|
|
365
|
+
|
|
366
|
+
# Look for trailing type annotation (#: Type)
|
|
367
|
+
trailing_block = comments.trailing_block!(node.location)
|
|
368
|
+
type_annotation = nil
|
|
369
|
+
|
|
370
|
+
if trailing_block
|
|
371
|
+
case annotation = trailing_block.trailing_annotation([])
|
|
372
|
+
when AST::Ruby::Annotations::NodeTypeAssertion
|
|
373
|
+
type_annotation = annotation
|
|
374
|
+
when AST::Ruby::CommentBlock::AnnotationSyntaxError
|
|
375
|
+
diagnostics << Diagnostic::AnnotationSyntaxError.new(
|
|
376
|
+
annotation.location, "Syntax error: " + annotation.error.error_message
|
|
377
|
+
)
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
# Report unused leading annotations since @rbs annotations are not used for attributes
|
|
382
|
+
if leading_block
|
|
383
|
+
report_unused_block(leading_block)
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
# Create the appropriate member type
|
|
387
|
+
member = case node.name
|
|
388
|
+
when :attr_reader
|
|
389
|
+
AST::Ruby::Members::AttrReaderMember.new(buffer, node, name_nodes, leading_block, type_annotation)
|
|
390
|
+
when :attr_writer
|
|
391
|
+
AST::Ruby::Members::AttrWriterMember.new(buffer, node, name_nodes, leading_block, type_annotation)
|
|
392
|
+
when :attr_accessor
|
|
393
|
+
AST::Ruby::Members::AttrAccessorMember.new(buffer, node, name_nodes, leading_block, type_annotation)
|
|
394
|
+
else
|
|
395
|
+
raise "Unexpected attribute method: #{node.name}"
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
current_module!.members << member
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
def parse_constant_declaration(node)
|
|
402
|
+
# Create TypeName for the constant
|
|
403
|
+
unless constant_name = constant_as_type_name(node)
|
|
404
|
+
location =
|
|
405
|
+
case node
|
|
406
|
+
when Prism::ConstantWriteNode
|
|
407
|
+
node.name_loc
|
|
408
|
+
when Prism::ConstantPathWriteNode
|
|
409
|
+
node.target.location
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
diagnostics << Diagnostic::NonConstantConstantDeclaration.new(
|
|
413
|
+
rbs_location(location),
|
|
414
|
+
"Constant name must be a constant"
|
|
415
|
+
)
|
|
416
|
+
return
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
# Look for leading comment block
|
|
420
|
+
leading_block = comments.leading_block!(node)
|
|
421
|
+
report_unused_block(leading_block) if leading_block
|
|
422
|
+
|
|
423
|
+
# Look for trailing type annotation (#: Type)
|
|
424
|
+
trailing_block = comments.trailing_block!(node.location)
|
|
425
|
+
type_annotation = nil
|
|
426
|
+
alias_annotation = nil
|
|
427
|
+
|
|
428
|
+
if trailing_block
|
|
429
|
+
case annotation = trailing_block.trailing_annotation([])
|
|
430
|
+
when AST::Ruby::Annotations::NodeTypeAssertion
|
|
431
|
+
type_annotation = annotation
|
|
432
|
+
when AST::Ruby::Annotations::ClassAliasAnnotation, AST::Ruby::Annotations::ModuleAliasAnnotation
|
|
433
|
+
alias_annotation = annotation
|
|
434
|
+
when AST::Ruby::CommentBlock::AnnotationSyntaxError
|
|
435
|
+
diagnostics << Diagnostic::AnnotationSyntaxError.new(
|
|
436
|
+
annotation.location, "Syntax error: " + annotation.error.error_message
|
|
437
|
+
)
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
# Handle class/module alias declarations
|
|
442
|
+
if alias_annotation
|
|
443
|
+
# Try to infer the old name from the right-hand side
|
|
444
|
+
infered_old_name = constant_as_type_name(node.value)
|
|
445
|
+
|
|
446
|
+
# Check if we have either an explicit type name or can infer one
|
|
447
|
+
if alias_annotation.type_name.nil? && infered_old_name.nil?
|
|
448
|
+
message =
|
|
449
|
+
if alias_annotation.is_a?(AST::Ruby::Annotations::ClassAliasAnnotation)
|
|
450
|
+
"Class name is missing in class alias declaration"
|
|
451
|
+
else
|
|
452
|
+
"Module name is missing in module alias declaration"
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
diagnostics << Diagnostic::ClassModuleAliasDeclarationMissingTypeName.new(
|
|
456
|
+
alias_annotation.location,
|
|
457
|
+
message
|
|
458
|
+
)
|
|
459
|
+
return
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
# Create class/module alias declaration
|
|
463
|
+
alias_decl = AST::Ruby::Declarations::ClassModuleAliasDecl.new(
|
|
464
|
+
buffer,
|
|
465
|
+
node,
|
|
466
|
+
constant_name,
|
|
467
|
+
infered_old_name,
|
|
468
|
+
leading_block,
|
|
469
|
+
alias_annotation
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
# Insert the alias declaration appropriately
|
|
473
|
+
|
|
474
|
+
if current_module
|
|
475
|
+
current_module.members << alias_decl
|
|
476
|
+
else
|
|
477
|
+
result.declarations << alias_decl
|
|
478
|
+
end
|
|
479
|
+
else
|
|
480
|
+
# Create regular constant declaration
|
|
481
|
+
constant_decl = AST::Ruby::Declarations::ConstantDecl.new(
|
|
482
|
+
buffer,
|
|
483
|
+
constant_name,
|
|
484
|
+
node,
|
|
485
|
+
leading_block,
|
|
486
|
+
type_annotation
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
# Insert the constant declaration appropriately
|
|
490
|
+
if current_module
|
|
491
|
+
current_module.members << constant_decl
|
|
492
|
+
else
|
|
493
|
+
result.declarations << constant_decl
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
end
|
|
497
|
+
|
|
171
498
|
def insert_declaration(decl)
|
|
172
499
|
if current_module
|
|
173
500
|
current_module.members << decl
|
|
@@ -192,6 +519,8 @@ module RBS
|
|
|
192
519
|
end
|
|
193
520
|
|
|
194
521
|
def report_unused_block(block)
|
|
522
|
+
return unless block.leading?
|
|
523
|
+
|
|
195
524
|
block.each_paragraph([]) do |paragraph|
|
|
196
525
|
case paragraph
|
|
197
526
|
when Location
|
|
@@ -201,6 +530,39 @@ module RBS
|
|
|
201
530
|
end
|
|
202
531
|
end
|
|
203
532
|
end
|
|
533
|
+
|
|
534
|
+
def parse_super_class(super_class_expr, inheritance_operator_loc)
|
|
535
|
+
# Check if the superclass is a constant
|
|
536
|
+
unless super_class_name = constant_as_type_name(super_class_expr)
|
|
537
|
+
diagnostics << Diagnostic::NonConstantSuperClassName.new(
|
|
538
|
+
rbs_location(super_class_expr.location),
|
|
539
|
+
"Super class name must be a constant"
|
|
540
|
+
)
|
|
541
|
+
return nil
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
# Look for type application annotation in trailing comments
|
|
545
|
+
# For example: class StringArray < Array #[String]
|
|
546
|
+
trailing_block = comments.trailing_block!(super_class_expr.location)
|
|
547
|
+
type_annotation = nil
|
|
548
|
+
|
|
549
|
+
if trailing_block
|
|
550
|
+
case annotation = trailing_block.trailing_annotation([])
|
|
551
|
+
when AST::Ruby::Annotations::TypeApplicationAnnotation
|
|
552
|
+
type_annotation = annotation
|
|
553
|
+
else
|
|
554
|
+
report_unused_annotation(annotation)
|
|
555
|
+
end
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
# Create SuperClass object
|
|
559
|
+
AST::Ruby::Declarations::ClassDecl::SuperClass.new(
|
|
560
|
+
rbs_location(super_class_expr.location),
|
|
561
|
+
rbs_location(inheritance_operator_loc),
|
|
562
|
+
super_class_name,
|
|
563
|
+
type_annotation
|
|
564
|
+
)
|
|
565
|
+
end
|
|
204
566
|
end
|
|
205
567
|
end
|
|
206
568
|
end
|
data/lib/rbs/location_aux.rb
CHANGED
data/lib/rbs/locator.rb
CHANGED
|
@@ -177,6 +177,10 @@ module RBS
|
|
|
177
177
|
find_in_type(pos, type: upper_bound, array: array) and return true
|
|
178
178
|
end
|
|
179
179
|
|
|
180
|
+
if lower_bound = type_param.lower_bound_type
|
|
181
|
+
find_in_type(pos, type: lower_bound, array: array) and return true
|
|
182
|
+
end
|
|
183
|
+
|
|
180
184
|
if default_type = type_param.default_type
|
|
181
185
|
find_in_type(pos, type: default_type, array: array) and return true
|
|
182
186
|
end
|
|
@@ -234,7 +238,7 @@ module RBS
|
|
|
234
238
|
|
|
235
239
|
def test_loc(pos, location:)
|
|
236
240
|
if location
|
|
237
|
-
location.
|
|
241
|
+
location.start_pos <= pos && pos <= location.end_pos
|
|
238
242
|
else
|
|
239
243
|
false
|
|
240
244
|
end
|
data/lib/rbs/method_type.rb
CHANGED
|
@@ -21,7 +21,7 @@ module RBS
|
|
|
21
21
|
other.block == block
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def to_json(state =
|
|
24
|
+
def to_json(state = nil)
|
|
25
25
|
{
|
|
26
26
|
type_params: type_params,
|
|
27
27
|
type: type,
|
|
@@ -129,11 +129,13 @@ module RBS
|
|
|
129
129
|
end
|
|
130
130
|
|
|
131
131
|
def with_nonreturn_void?
|
|
132
|
-
if type.with_nonreturn_void?
|
|
132
|
+
if type.with_nonreturn_void? # steep:ignore DeprecatedReference
|
|
133
133
|
true
|
|
134
134
|
else
|
|
135
135
|
if block = block()
|
|
136
|
-
block.type.with_nonreturn_void? ||
|
|
136
|
+
block.type.with_nonreturn_void? || # steep:ignore DeprecatedReference
|
|
137
|
+
block.self_type&.with_nonreturn_void? || # steep:ignore DeprecatedReference
|
|
138
|
+
false
|
|
137
139
|
else
|
|
138
140
|
false
|
|
139
141
|
end
|
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
|
|