rbs 4.0.0.dev.4 → 4.0.0.dev.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +14 -14
- data/.github/workflows/bundle-update.yml +60 -0
- data/.github/workflows/c-check.yml +11 -8
- data/.github/workflows/comments.yml +3 -3
- data/.github/workflows/dependabot.yml +1 -1
- data/.github/workflows/ruby.yml +17 -34
- data/.github/workflows/typecheck.yml +2 -2
- data/.github/workflows/valgrind.yml +42 -0
- data/.github/workflows/windows.yml +2 -2
- data/.rubocop.yml +1 -1
- data/README.md +1 -1
- data/Rakefile +32 -5
- data/config.yml +46 -0
- data/core/array.rbs +96 -46
- data/core/binding.rbs +0 -2
- data/core/builtin.rbs +2 -2
- data/core/comparable.rbs +13 -6
- data/core/complex.rbs +55 -41
- data/core/dir.rbs +4 -4
- data/core/encoding.rbs +7 -10
- data/core/enumerable.rbs +90 -3
- data/core/enumerator/arithmetic_sequence.rbs +70 -0
- data/core/enumerator.rbs +63 -1
- data/core/errno.rbs +8 -0
- data/core/errors.rbs +28 -1
- data/core/exception.rbs +2 -2
- data/core/fiber.rbs +40 -20
- data/core/file.rbs +108 -78
- data/core/file_test.rbs +1 -1
- data/core/float.rbs +225 -69
- data/core/gc.rbs +417 -281
- data/core/hash.rbs +1023 -727
- data/core/integer.rbs +104 -110
- data/core/io/buffer.rbs +21 -10
- data/core/io/wait.rbs +11 -33
- data/core/io.rbs +82 -19
- data/core/kernel.rbs +70 -59
- data/core/marshal.rbs +1 -1
- data/core/match_data.rbs +1 -1
- data/core/math.rbs +42 -3
- data/core/method.rbs +63 -27
- data/core/module.rbs +103 -26
- data/core/nil_class.rbs +3 -3
- data/core/numeric.rbs +43 -35
- data/core/object.rbs +3 -3
- data/core/object_space.rbs +21 -15
- data/core/pathname.rbs +1272 -0
- data/core/proc.rbs +30 -25
- data/core/process.rbs +4 -2
- data/core/ractor.rbs +361 -509
- data/core/random.rbs +17 -0
- data/core/range.rbs +113 -16
- data/core/rational.rbs +56 -85
- data/core/rbs/unnamed/argf.rbs +2 -2
- data/core/rbs/unnamed/env_class.rbs +1 -1
- data/core/rbs/unnamed/random.rbs +4 -113
- data/core/regexp.rbs +25 -20
- data/core/ruby.rbs +53 -0
- data/core/ruby_vm.rbs +6 -4
- data/core/rubygems/errors.rbs +3 -70
- data/core/rubygems/rubygems.rbs +11 -79
- data/core/rubygems/version.rbs +2 -3
- data/core/set.rbs +488 -359
- data/core/signal.rbs +24 -14
- data/core/string.rbs +3171 -1241
- data/core/struct.rbs +1 -1
- data/core/symbol.rbs +17 -11
- data/core/thread.rbs +95 -33
- data/core/time.rbs +35 -9
- data/core/trace_point.rbs +7 -4
- data/core/unbound_method.rbs +14 -6
- data/docs/aliases.md +79 -0
- data/docs/collection.md +2 -2
- data/docs/encoding.md +56 -0
- data/docs/gem.md +0 -1
- data/docs/inline.md +470 -0
- data/docs/sigs.md +3 -3
- data/docs/syntax.md +33 -4
- data/docs/type_fingerprint.md +21 -0
- data/exe/rbs +1 -1
- data/ext/rbs_extension/ast_translation.c +77 -3
- data/ext/rbs_extension/ast_translation.h +3 -0
- data/ext/rbs_extension/class_constants.c +8 -2
- data/ext/rbs_extension/class_constants.h +4 -0
- data/ext/rbs_extension/extconf.rb +5 -1
- data/ext/rbs_extension/legacy_location.c +5 -5
- data/ext/rbs_extension/main.c +37 -20
- data/include/rbs/ast.h +85 -38
- data/include/rbs/defines.h +27 -0
- data/include/rbs/lexer.h +30 -11
- data/include/rbs/parser.h +6 -6
- 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_encoding.h +2 -0
- data/include/rbs/util/rbs_unescape.h +2 -1
- 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 +137 -0
- data/lib/rbs/ast/ruby/comment_block.rb +24 -0
- data/lib/rbs/ast/ruby/declarations.rb +198 -3
- data/lib/rbs/ast/ruby/helpers/constant_helper.rb +4 -0
- data/lib/rbs/ast/ruby/members.rb +159 -1
- data/lib/rbs/ast/type_param.rb +24 -4
- data/lib/rbs/buffer.rb +20 -15
- data/lib/rbs/cli/diff.rb +16 -15
- data/lib/rbs/cli/validate.rb +38 -51
- data/lib/rbs/cli.rb +52 -19
- data/lib/rbs/collection/config/lockfile_generator.rb +8 -0
- data/lib/rbs/collection/sources/git.rb +1 -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 +20 -0
- data/lib/rbs/definition_builder.rb +91 -2
- data/lib/rbs/diff.rb +7 -1
- data/lib/rbs/environment.rb +227 -74
- data/lib/rbs/environment_loader.rb +0 -6
- data/lib/rbs/errors.rb +27 -7
- data/lib/rbs/inline_parser.rb +341 -5
- 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/parser_aux.rb +2 -2
- data/lib/rbs/prototype/rb.rb +2 -2
- data/lib/rbs/prototype/rbi.rb +2 -0
- data/lib/rbs/prototype/runtime.rb +8 -0
- data/lib/rbs/resolver/constant_resolver.rb +2 -2
- data/lib/rbs/resolver/type_name_resolver.rb +116 -38
- data/lib/rbs/subtractor.rb +3 -1
- data/lib/rbs/test/type_check.rb +16 -2
- data/lib/rbs/type_name.rb +1 -1
- data/lib/rbs/types.rb +27 -27
- data/lib/rbs/validator.rb +2 -2
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs.rb +1 -1
- data/lib/rdoc/discover.rb +1 -1
- data/lib/rdoc_plugin/parser.rb +1 -1
- data/rbs.gemspec +3 -2
- data/schema/typeParam.json +17 -1
- data/sig/ast/ruby/annotations.rbs +124 -0
- data/sig/ast/ruby/comment_block.rbs +8 -0
- data/sig/ast/ruby/declarations.rbs +102 -4
- data/sig/ast/ruby/members.rbs +87 -1
- data/sig/cli/diff.rbs +5 -11
- data/sig/cli/validate.rbs +13 -4
- data/sig/cli.rbs +18 -18
- data/sig/definition.rbs +6 -1
- data/sig/environment.rbs +70 -12
- data/sig/errors.rbs +13 -6
- data/sig/inline_parser.rbs +39 -2
- data/sig/locator.rbs +0 -2
- data/sig/manifest.yaml +0 -1
- data/sig/method_builder.rbs +3 -1
- data/sig/method_types.rbs +1 -1
- data/sig/parser.rbs +16 -2
- data/sig/resolver/type_name_resolver.rbs +35 -7
- data/sig/source.rbs +3 -3
- data/sig/type_param.rbs +13 -8
- data/sig/types.rbs +4 -4
- data/src/ast.c +80 -1
- data/src/lexer.c +1392 -1313
- data/src/lexer.re +3 -0
- data/src/lexstate.c +58 -37
- data/src/location.c +4 -4
- data/src/parser.c +412 -145
- data/src/string.c +0 -48
- data/src/util/rbs_allocator.c +89 -71
- data/src/util/rbs_assert.c +1 -1
- data/src/util/rbs_buffer.c +2 -2
- data/src/util/rbs_constant_pool.c +10 -10
- data/src/util/rbs_encoding.c +4 -8
- data/src/util/rbs_unescape.c +56 -20
- data/stdlib/bigdecimal/0/big_decimal.rbs +100 -82
- 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 +3 -1
- data/stdlib/date/0/date.rbs +67 -59
- data/stdlib/date/0/date_time.rbs +1 -1
- data/stdlib/delegate/0/delegator.rbs +10 -7
- data/stdlib/digest/0/digest.rbs +110 -0
- data/stdlib/erb/0/erb.rbs +737 -347
- data/stdlib/fileutils/0/fileutils.rbs +20 -14
- data/stdlib/forwardable/0/forwardable.rbs +3 -0
- data/stdlib/json/0/json.rbs +82 -28
- data/stdlib/net-http/0/net-http.rbs +3 -0
- data/stdlib/objspace/0/objspace.rbs +9 -27
- data/stdlib/open-uri/0/open-uri.rbs +40 -0
- data/stdlib/open3/0/open3.rbs +459 -1
- data/stdlib/openssl/0/openssl.rbs +331 -228
- data/stdlib/optparse/0/optparse.rbs +8 -3
- data/stdlib/pathname/0/pathname.rbs +9 -1379
- data/stdlib/psych/0/psych.rbs +4 -4
- 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 +25 -68
- data/stdlib/ripper/0/ripper.rbs +2 -2
- data/stdlib/securerandom/0/manifest.yaml +2 -0
- data/stdlib/securerandom/0/securerandom.rbs +6 -19
- data/stdlib/singleton/0/singleton.rbs +3 -0
- data/stdlib/socket/0/socket.rbs +13 -1
- data/stdlib/socket/0/tcp_socket.rbs +10 -2
- data/stdlib/stringio/0/stringio.rbs +1176 -85
- data/stdlib/strscan/0/string_scanner.rbs +31 -31
- data/stdlib/tempfile/0/tempfile.rbs +3 -3
- data/stdlib/time/0/time.rbs +1 -1
- data/stdlib/timeout/0/timeout.rbs +63 -7
- data/stdlib/tsort/0/cyclic.rbs +3 -0
- data/stdlib/uri/0/common.rbs +16 -2
- data/stdlib/uri/0/file.rbs +1 -1
- data/stdlib/uri/0/generic.rbs +24 -16
- data/stdlib/uri/0/rfc2396_parser.rbs +6 -7
- data/stdlib/zlib/0/gzip_reader.rbs +2 -2
- data/stdlib/zlib/0/gzip_writer.rbs +1 -1
- data/stdlib/zlib/0/zstream.rbs +1 -0
- metadata +30 -4
data/lib/rbs/errors.rb
CHANGED
|
@@ -93,7 +93,7 @@ module RBS
|
|
|
93
93
|
params =
|
|
94
94
|
case
|
|
95
95
|
when type_name.class?
|
|
96
|
-
decl = env.
|
|
96
|
+
decl = env.module_class_entry(type_name, normalized: true) or raise
|
|
97
97
|
decl.type_params
|
|
98
98
|
when type_name.interface?
|
|
99
99
|
env.interface_decls.fetch(type_name).decl.type_params
|
|
@@ -475,7 +475,7 @@ module RBS
|
|
|
475
475
|
@type_name = type_name
|
|
476
476
|
@member = member
|
|
477
477
|
|
|
478
|
-
super "#{Location.to_string member.location}: Cannot #{mixin_name} a class `#{member
|
|
478
|
+
super "#{Location.to_string member.location}: Cannot #{mixin_name} a class `#{member_name(member)}` in the definition of `#{type_name}`"
|
|
479
479
|
end
|
|
480
480
|
|
|
481
481
|
def location
|
|
@@ -483,23 +483,43 @@ module RBS
|
|
|
483
483
|
end
|
|
484
484
|
|
|
485
485
|
def self.check!(type_name:, env:, member:)
|
|
486
|
-
|
|
486
|
+
name = case member
|
|
487
|
+
when AST::Members::Include, AST::Members::Extend, AST::Members::Prepend
|
|
488
|
+
member.name
|
|
489
|
+
when AST::Ruby::Members::IncludeMember, AST::Ruby::Members::ExtendMember, AST::Ruby::Members::PrependMember
|
|
490
|
+
member.module_name
|
|
491
|
+
else
|
|
492
|
+
raise "Unknown member type: #{member.class}"
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
if env.class_decl?(name)
|
|
487
496
|
raise new(type_name: type_name, member: member)
|
|
488
497
|
end
|
|
489
498
|
end
|
|
490
499
|
|
|
491
500
|
private
|
|
492
501
|
|
|
502
|
+
def member_name(member)
|
|
503
|
+
case member
|
|
504
|
+
when AST::Members::Include, AST::Members::Extend, AST::Members::Prepend
|
|
505
|
+
member.name
|
|
506
|
+
when AST::Ruby::Members::IncludeMember, AST::Ruby::Members::ExtendMember, AST::Ruby::Members::PrependMember
|
|
507
|
+
member.module_name
|
|
508
|
+
else
|
|
509
|
+
raise "Unknown member type: #{member.class}"
|
|
510
|
+
end
|
|
511
|
+
end
|
|
512
|
+
|
|
493
513
|
def mixin_name
|
|
494
514
|
case member
|
|
495
|
-
when AST::Members::Prepend
|
|
515
|
+
when AST::Members::Prepend, AST::Ruby::Members::PrependMember
|
|
496
516
|
"prepend"
|
|
497
|
-
when AST::Members::Include
|
|
517
|
+
when AST::Members::Include, AST::Ruby::Members::IncludeMember
|
|
498
518
|
"include"
|
|
499
|
-
when AST::Members::Extend
|
|
519
|
+
when AST::Members::Extend, AST::Ruby::Members::ExtendMember
|
|
500
520
|
"extend"
|
|
501
521
|
else
|
|
502
|
-
raise
|
|
522
|
+
raise "Unknown member type: #{member.class}"
|
|
503
523
|
end
|
|
504
524
|
end
|
|
505
525
|
end
|
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,46 @@ module RBS
|
|
|
96
111
|
return
|
|
97
112
|
end
|
|
98
113
|
|
|
99
|
-
|
|
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)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
class_decl = AST::Ruby::Declarations::ClassDecl.new(buffer, class_name, node, super_class)
|
|
100
121
|
insert_declaration(class_decl)
|
|
101
122
|
push_module_nesting(class_decl) do
|
|
102
123
|
visit_child_nodes(node)
|
|
124
|
+
|
|
125
|
+
node.child_nodes.each do |child_node|
|
|
126
|
+
if child_node
|
|
127
|
+
comments.each_enclosed_block(child_node) do |block|
|
|
128
|
+
report_unused_block(block)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
103
132
|
end
|
|
104
133
|
|
|
105
134
|
comments.each_enclosed_block(node) do |block|
|
|
106
|
-
|
|
135
|
+
unused_annotations = [] #: Array[AST::Ruby::CommentBlock::AnnotationSyntaxError | AST::Ruby::Annotations::leading_annotation]
|
|
136
|
+
|
|
137
|
+
block.each_paragraph([]) do |paragraph|
|
|
138
|
+
case paragraph
|
|
139
|
+
when AST::Ruby::Annotations::InstanceVariableAnnotation
|
|
140
|
+
class_decl.members << AST::Ruby::Members::InstanceVariableMember.new(buffer, paragraph)
|
|
141
|
+
when Location
|
|
142
|
+
# Skip
|
|
143
|
+
when AST::Ruby::CommentBlock::AnnotationSyntaxError
|
|
144
|
+
unused_annotations << paragraph
|
|
145
|
+
else
|
|
146
|
+
unused_annotations << paragraph
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
report_unused_annotation(*unused_annotations)
|
|
107
151
|
end
|
|
152
|
+
|
|
153
|
+
class_decl.members.sort_by! { _1.location.start_line }
|
|
108
154
|
end
|
|
109
155
|
|
|
110
156
|
def visit_module_node(node)
|
|
@@ -153,12 +199,12 @@ module RBS
|
|
|
153
199
|
method_type, leading_unuseds, trailing_unused = AST::Ruby::Members::MethodTypeAnnotation.build(leading_block, trailing_block, [])
|
|
154
200
|
report_unused_annotation(trailing_unused, *leading_unuseds)
|
|
155
201
|
|
|
156
|
-
defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type)
|
|
202
|
+
defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type, leading_block)
|
|
157
203
|
current.members << defn
|
|
158
204
|
|
|
159
205
|
# Skip other comments in `def` node
|
|
160
206
|
comments.each_enclosed_block(node) do |block|
|
|
161
|
-
|
|
207
|
+
report_unused_block(block)
|
|
162
208
|
end
|
|
163
209
|
else
|
|
164
210
|
diagnostics << Diagnostic::TopLevelMethodDefinition.new(
|
|
@@ -168,6 +214,261 @@ module RBS
|
|
|
168
214
|
end
|
|
169
215
|
end
|
|
170
216
|
|
|
217
|
+
def visit_call_node(node)
|
|
218
|
+
return unless node.receiver.nil? # Only handle top-level calls like include, extend, prepend, attr_*
|
|
219
|
+
|
|
220
|
+
case node.name
|
|
221
|
+
when :include, :extend, :prepend
|
|
222
|
+
return if skip_node?(node)
|
|
223
|
+
|
|
224
|
+
case current = current_module
|
|
225
|
+
when AST::Ruby::Declarations::ClassDecl, AST::Ruby::Declarations::ModuleDecl
|
|
226
|
+
parse_mixin_call(node)
|
|
227
|
+
end
|
|
228
|
+
when :attr_reader, :attr_writer, :attr_accessor
|
|
229
|
+
return if skip_node?(node)
|
|
230
|
+
|
|
231
|
+
case current = current_module
|
|
232
|
+
when AST::Ruby::Declarations::ClassDecl, AST::Ruby::Declarations::ModuleDecl
|
|
233
|
+
parse_attribute_call(node)
|
|
234
|
+
when nil
|
|
235
|
+
# Top-level attribute definition
|
|
236
|
+
diagnostics << Diagnostic::TopLevelAttributeDefinition.new(
|
|
237
|
+
rbs_location(node.message_loc || node.location),
|
|
238
|
+
"Top-level attribute definition is not supported"
|
|
239
|
+
)
|
|
240
|
+
end
|
|
241
|
+
else
|
|
242
|
+
visit_child_nodes(node)
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def visit_constant_write_node(node)
|
|
247
|
+
return if skip_node?(node)
|
|
248
|
+
|
|
249
|
+
# Parse constant declaration (both top-level and in classes/modules)
|
|
250
|
+
parse_constant_declaration(node)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def visit_constant_path_write_node(node)
|
|
254
|
+
return if skip_node?(node)
|
|
255
|
+
|
|
256
|
+
parse_constant_declaration(node)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def parse_mixin_call(node)
|
|
260
|
+
# Check for multiple arguments
|
|
261
|
+
if node.arguments && node.arguments.arguments.length > 1
|
|
262
|
+
diagnostics << Diagnostic::MixinMultipleArguments.new(
|
|
263
|
+
rbs_location(node.location),
|
|
264
|
+
"Mixing multiple modules with one call is not supported"
|
|
265
|
+
)
|
|
266
|
+
return
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Check for missing arguments
|
|
270
|
+
unless node.arguments && node.arguments.arguments.length == 1
|
|
271
|
+
# This shouldn't happen in valid Ruby code, but handle it gracefully
|
|
272
|
+
return
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
first_arg = node.arguments.arguments.first
|
|
276
|
+
|
|
277
|
+
# Check if the argument is a constant
|
|
278
|
+
unless module_name = constant_as_type_name(first_arg)
|
|
279
|
+
diagnostics << Diagnostic::MixinNonConstantModule.new(
|
|
280
|
+
rbs_location(first_arg.location),
|
|
281
|
+
"Module name must be a constant"
|
|
282
|
+
)
|
|
283
|
+
return
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# Look for type application annotation in trailing comments
|
|
287
|
+
# For single-line calls like "include Bar #[String]", the annotation is trailing
|
|
288
|
+
trailing_block = comments.trailing_block!(node.location)
|
|
289
|
+
annotation = nil
|
|
290
|
+
|
|
291
|
+
if trailing_block
|
|
292
|
+
case trailing_annotation = trailing_block.trailing_annotation([])
|
|
293
|
+
when AST::Ruby::Annotations::TypeApplicationAnnotation
|
|
294
|
+
annotation = trailing_annotation
|
|
295
|
+
else
|
|
296
|
+
report_unused_annotation(trailing_annotation)
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Create the appropriate member based on the method name
|
|
301
|
+
member = case node.name
|
|
302
|
+
when :include
|
|
303
|
+
AST::Ruby::Members::IncludeMember.new(buffer, node, module_name, annotation)
|
|
304
|
+
when :extend
|
|
305
|
+
AST::Ruby::Members::ExtendMember.new(buffer, node, module_name, annotation)
|
|
306
|
+
when :prepend
|
|
307
|
+
AST::Ruby::Members::PrependMember.new(buffer, node, module_name, annotation)
|
|
308
|
+
else
|
|
309
|
+
raise "Unexpected mixin method: #{node.name}"
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
current_module!.members << member
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def parse_attribute_call(node)
|
|
316
|
+
# Get the name nodes (arguments to attr_*)
|
|
317
|
+
unless node.arguments && !node.arguments.arguments.empty?
|
|
318
|
+
return # No arguments, nothing to do
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
name_nodes = [] #: Array[Prism::SymbolNode]
|
|
322
|
+
node.arguments.arguments.each do |arg|
|
|
323
|
+
case arg
|
|
324
|
+
when Prism::SymbolNode
|
|
325
|
+
name_nodes << arg
|
|
326
|
+
else
|
|
327
|
+
# Non-symbol argument, report error
|
|
328
|
+
diagnostics << Diagnostic::AttributeNonSymbolName.new(
|
|
329
|
+
rbs_location(arg.location),
|
|
330
|
+
"Attribute name must be a symbol"
|
|
331
|
+
)
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
return if name_nodes.empty?
|
|
336
|
+
|
|
337
|
+
# Look for leading comment block
|
|
338
|
+
leading_block = comments.leading_block!(node)
|
|
339
|
+
|
|
340
|
+
# Look for trailing type annotation (#: Type)
|
|
341
|
+
trailing_block = comments.trailing_block!(node.location)
|
|
342
|
+
type_annotation = nil
|
|
343
|
+
|
|
344
|
+
if trailing_block
|
|
345
|
+
case annotation = trailing_block.trailing_annotation([])
|
|
346
|
+
when AST::Ruby::Annotations::NodeTypeAssertion
|
|
347
|
+
type_annotation = annotation
|
|
348
|
+
when AST::Ruby::CommentBlock::AnnotationSyntaxError
|
|
349
|
+
diagnostics << Diagnostic::AnnotationSyntaxError.new(
|
|
350
|
+
annotation.location, "Syntax error: " + annotation.error.error_message
|
|
351
|
+
)
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# Report unused leading annotations since @rbs annotations are not used for attributes
|
|
356
|
+
if leading_block
|
|
357
|
+
report_unused_block(leading_block)
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Create the appropriate member type
|
|
361
|
+
member = case node.name
|
|
362
|
+
when :attr_reader
|
|
363
|
+
AST::Ruby::Members::AttrReaderMember.new(buffer, node, name_nodes, leading_block, type_annotation)
|
|
364
|
+
when :attr_writer
|
|
365
|
+
AST::Ruby::Members::AttrWriterMember.new(buffer, node, name_nodes, leading_block, type_annotation)
|
|
366
|
+
when :attr_accessor
|
|
367
|
+
AST::Ruby::Members::AttrAccessorMember.new(buffer, node, name_nodes, leading_block, type_annotation)
|
|
368
|
+
else
|
|
369
|
+
raise "Unexpected attribute method: #{node.name}"
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
current_module!.members << member
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def parse_constant_declaration(node)
|
|
376
|
+
# Create TypeName for the constant
|
|
377
|
+
unless constant_name = constant_as_type_name(node)
|
|
378
|
+
location =
|
|
379
|
+
case node
|
|
380
|
+
when Prism::ConstantWriteNode
|
|
381
|
+
node.name_loc
|
|
382
|
+
when Prism::ConstantPathWriteNode
|
|
383
|
+
node.target.location
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
diagnostics << Diagnostic::NonConstantConstantDeclaration.new(
|
|
387
|
+
rbs_location(location),
|
|
388
|
+
"Constant name must be a constant"
|
|
389
|
+
)
|
|
390
|
+
return
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
# Look for leading comment block
|
|
394
|
+
leading_block = comments.leading_block!(node)
|
|
395
|
+
report_unused_block(leading_block) if leading_block
|
|
396
|
+
|
|
397
|
+
# Look for trailing type annotation (#: Type)
|
|
398
|
+
trailing_block = comments.trailing_block!(node.location)
|
|
399
|
+
type_annotation = nil
|
|
400
|
+
alias_annotation = nil
|
|
401
|
+
|
|
402
|
+
if trailing_block
|
|
403
|
+
case annotation = trailing_block.trailing_annotation([])
|
|
404
|
+
when AST::Ruby::Annotations::NodeTypeAssertion
|
|
405
|
+
type_annotation = annotation
|
|
406
|
+
when AST::Ruby::Annotations::ClassAliasAnnotation, AST::Ruby::Annotations::ModuleAliasAnnotation
|
|
407
|
+
alias_annotation = annotation
|
|
408
|
+
when AST::Ruby::CommentBlock::AnnotationSyntaxError
|
|
409
|
+
diagnostics << Diagnostic::AnnotationSyntaxError.new(
|
|
410
|
+
annotation.location, "Syntax error: " + annotation.error.error_message
|
|
411
|
+
)
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
# Handle class/module alias declarations
|
|
416
|
+
if alias_annotation
|
|
417
|
+
# Try to infer the old name from the right-hand side
|
|
418
|
+
infered_old_name = constant_as_type_name(node.value)
|
|
419
|
+
|
|
420
|
+
# Check if we have either an explicit type name or can infer one
|
|
421
|
+
if alias_annotation.type_name.nil? && infered_old_name.nil?
|
|
422
|
+
message =
|
|
423
|
+
if alias_annotation.is_a?(AST::Ruby::Annotations::ClassAliasAnnotation)
|
|
424
|
+
"Class name is missing in class alias declaration"
|
|
425
|
+
else
|
|
426
|
+
"Module name is missing in module alias declaration"
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
diagnostics << Diagnostic::ClassModuleAliasDeclarationMissingTypeName.new(
|
|
430
|
+
alias_annotation.location,
|
|
431
|
+
message
|
|
432
|
+
)
|
|
433
|
+
return
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
# Create class/module alias declaration
|
|
437
|
+
alias_decl = AST::Ruby::Declarations::ClassModuleAliasDecl.new(
|
|
438
|
+
buffer,
|
|
439
|
+
node,
|
|
440
|
+
constant_name,
|
|
441
|
+
infered_old_name,
|
|
442
|
+
leading_block,
|
|
443
|
+
alias_annotation
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
# Insert the alias declaration appropriately
|
|
447
|
+
|
|
448
|
+
if current_module
|
|
449
|
+
current_module.members << alias_decl
|
|
450
|
+
else
|
|
451
|
+
result.declarations << alias_decl
|
|
452
|
+
end
|
|
453
|
+
else
|
|
454
|
+
# Create regular constant declaration
|
|
455
|
+
constant_decl = AST::Ruby::Declarations::ConstantDecl.new(
|
|
456
|
+
buffer,
|
|
457
|
+
constant_name,
|
|
458
|
+
node,
|
|
459
|
+
leading_block,
|
|
460
|
+
type_annotation
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
# Insert the constant declaration appropriately
|
|
464
|
+
if current_module
|
|
465
|
+
current_module.members << constant_decl
|
|
466
|
+
else
|
|
467
|
+
result.declarations << constant_decl
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
|
|
171
472
|
def insert_declaration(decl)
|
|
172
473
|
if current_module
|
|
173
474
|
current_module.members << decl
|
|
@@ -192,6 +493,8 @@ module RBS
|
|
|
192
493
|
end
|
|
193
494
|
|
|
194
495
|
def report_unused_block(block)
|
|
496
|
+
return unless block.leading?
|
|
497
|
+
|
|
195
498
|
block.each_paragraph([]) do |paragraph|
|
|
196
499
|
case paragraph
|
|
197
500
|
when Location
|
|
@@ -201,6 +504,39 @@ module RBS
|
|
|
201
504
|
end
|
|
202
505
|
end
|
|
203
506
|
end
|
|
507
|
+
|
|
508
|
+
def parse_super_class(super_class_expr, inheritance_operator_loc)
|
|
509
|
+
# Check if the superclass is a constant
|
|
510
|
+
unless super_class_name = constant_as_type_name(super_class_expr)
|
|
511
|
+
diagnostics << Diagnostic::NonConstantSuperClassName.new(
|
|
512
|
+
rbs_location(super_class_expr.location),
|
|
513
|
+
"Super class name must be a constant"
|
|
514
|
+
)
|
|
515
|
+
return nil
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
# Look for type application annotation in trailing comments
|
|
519
|
+
# For example: class StringArray < Array #[String]
|
|
520
|
+
trailing_block = comments.trailing_block!(super_class_expr.location)
|
|
521
|
+
type_annotation = nil
|
|
522
|
+
|
|
523
|
+
if trailing_block
|
|
524
|
+
case annotation = trailing_block.trailing_annotation([])
|
|
525
|
+
when AST::Ruby::Annotations::TypeApplicationAnnotation
|
|
526
|
+
type_annotation = annotation
|
|
527
|
+
else
|
|
528
|
+
report_unused_annotation(annotation)
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
# Create SuperClass object
|
|
533
|
+
AST::Ruby::Declarations::ClassDecl::SuperClass.new(
|
|
534
|
+
rbs_location(super_class_expr.location),
|
|
535
|
+
rbs_location(inheritance_operator_loc),
|
|
536
|
+
super_class_name,
|
|
537
|
+
type_annotation
|
|
538
|
+
)
|
|
539
|
+
end
|
|
204
540
|
end
|
|
205
541
|
end
|
|
206
542
|
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/parser_aux.rb
CHANGED
|
@@ -5,9 +5,9 @@ require_relative "parser/token"
|
|
|
5
5
|
|
|
6
6
|
module RBS
|
|
7
7
|
class Parser
|
|
8
|
-
def self.parse_type(source, range: 0..., variables: [], require_eof: false)
|
|
8
|
+
def self.parse_type(source, range: 0..., variables: [], require_eof: false, void_allowed: true, self_allowed: true)
|
|
9
9
|
buf = buffer(source)
|
|
10
|
-
_parse_type(buf, range.begin || 0, range.end || buf.last_position, variables, require_eof)
|
|
10
|
+
_parse_type(buf, range.begin || 0, range.end || buf.last_position, variables, require_eof, void_allowed, self_allowed)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def self.parse_method_type(source, range: 0..., variables: [], require_eof: false)
|
data/lib/rbs/prototype/rb.rb
CHANGED
|
@@ -372,8 +372,8 @@ module RBS
|
|
|
372
372
|
end
|
|
373
373
|
|
|
374
374
|
value_node = node.children.last
|
|
375
|
-
type = if value_node.nil?
|
|
376
|
-
# Give up type prediction when node is MASGN.
|
|
375
|
+
type = if value_node.nil? || value_node.type == :SELF
|
|
376
|
+
# Give up type prediction when node is MASGN or SELF.
|
|
377
377
|
Types::Bases::Any.new(location: nil)
|
|
378
378
|
else
|
|
379
379
|
literal_to_type(value_node)
|
data/lib/rbs/prototype/rbi.rb
CHANGED
|
@@ -235,6 +235,7 @@ module RBS
|
|
|
235
235
|
variance: variance || :invariant,
|
|
236
236
|
location: nil,
|
|
237
237
|
upper_bound: nil,
|
|
238
|
+
lower_bound: nil,
|
|
238
239
|
default_type: nil
|
|
239
240
|
)
|
|
240
241
|
end
|
|
@@ -332,6 +333,7 @@ module RBS
|
|
|
332
333
|
name: name,
|
|
333
334
|
variance: :invariant,
|
|
334
335
|
upper_bound: nil,
|
|
336
|
+
lower_bound: nil,
|
|
335
337
|
location: nil,
|
|
336
338
|
default_type: nil
|
|
337
339
|
)
|
|
@@ -27,6 +27,10 @@ module RBS
|
|
|
27
27
|
method_definition = @builder.build_singleton(module_name.absolute!).methods[method.name]
|
|
28
28
|
return false unless method_definition
|
|
29
29
|
|
|
30
|
+
return false unless method_definition.defs.any? do |type_def|
|
|
31
|
+
type_def.implemented_in&.relative!.to_s == method.owner.to_s.delete_prefix("#<Class:").delete_suffix(">")
|
|
32
|
+
end
|
|
33
|
+
|
|
30
34
|
method_definition.accessibility == accessibility
|
|
31
35
|
end
|
|
32
36
|
|
|
@@ -36,6 +40,10 @@ module RBS
|
|
|
36
40
|
method_definition = @builder.build_instance(module_name.absolute!).methods[method.name]
|
|
37
41
|
return false unless method_definition
|
|
38
42
|
|
|
43
|
+
return false unless method_definition.defs.any? do |type_def|
|
|
44
|
+
type_def.implemented_in&.relative!.to_s == method.owner.to_s
|
|
45
|
+
end
|
|
46
|
+
|
|
39
47
|
method_definition.accessibility == accessibility
|
|
40
48
|
end
|
|
41
49
|
|
|
@@ -32,7 +32,7 @@ module RBS
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
environment.class_alias_decls.each do |name, entry|
|
|
35
|
-
normalized_entry = environment.
|
|
35
|
+
normalized_entry = environment.module_class_entry(name, normalized: true) or next
|
|
36
36
|
constant = constant_of_module(name, normalized_entry)
|
|
37
37
|
|
|
38
38
|
# Insert class/module aliases into `children_table` and `toplevel` table
|
|
@@ -176,7 +176,7 @@ module RBS
|
|
|
176
176
|
end
|
|
177
177
|
|
|
178
178
|
def constants_from_ancestors(module_name, constants:)
|
|
179
|
-
entry = builder.env.
|
|
179
|
+
entry = builder.env.module_class_entry(module_name, normalized: true) or raise
|
|
180
180
|
|
|
181
181
|
if entry.is_a?(Environment::ClassEntry) || entry.is_a?(Environment::ModuleEntry)
|
|
182
182
|
constants.merge!(table.children(BuiltinNames::Object.name) || raise)
|