rbs 3.4.4 → 3.5.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +7 -0
- data/CHANGELOG.md +0 -26
- data/Gemfile +12 -1
- data/Gemfile.lock +51 -34
- data/README.md +2 -1
- data/Rakefile +2 -2
- data/core/enumerator.rbs +1 -1
- data/core/gc.rbs +272 -150
- data/core/integer.rbs +4 -3
- data/core/io/wait.rbs +4 -4
- data/core/io.rbs +10 -3
- data/core/kernel.rbs +8 -7
- data/core/module.rbs +17 -4
- data/core/range.rbs +2 -2
- data/core/regexp.rbs +101 -90
- data/core/ruby_vm.rbs +103 -103
- data/core/string.rbs +3 -3
- data/core/symbol.rbs +2 -1
- data/core/thread.rbs +1 -1
- data/core/time.rbs +24 -4
- data/docs/architecture.md +110 -0
- data/docs/syntax.md +5 -1
- data/ext/rbs_extension/constants.c +2 -0
- data/ext/rbs_extension/constants.h +1 -0
- data/ext/rbs_extension/location.c +79 -70
- data/ext/rbs_extension/location.h +23 -5
- data/ext/rbs_extension/parser.c +82 -24
- data/ext/rbs_extension/parserstate.c +4 -0
- data/ext/rbs_extension/ruby_objs.c +13 -3
- data/ext/rbs_extension/ruby_objs.h +1 -0
- data/lib/rbs/collection/config.rb +1 -1
- data/lib/rbs/collection/sources/git.rb +1 -6
- data/lib/rbs/definition_builder/method_builder.rb +1 -1
- data/lib/rbs/definition_builder.rb +8 -8
- data/lib/rbs/diff.rb +1 -1
- data/lib/rbs/environment_loader.rb +2 -1
- data/lib/rbs/errors.rb +0 -14
- data/lib/rbs/parser_aux.rb +0 -5
- data/lib/rbs/prototype/helpers.rb +22 -12
- data/lib/rbs/prototype/rb.rb +38 -4
- data/lib/rbs/prototype/rbi.rb +30 -20
- data/lib/rbs/test/errors.rb +19 -14
- data/lib/rbs/test/tester.rb +1 -1
- data/lib/rbs/test/type_check.rb +95 -16
- data/lib/rbs/types.rb +112 -13
- data/lib/rbs/unit_test/spy.rb +1 -1
- data/lib/rbs/version.rb +1 -1
- data/rbs.gemspec +1 -1
- data/sig/environment_loader.rbs +1 -1
- data/sig/errors.rbs +1 -1
- data/sig/method_types.rbs +3 -3
- data/sig/prototype/helpers.rbs +4 -0
- data/sig/prototype/rbi.rbs +2 -0
- data/sig/types.rbs +54 -4
- data/sig/variance_calculator.rbs +2 -2
- data/stdlib/csv/0/csv.rbs +4 -1
- data/stdlib/fileutils/0/fileutils.rbs +1 -1
- data/stdlib/net-http/0/net-http.rbs +29 -27
- data/stdlib/socket/0/socket.rbs +2 -2
- data/stdlib/timeout/0/timeout.rbs +6 -0
- data/stdlib/uri/0/generic.rbs +2 -2
- data/stdlib/uri/0/http.rbs +2 -2
- metadata +3 -6
- data/lib/rbs/parser_compat/lexer_error.rb +0 -6
- data/lib/rbs/parser_compat/located_value.rb +0 -7
- data/lib/rbs/parser_compat/semantics_error.rb +0 -6
- data/lib/rbs/parser_compat/syntax_error.rb +0 -6
data/lib/rbs/prototype/rb.rb
CHANGED
@@ -5,7 +5,7 @@ module RBS
|
|
5
5
|
class RB
|
6
6
|
include Helpers
|
7
7
|
|
8
|
-
Context
|
8
|
+
class Context < Struct.new(:module_function, :singleton, :namespace, :in_def, keyword_init: true)
|
9
9
|
# @implements Context
|
10
10
|
|
11
11
|
def self.initial(namespace: Namespace.root)
|
@@ -461,6 +461,8 @@ module RBS
|
|
461
461
|
|
462
462
|
def literal_to_symbol(node)
|
463
463
|
case node.type
|
464
|
+
when :SYM
|
465
|
+
node.children[0]
|
464
466
|
when :LIT
|
465
467
|
node.children[0] if node.children[0].is_a?(Symbol)
|
466
468
|
when :STR
|
@@ -495,7 +497,7 @@ module RBS
|
|
495
497
|
end
|
496
498
|
|
497
499
|
if rest
|
498
|
-
rest_name = rest == :* ? nil : rest #
|
500
|
+
rest_name = rest == :* ? nil : rest # `def f(...)` syntax has `*` name
|
499
501
|
fun = fun.update(rest_positionals: Types::Function::Param.new(name: rest_name, type: untyped))
|
500
502
|
end
|
501
503
|
|
@@ -518,7 +520,9 @@ module RBS
|
|
518
520
|
end
|
519
521
|
|
520
522
|
if kwrest && kwrest.children.any?
|
521
|
-
|
523
|
+
kwrest_name = kwrest.children[0] #: Symbol?
|
524
|
+
kwrest_name = nil if kwrest_name == :** # `def f(...)` syntax has `**` name
|
525
|
+
fun = fun.update(rest_keywords: Types::Function::Param.new(name: kwrest_name, type: untyped))
|
522
526
|
end
|
523
527
|
|
524
528
|
fun
|
@@ -574,9 +578,16 @@ module RBS
|
|
574
578
|
end
|
575
579
|
when :DSTR, :XSTR
|
576
580
|
BuiltinNames::String.instance_type
|
581
|
+
when :SYM
|
582
|
+
lit = node.children[0]
|
583
|
+
if lit.to_s.ascii_only?
|
584
|
+
Types::Literal.new(literal: lit, location: nil)
|
585
|
+
else
|
586
|
+
BuiltinNames::Symbol.instance_type
|
587
|
+
end
|
577
588
|
when :DSYM
|
578
589
|
BuiltinNames::Symbol.instance_type
|
579
|
-
when :DREGX
|
590
|
+
when :DREGX, :REGX
|
580
591
|
BuiltinNames::Regexp.instance_type
|
581
592
|
when :TRUE
|
582
593
|
Types::Literal.new(literal: true, location: nil)
|
@@ -584,6 +595,14 @@ module RBS
|
|
584
595
|
Types::Literal.new(literal: false, location: nil)
|
585
596
|
when :NIL
|
586
597
|
Types::Bases::Nil.new(location: nil)
|
598
|
+
when :INTEGER
|
599
|
+
Types::Literal.new(literal: node.children[0], location: nil)
|
600
|
+
when :FLOAT
|
601
|
+
BuiltinNames::Float.instance_type
|
602
|
+
when :RATIONAL, :IMAGINARY
|
603
|
+
lit = node.children[0]
|
604
|
+
type_name = TypeName.new(name: lit.class.name.to_sym, namespace: Namespace.root)
|
605
|
+
Types::ClassInstance.new(name: type_name, args: [], location: nil)
|
587
606
|
when :LIT
|
588
607
|
lit = node.children[0]
|
589
608
|
case lit
|
@@ -595,6 +614,11 @@ module RBS
|
|
595
614
|
end
|
596
615
|
when Integer
|
597
616
|
Types::Literal.new(literal: lit, location: nil)
|
617
|
+
when String
|
618
|
+
# For Ruby <=3.3 which generates `LIT` node for string literals inside Hash literal.
|
619
|
+
# "a" => STR node
|
620
|
+
# { "a" => nil } => LIT node
|
621
|
+
Types::Literal.new(literal: lit, location: nil)
|
598
622
|
else
|
599
623
|
type_name = TypeName.new(name: lit.class.name.to_sym, namespace: Namespace.root)
|
600
624
|
Types::ClassInstance.new(name: type_name, args: [], location: nil)
|
@@ -686,6 +710,14 @@ module RBS
|
|
686
710
|
|
687
711
|
def param_type(node, default: Types::Bases::Any.new(location: nil))
|
688
712
|
case node.type
|
713
|
+
when :INTEGER
|
714
|
+
BuiltinNames::Integer.instance_type
|
715
|
+
when :FLOAT
|
716
|
+
BuiltinNames::Float.instance_type
|
717
|
+
when :RATIONAL
|
718
|
+
Types::ClassInstance.new(name: TypeName("::Rational"), args: [], location: nil)
|
719
|
+
when :IMAGINARY
|
720
|
+
Types::ClassInstance.new(name: TypeName("::Complex"), args: [], location: nil)
|
689
721
|
when :LIT
|
690
722
|
case node.children[0]
|
691
723
|
when Symbol
|
@@ -697,6 +729,8 @@ module RBS
|
|
697
729
|
else
|
698
730
|
default
|
699
731
|
end
|
732
|
+
when :SYM
|
733
|
+
BuiltinNames::Symbol.instance_type
|
700
734
|
when :STR, :DSTR
|
701
735
|
BuiltinNames::String.instance_type
|
702
736
|
when :NIL
|
data/lib/rbs/prototype/rbi.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
module RBS
|
4
4
|
module Prototype
|
5
5
|
class RBI
|
6
|
+
include Helpers
|
7
|
+
|
6
8
|
attr_reader :decls
|
7
9
|
attr_reader :modules
|
8
10
|
attr_reader :last_sig
|
@@ -218,11 +220,11 @@ module RBS
|
|
218
220
|
if (send = node.children.last) && send.type == :FCALL && send.children[0] == :type_member
|
219
221
|
unless each_arg(send.children[1]).any? {|node|
|
220
222
|
node.type == :HASH &&
|
221
|
-
each_arg(node.children[0]).each_slice(2).any? {|a, _| a
|
223
|
+
each_arg(node.children[0]).each_slice(2).any? {|a, _| symbol_literal_node?(a) == :fixed }
|
222
224
|
}
|
223
225
|
# @type var variance: AST::TypeParam::variance?
|
224
|
-
if (a0 = each_arg(send.children[1]).to_a[0]) &&
|
225
|
-
variance = case
|
226
|
+
if (a0 = each_arg(send.children[1]).to_a[0]) && (v = symbol_literal_node?(a0))
|
227
|
+
variance = case v
|
226
228
|
when :out
|
227
229
|
:covariant
|
228
230
|
when :in
|
@@ -315,14 +317,18 @@ module RBS
|
|
315
317
|
Types::Function::Param.new(name: name, type: type)
|
316
318
|
end
|
317
319
|
|
318
|
-
|
320
|
+
if method_type.type.is_a?(RBS::Types::Function)
|
321
|
+
method_type.update(type: method_type.type.update(required_positionals: required_positionals))
|
322
|
+
else
|
323
|
+
method_type
|
324
|
+
end
|
319
325
|
end
|
320
326
|
when :type_parameters
|
321
327
|
type_params = []
|
322
328
|
|
323
329
|
each_arg args do |node|
|
324
|
-
if
|
325
|
-
type_params <<
|
330
|
+
if name = symbol_literal_node?(node)
|
331
|
+
type_params << name
|
326
332
|
end
|
327
333
|
end
|
328
334
|
|
@@ -444,18 +450,22 @@ module RBS
|
|
444
450
|
end
|
445
451
|
end
|
446
452
|
|
447
|
-
method_type.
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
453
|
+
if method_type.type.is_a?(Types::Function)
|
454
|
+
method_type.update(
|
455
|
+
type: method_type.type.update(
|
456
|
+
required_positionals: required_positionals,
|
457
|
+
optional_positionals: optional_positionals,
|
458
|
+
rest_positionals: rest_positionals,
|
459
|
+
trailing_positionals: trailing_positionals,
|
460
|
+
required_keywords: required_keywords,
|
461
|
+
optional_keywords: optional_keywords,
|
462
|
+
rest_keywords: rest_keywords
|
463
|
+
),
|
464
|
+
block: method_block
|
465
|
+
)
|
466
|
+
else
|
467
|
+
method_type
|
468
|
+
end
|
459
469
|
end
|
460
470
|
|
461
471
|
def type_of(type_node, variables:)
|
@@ -613,8 +623,8 @@ module RBS
|
|
613
623
|
each_arg(node.children[0]).each_slice(2) do |var, type|
|
614
624
|
var or raise
|
615
625
|
|
616
|
-
if
|
617
|
-
hash[
|
626
|
+
if (name = symbol_literal_node?(var)) && type
|
627
|
+
hash[name] = type
|
618
628
|
end
|
619
629
|
end
|
620
630
|
|
data/lib/rbs/test/errors.rb
CHANGED
@@ -40,32 +40,37 @@ module RBS
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
def self.
|
44
|
-
|
45
|
-
inspect_(error.klass).sub(/\A#<Class:(.*)>\z/, '\1')
|
43
|
+
def self.method_tag(error)
|
44
|
+
if error.klass.singleton_class?
|
45
|
+
name = inspect_(error.klass).sub(/\A#<Class:(.*)>\z/, '\1')
|
46
|
+
method_name = ".#{error.method_name}"
|
46
47
|
else
|
47
|
-
error.klass.name
|
48
|
+
name = error.klass.name
|
49
|
+
method_name = "##{error.method_name}"
|
48
50
|
end
|
49
|
-
|
51
|
+
"[#{name}#{method_name}]"
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.to_string(error)
|
50
55
|
case error
|
51
56
|
when ArgumentTypeError
|
52
|
-
"
|
57
|
+
"#{method_tag(error)} ArgumentTypeError: expected #{format_param error.param} but given `#{inspect_(error.value)}`"
|
53
58
|
when BlockArgumentTypeError
|
54
|
-
"
|
59
|
+
"#{method_tag(error)} BlockArgumentTypeError: expected #{format_param error.param} but given `#{inspect_(error.value)}`"
|
55
60
|
when ArgumentError
|
56
|
-
"
|
61
|
+
"#{method_tag(error)} ArgumentError: expected method type #{error.method_type}"
|
57
62
|
when BlockArgumentError
|
58
|
-
"
|
63
|
+
"#{method_tag(error)} BlockArgumentError: expected method type #{error.method_type}"
|
59
64
|
when ReturnTypeError
|
60
|
-
"
|
65
|
+
"#{method_tag(error)} ReturnTypeError: expected `#{error.type}` but returns `#{inspect_(error.value)}`"
|
61
66
|
when BlockReturnTypeError
|
62
|
-
"
|
67
|
+
"#{method_tag(error)} BlockReturnTypeError: expected `#{error.type}` but returns `#{inspect_(error.value)}`"
|
63
68
|
when UnexpectedBlockError
|
64
|
-
"
|
69
|
+
"#{method_tag(error)} UnexpectedBlockError: unexpected block is given for `#{error.method_type}`"
|
65
70
|
when MissingBlockError
|
66
|
-
"
|
71
|
+
"#{method_tag(error)} MissingBlockError: required block is missing for `#{error.method_type}`"
|
67
72
|
when UnresolvedOverloadingError
|
68
|
-
"
|
73
|
+
"#{method_tag(error)} UnresolvedOverloadingError: couldn't find a suitable overloading"
|
69
74
|
else
|
70
75
|
raise "Unexpected error: #{inspect_(error)}"
|
71
76
|
end
|
data/lib/rbs/test/tester.rb
CHANGED
@@ -149,7 +149,7 @@ module RBS
|
|
149
149
|
method = definition.methods[method_name]
|
150
150
|
if method
|
151
151
|
RBS.logger.debug { "Type checking `#{self_class}#{format_method_name(method_name)}`..."}
|
152
|
-
errors = check.overloaded_call(method,
|
152
|
+
errors = check.overloaded_call(method, method_name, trace, errors: [])
|
153
153
|
|
154
154
|
if errors.empty?
|
155
155
|
RBS.logger.debug { "No type error detected 👏" }
|
data/lib/rbs/test/type_check.rb
CHANGED
@@ -35,22 +35,24 @@ module RBS
|
|
35
35
|
if es.size == 1
|
36
36
|
errors.push(*es[0])
|
37
37
|
else
|
38
|
+
error = Errors::UnresolvedOverloadingError.new(
|
39
|
+
klass: self_class,
|
40
|
+
method_name: method_name,
|
41
|
+
method_types: method.method_types
|
42
|
+
)
|
38
43
|
RBS.logger.warn do
|
39
|
-
|
44
|
+
tag = Errors.method_tag(error)
|
45
|
+
message = +"#{tag} UnresolvedOverloadingError "
|
40
46
|
message << method.method_types.zip(es).map do |method_type, es|
|
41
47
|
msg = +"method_type=`#{method_type}`"
|
42
48
|
details = es.map do |e|
|
43
|
-
"\"#{Errors.to_string(e).sub("
|
49
|
+
"\"#{Errors.to_string(e).sub("#{tag} ", "") }\""
|
44
50
|
end.join(', ')
|
45
51
|
msg << " details=[#{details}]"
|
46
52
|
end.join(', ')
|
47
53
|
message
|
48
54
|
end
|
49
|
-
errors <<
|
50
|
-
klass: self_class,
|
51
|
-
method_name: method_name,
|
52
|
-
method_types: method.method_types
|
53
|
-
)
|
55
|
+
errors << error
|
54
56
|
end
|
55
57
|
|
56
58
|
errors
|
@@ -281,19 +283,22 @@ module RBS
|
|
281
283
|
end
|
282
284
|
end
|
283
285
|
|
284
|
-
each_sample(values).all? do |v|
|
286
|
+
value_check = values.empty? || each_sample(values).all? do |v|
|
285
287
|
if v.size == 1
|
286
288
|
# Only one block argument.
|
287
289
|
value(v[0], type.args[0]) || value(v, type.args[0])
|
288
290
|
else
|
289
291
|
value(v, type.args[0])
|
290
292
|
end
|
291
|
-
end
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
293
|
+
end
|
294
|
+
|
295
|
+
return_check = if ret.equal?(self)
|
296
|
+
type.args[1].is_a?(Types::Bases::Bottom)
|
297
|
+
else
|
298
|
+
value(ret, type.args[1])
|
299
|
+
end
|
300
|
+
|
301
|
+
value_check && return_check
|
297
302
|
end
|
298
303
|
else
|
299
304
|
Test.call(val, IS_AP, klass)
|
@@ -308,8 +313,15 @@ module RBS
|
|
308
313
|
val.is_a?(singleton_class)
|
309
314
|
when Types::Interface
|
310
315
|
if (definition = builder.build_interface(type.name.absolute!))
|
311
|
-
definition.methods.
|
312
|
-
Test.call(val, RESPOND_TOP, method_name)
|
316
|
+
definition.methods.each.all? do |method_name, method|
|
317
|
+
next false unless Test.call(val, RESPOND_TOP, method_name)
|
318
|
+
|
319
|
+
meth = Test.call(val, METHOD, method_name)
|
320
|
+
method.defs.all? do |type_def|
|
321
|
+
type_def.member.overloads.all? do |overload|
|
322
|
+
callable_argument?(meth.parameters, overload.method_type)
|
323
|
+
end
|
324
|
+
end
|
313
325
|
end
|
314
326
|
end
|
315
327
|
when Types::Variable
|
@@ -336,6 +348,73 @@ module RBS
|
|
336
348
|
false
|
337
349
|
end
|
338
350
|
end
|
351
|
+
|
352
|
+
private
|
353
|
+
|
354
|
+
def callable_argument?(parameters, method_type)
|
355
|
+
fun = method_type.type
|
356
|
+
take_has_rest = !!parameters.find { |(op, _)| op == :rest }
|
357
|
+
|
358
|
+
fun.required_positionals.each do
|
359
|
+
op, _ = parameters.first
|
360
|
+
return false if op.nil? || op == :keyreq || op == :key || op == :keyrest
|
361
|
+
parameters.shift if op == :req || op == :opt
|
362
|
+
end
|
363
|
+
|
364
|
+
fun.optional_positionals.each do
|
365
|
+
op, _ = parameters.first
|
366
|
+
return false if op.nil? || op == :req || op == :keyreq || op == :key || op == :keyrest
|
367
|
+
parameters.shift if op == :opt
|
368
|
+
end
|
369
|
+
|
370
|
+
if fun.rest_positionals
|
371
|
+
op, _ = parameters.shift
|
372
|
+
return false if op.nil? || op != :rest
|
373
|
+
end
|
374
|
+
|
375
|
+
fun.trailing_positionals.each do
|
376
|
+
op, _ = parameters.first
|
377
|
+
return false if !take_has_rest && (op.nil? || op == :keyreq || op == :key || op == :keyrest)
|
378
|
+
index = parameters.find_index { |(op, _)| op == :req }
|
379
|
+
parameters.delete_at(index) if index
|
380
|
+
end
|
381
|
+
|
382
|
+
if fun.has_keyword?
|
383
|
+
return false if !take_has_rest && parameters.empty?
|
384
|
+
|
385
|
+
fun.required_keywords.each do |name, _|
|
386
|
+
return false if !take_has_rest && parameters.empty?
|
387
|
+
index = parameters.find_index { |(op, n)| (op == :keyreq || op == :key) && n == name }
|
388
|
+
parameters.delete_at(index) if index
|
389
|
+
end
|
390
|
+
|
391
|
+
if !fun.optional_keywords.empty?
|
392
|
+
fun.optional_keywords.each do |name, _|
|
393
|
+
return false if !take_has_rest && parameters.empty?
|
394
|
+
index = parameters.find_index { |(op, n)| op == :key && n == name }
|
395
|
+
parameters.delete_at(index) if index
|
396
|
+
end
|
397
|
+
op, _ = parameters.first
|
398
|
+
return false if op == :req
|
399
|
+
end
|
400
|
+
|
401
|
+
if fun.rest_keywords
|
402
|
+
op, _ = parameters.first
|
403
|
+
return false if (!take_has_rest && op.nil?)
|
404
|
+
# f(a) allows (Integer, a: Integer)
|
405
|
+
return false if op == :req && fun.required_keywords.empty?
|
406
|
+
end
|
407
|
+
|
408
|
+
op, _ = parameters.first
|
409
|
+
return true if (op == :req || op == :opt) && parameters.length == 1
|
410
|
+
end
|
411
|
+
|
412
|
+
# rest required arguments
|
413
|
+
op, _ = parameters.first
|
414
|
+
return false if op == :req || op == :keyreq
|
415
|
+
|
416
|
+
true
|
417
|
+
end
|
339
418
|
end
|
340
419
|
end
|
341
420
|
end
|
data/lib/rbs/types.rb
CHANGED
@@ -515,22 +515,34 @@ module RBS
|
|
515
515
|
end
|
516
516
|
|
517
517
|
class Record
|
518
|
-
attr_reader :fields
|
518
|
+
attr_reader :all_fields, :fields, :optional_fields
|
519
519
|
attr_reader :location
|
520
520
|
|
521
|
-
def initialize(fields
|
522
|
-
|
521
|
+
def initialize(all_fields: nil, fields: nil, location:)
|
522
|
+
case
|
523
|
+
when fields && all_fields.nil?
|
524
|
+
@all_fields = fields.map { |k, v| [k, [v, true]] }.to_h
|
525
|
+
@fields = fields
|
526
|
+
@optional_fields = {}
|
527
|
+
when all_fields && fields.nil?
|
528
|
+
@all_fields = all_fields
|
529
|
+
@fields = all_fields.filter_map { |k, (v, required)| [k, v] if required }.to_h
|
530
|
+
@optional_fields = all_fields.filter_map { |k, (v, required)| [k, v] unless required }.to_h
|
531
|
+
else
|
532
|
+
raise ArgumentError, "only one of `:fields` or `:all_fields` is requireds"
|
533
|
+
end
|
534
|
+
|
523
535
|
@location = location
|
524
536
|
end
|
525
537
|
|
526
538
|
def ==(other)
|
527
|
-
other.is_a?(Record) && other.fields == fields
|
539
|
+
other.is_a?(Record) && other.fields == fields && other.optional_fields == optional_fields
|
528
540
|
end
|
529
541
|
|
530
542
|
alias eql? ==
|
531
543
|
|
532
544
|
def hash
|
533
|
-
self.class.hash ^
|
545
|
+
self.class.hash ^ all_fields.hash
|
534
546
|
end
|
535
547
|
|
536
548
|
def free_variables(set = Set.new)
|
@@ -538,27 +550,35 @@ module RBS
|
|
538
550
|
fields.each_value do |type|
|
539
551
|
type.free_variables set
|
540
552
|
end
|
553
|
+
optional_fields.each_value do |type|
|
554
|
+
type.free_variables set
|
555
|
+
end
|
541
556
|
end
|
542
557
|
end
|
543
558
|
|
544
559
|
def to_json(state = _ = nil)
|
545
|
-
{ class: :record, fields: fields, location: location }.to_json(state)
|
560
|
+
{ class: :record, fields: fields, optional_fields: optional_fields, location: location }.to_json(state)
|
546
561
|
end
|
547
562
|
|
548
563
|
def sub(s)
|
549
|
-
self.class.new(
|
550
|
-
|
564
|
+
self.class.new(
|
565
|
+
all_fields: all_fields.transform_values {|ty, required| [ty.sub(s), required] },
|
566
|
+
location: location
|
567
|
+
)
|
551
568
|
end
|
552
569
|
|
553
570
|
def to_s(level = 0)
|
554
|
-
return "{ }" if
|
571
|
+
return "{ }" if all_fields.empty?
|
555
572
|
|
556
|
-
fields =
|
557
|
-
if key.is_a?(Symbol) && key.match?(/\A[A-Za-z_][A-Za-z_0-9]*\z/)
|
573
|
+
fields = all_fields.map do |key, (type, required)|
|
574
|
+
field = if key.is_a?(Symbol) && key.match?(/\A[A-Za-z_][A-Za-z_0-9]*\z/)
|
558
575
|
"#{key}: #{type}"
|
559
576
|
else
|
560
577
|
"#{key.inspect} => #{type}"
|
561
578
|
end
|
579
|
+
|
580
|
+
field = "?#{field}" unless required
|
581
|
+
field
|
562
582
|
end
|
563
583
|
"{ #{fields.join(", ")} }"
|
564
584
|
end
|
@@ -566,6 +586,7 @@ module RBS
|
|
566
586
|
def each_type(&block)
|
567
587
|
if block
|
568
588
|
fields.each_value(&block)
|
589
|
+
optional_fields.each_value(&block)
|
569
590
|
else
|
570
591
|
enum_for :each_type
|
571
592
|
end
|
@@ -573,7 +594,7 @@ module RBS
|
|
573
594
|
|
574
595
|
def map_type_name(&block)
|
575
596
|
Record.new(
|
576
|
-
|
597
|
+
all_fields: all_fields.transform_values {|ty, required| [ty.map_type_name(&block), required] },
|
577
598
|
location: location
|
578
599
|
)
|
579
600
|
end
|
@@ -581,7 +602,7 @@ module RBS
|
|
581
602
|
def map_type(&block)
|
582
603
|
if block
|
583
604
|
Record.new(
|
584
|
-
|
605
|
+
all_fields: all_fields.transform_values {|type, required| [yield(type), required] },
|
585
606
|
location: location
|
586
607
|
)
|
587
608
|
else
|
@@ -1181,6 +1202,84 @@ module RBS
|
|
1181
1202
|
end
|
1182
1203
|
end
|
1183
1204
|
|
1205
|
+
class UntypedFunction
|
1206
|
+
attr_reader :return_type
|
1207
|
+
|
1208
|
+
def initialize(return_type:)
|
1209
|
+
@return_type = return_type
|
1210
|
+
end
|
1211
|
+
|
1212
|
+
def free_variables(acc = Set.new)
|
1213
|
+
return_type.free_variables(acc)
|
1214
|
+
end
|
1215
|
+
|
1216
|
+
def map_type(&block)
|
1217
|
+
if block
|
1218
|
+
update(return_type: yield(return_type))
|
1219
|
+
else
|
1220
|
+
enum_for :map_type
|
1221
|
+
end
|
1222
|
+
end
|
1223
|
+
|
1224
|
+
def each_type(&block)
|
1225
|
+
if block
|
1226
|
+
yield return_type
|
1227
|
+
else
|
1228
|
+
enum_for :each_type
|
1229
|
+
end
|
1230
|
+
end
|
1231
|
+
|
1232
|
+
def each_param(&block)
|
1233
|
+
if block
|
1234
|
+
# noop
|
1235
|
+
else
|
1236
|
+
enum_for :each_param
|
1237
|
+
end
|
1238
|
+
end
|
1239
|
+
|
1240
|
+
def to_json(state = _ = nil)
|
1241
|
+
{
|
1242
|
+
return_type: return_type
|
1243
|
+
}.to_json(state)
|
1244
|
+
end
|
1245
|
+
|
1246
|
+
def sub(subst)
|
1247
|
+
map_type { _1.sub(subst) }
|
1248
|
+
end
|
1249
|
+
|
1250
|
+
def with_return_type(ty)
|
1251
|
+
update(return_type: ty)
|
1252
|
+
end
|
1253
|
+
|
1254
|
+
def update(return_type: self.return_type)
|
1255
|
+
UntypedFunction.new(return_type: return_type)
|
1256
|
+
end
|
1257
|
+
|
1258
|
+
def empty?
|
1259
|
+
true
|
1260
|
+
end
|
1261
|
+
|
1262
|
+
def has_self_type?
|
1263
|
+
return_type.has_self_type?
|
1264
|
+
end
|
1265
|
+
|
1266
|
+
def has_classish_type?
|
1267
|
+
return_type.has_classish_type?
|
1268
|
+
end
|
1269
|
+
|
1270
|
+
def with_nonreturn_void
|
1271
|
+
false
|
1272
|
+
end
|
1273
|
+
|
1274
|
+
def param_to_s
|
1275
|
+
"?"
|
1276
|
+
end
|
1277
|
+
|
1278
|
+
def return_to_s
|
1279
|
+
return_type.to_s(1)
|
1280
|
+
end
|
1281
|
+
end
|
1282
|
+
|
1184
1283
|
class Block
|
1185
1284
|
attr_reader :type
|
1186
1285
|
attr_reader :required
|
data/lib/rbs/unit_test/spy.rb
CHANGED
data/lib/rbs/version.rb
CHANGED
data/rbs.gemspec
CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
|
|
28
28
|
# Specify which files should be added to the gem when it is released.
|
29
29
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
30
30
|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
31
|
-
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|bin|steep)/}) }
|
31
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|bin|steep|benchmark)/}) }
|
32
32
|
end
|
33
33
|
spec.extensions = %w{ext/rbs_extension/extconf.rb}
|
34
34
|
|
data/sig/environment_loader.rbs
CHANGED
data/sig/errors.rbs
CHANGED
data/sig/method_types.rbs
CHANGED
@@ -14,11 +14,11 @@ module RBS
|
|
14
14
|
type loc = def_loc | attr_loc
|
15
15
|
|
16
16
|
attr_reader type_params: Array[AST::TypeParam]
|
17
|
-
attr_reader type: Types::
|
17
|
+
attr_reader type: Types::function
|
18
18
|
attr_reader block: Types::Block?
|
19
19
|
attr_reader location: loc?
|
20
20
|
|
21
|
-
def initialize: (type_params: Array[AST::TypeParam], type: Types::
|
21
|
+
def initialize: (type_params: Array[AST::TypeParam], type: Types::function, block: Types::Block?, location: loc?) -> void
|
22
22
|
|
23
23
|
def ==: (untyped other) -> bool
|
24
24
|
|
@@ -29,7 +29,7 @@ module RBS
|
|
29
29
|
#
|
30
30
|
def sub: (Substitution) -> MethodType
|
31
31
|
|
32
|
-
def update: (?type_params: Array[AST::TypeParam], ?type: Types::
|
32
|
+
def update: (?type_params: Array[AST::TypeParam], ?type: Types::function, ?block: Types::Block?, ?location: loc?) -> MethodType
|
33
33
|
|
34
34
|
def free_variables: (?Set[Symbol] set) -> Set[Symbol]
|
35
35
|
|