rbs 3.4.4 → 3.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +12 -4
- data/.github/workflows/dependabot.yml +26 -0
- data/.github/workflows/ruby.yml +14 -1
- data/CHANGELOG.md +87 -1
- data/README.md +5 -3
- data/Rakefile +20 -3
- data/Steepfile +1 -1
- data/core/enumerator.rbs +1 -1
- data/core/float.rbs +2 -1
- data/core/gc.rbs +272 -150
- data/core/integer.rbs +6 -4
- 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/proc.rbs +1 -1
- data/core/range.rbs +2 -2
- data/core/rational.rbs +2 -1
- data/core/regexp.rbs +101 -90
- data/core/ruby_vm.rbs +107 -103
- data/core/rubygems/rubygems.rbs +1 -1
- data/core/set.rbs +13 -7
- 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/gem.md +0 -1
- 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/lexer.c +1338 -1341
- data/ext/rbs_extension/lexer.h +2 -0
- data/ext/rbs_extension/lexer.re +2 -3
- data/ext/rbs_extension/lexstate.c +5 -1
- data/ext/rbs_extension/location.c +80 -70
- data/ext/rbs_extension/location.h +25 -5
- data/ext/rbs_extension/parser.c +149 -43
- data/ext/rbs_extension/parserstate.c +12 -1
- data/ext/rbs_extension/parserstate.h +9 -0
- data/ext/rbs_extension/ruby_objs.c +13 -3
- data/ext/rbs_extension/ruby_objs.h +1 -0
- data/lib/rbs/cli/validate.rb +2 -2
- data/lib/rbs/cli.rb +4 -6
- 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/location_aux.rb +6 -1
- data/lib/rbs/parser/lex_result.rb +15 -0
- data/lib/rbs/parser/token.rb +23 -0
- data/lib/rbs/parser_aux.rb +12 -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 +7 -2
- data/sig/environment_loader.rbs +1 -1
- data/sig/errors.rbs +1 -1
- data/sig/manifest.yaml +0 -1
- data/sig/method_types.rbs +3 -3
- data/sig/parser.rbs +28 -0
- 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
- data/stdlib/uri/0/mailto.rbs +84 -0
- metadata +7 -9
- data/Gemfile +0 -30
- data/Gemfile.lock +0 -117
- 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
@@ -630,12 +630,12 @@ module RBS
|
|
630
630
|
end
|
631
631
|
|
632
632
|
# @type var accessibility: RBS::Definition::accessibility
|
633
|
-
accessibility =
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
633
|
+
accessibility =
|
634
|
+
if original.instance? && [:initialize, :initialize_copy, :initialize_clone, :initialize_dup, :respond_to_missing?].include?(method.name)
|
635
|
+
:private
|
636
|
+
else
|
637
|
+
method.accessibility
|
638
|
+
end
|
639
639
|
# Skip setting up `super_method` if `implemented_in` is `nil`, that means the type doesn't have implementation.
|
640
640
|
# This typically happens if the type is an interface.
|
641
641
|
if implemented_in
|
@@ -669,7 +669,7 @@ module RBS
|
|
669
669
|
]
|
670
670
|
),
|
671
671
|
block: nil,
|
672
|
-
location:
|
672
|
+
location: original.location
|
673
673
|
)
|
674
674
|
else
|
675
675
|
# getter
|
@@ -677,7 +677,7 @@ module RBS
|
|
677
677
|
type_params: [],
|
678
678
|
type: Types::Function.empty(attr_type),
|
679
679
|
block: nil,
|
680
|
-
location:
|
680
|
+
location: original.location
|
681
681
|
)
|
682
682
|
end
|
683
683
|
|
data/lib/rbs/diff.rb
CHANGED
@@ -83,7 +83,7 @@ module RBS
|
|
83
83
|
manifest_pathname = dir_pathname / 'manifest.yaml'
|
84
84
|
if manifest_pathname.exist?
|
85
85
|
manifest = YAML.safe_load(manifest_pathname.read)
|
86
|
-
if manifest['dependencies']
|
86
|
+
if manifest && manifest['dependencies']
|
87
87
|
manifest['dependencies'].each do |dependency|
|
88
88
|
loader.add(library: dependency['name'], version: nil)
|
89
89
|
end
|
data/lib/rbs/errors.rb
CHANGED
@@ -62,20 +62,6 @@ module RBS
|
|
62
62
|
|
63
63
|
super "#{Location.to_string location}: Syntax error: #{error_message}, token=`#{location.source}` (#{token_type})"
|
64
64
|
end
|
65
|
-
|
66
|
-
def error_value
|
67
|
-
RBS.print_warning {
|
68
|
-
"#{self.class.name}#error_value is deprecated and will be deleted in RBS 2.0. Consider using `location.source` instead."
|
69
|
-
}
|
70
|
-
location.source
|
71
|
-
end
|
72
|
-
|
73
|
-
def token_str
|
74
|
-
RBS.print_warning {
|
75
|
-
"#{self.class.name}#token_str is deprecated and will be deleted in RBS 2.0. Consider using `token_type` instead."
|
76
|
-
}
|
77
|
-
token_type
|
78
|
-
end
|
79
65
|
end
|
80
66
|
|
81
67
|
class InvalidTypeApplicationError < DefinitionError
|
data/lib/rbs/location_aux.rb
CHANGED
@@ -5,7 +5,12 @@ module RBS
|
|
5
5
|
def inspect
|
6
6
|
rks = each_required_key.to_a
|
7
7
|
ops = each_optional_key.to_a.map {|x| "?#{x}" }
|
8
|
-
|
8
|
+
src = if source.length <= 1
|
9
|
+
source.inspect
|
10
|
+
else
|
11
|
+
source.each_line.first&.chomp&.inspect
|
12
|
+
end
|
13
|
+
"#<#{self.class}:#{self.__id__} buffer=#{buffer.name}, start=#{start_line}:#{start_column}, pos=#{start_pos}...#{end_pos}, children=#{(rks + ops).join(",")} source=#{src}>"
|
9
14
|
end
|
10
15
|
|
11
16
|
def self.new(buffer_ = nil, start_pos_ = nil, end_pos_ = nil, buffer: nil, start_pos: nil, end_pos: nil)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RBS
|
4
|
+
class Parser
|
5
|
+
class Token
|
6
|
+
attr_reader :type
|
7
|
+
attr_reader :location
|
8
|
+
|
9
|
+
def initialize(type:, location:)
|
10
|
+
@type = type
|
11
|
+
@location = location
|
12
|
+
end
|
13
|
+
|
14
|
+
def value
|
15
|
+
@location.source
|
16
|
+
end
|
17
|
+
|
18
|
+
def comment?
|
19
|
+
@type == :tCOMMENT || @type == :tLINECOMMENT
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/rbs/parser_aux.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "parser/lex_result"
|
4
|
+
require_relative "parser/token"
|
5
|
+
|
3
6
|
module RBS
|
4
7
|
class Parser
|
5
8
|
def self.parse_type(source, range: 0..., variables: [], require_eof: false)
|
@@ -19,6 +22,15 @@ module RBS
|
|
19
22
|
[buf, dirs, decls]
|
20
23
|
end
|
21
24
|
|
25
|
+
def self.lex(source)
|
26
|
+
buf = buffer(source)
|
27
|
+
list = _lex(buf, buf.last_position)
|
28
|
+
value = list.map do |type, location|
|
29
|
+
Token.new(type: type, location: location)
|
30
|
+
end
|
31
|
+
LexResult.new(buffer: buf, value: value)
|
32
|
+
end
|
33
|
+
|
22
34
|
def self.buffer(source)
|
23
35
|
case source
|
24
36
|
when String
|
@@ -28,11 +40,6 @@ module RBS
|
|
28
40
|
end
|
29
41
|
end
|
30
42
|
|
31
|
-
autoload :SyntaxError, "rbs/parser_compat/syntax_error"
|
32
|
-
autoload :SemanticsError, "rbs/parser_compat/semantics_error"
|
33
|
-
autoload :LexerError, "rbs/parser_compat/lexer_error"
|
34
|
-
autoload :LocatedValue, "rbs/parser_compat/located_value"
|
35
|
-
|
36
43
|
KEYWORDS = %w(
|
37
44
|
bool
|
38
45
|
bot
|
@@ -37,13 +37,9 @@ module RBS
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
method_block = Types::Block.new(
|
41
|
-
required: required,
|
42
|
-
type: Types::Function.empty(untyped),
|
43
|
-
self_type: nil
|
44
|
-
)
|
45
|
-
|
46
40
|
if yields
|
41
|
+
function = Types::Function.empty(untyped)
|
42
|
+
|
47
43
|
yields.each do |yield_node|
|
48
44
|
array_content = yield_node.children[0]&.children&.compact || []
|
49
45
|
|
@@ -54,9 +50,9 @@ module RBS
|
|
54
50
|
[array_content, nil]
|
55
51
|
end
|
56
52
|
|
57
|
-
if (diff = positionals.size -
|
53
|
+
if (diff = positionals.size - function.required_positionals.size) > 0
|
58
54
|
diff.times do
|
59
|
-
|
55
|
+
function.required_positionals << Types::Function::Param.new(
|
60
56
|
type: untyped,
|
61
57
|
name: nil
|
62
58
|
)
|
@@ -67,7 +63,7 @@ module RBS
|
|
67
63
|
keywords.children[0].children.each_slice(2) do |key_node, value_node|
|
68
64
|
if key_node
|
69
65
|
key = key_node.children[0]
|
70
|
-
|
66
|
+
function.required_keywords[key] ||=
|
71
67
|
Types::Function::Param.new(
|
72
68
|
type: untyped,
|
73
69
|
name: nil
|
@@ -76,10 +72,13 @@ module RBS
|
|
76
72
|
end
|
77
73
|
end
|
78
74
|
end
|
75
|
+
else
|
76
|
+
function = Types::UntypedFunction.new(return_type: untyped)
|
79
77
|
end
|
80
|
-
end
|
81
78
|
|
82
|
-
|
79
|
+
|
80
|
+
Types::Block.new(required: required, type: function, self_type: nil)
|
81
|
+
end
|
83
82
|
end
|
84
83
|
|
85
84
|
def each_child(node, &block)
|
@@ -109,7 +108,7 @@ module RBS
|
|
109
108
|
def keyword_hash?(node)
|
110
109
|
if node && node.type == :HASH
|
111
110
|
node.children[0].children.compact.each_slice(2).all? {|key, _|
|
112
|
-
|
111
|
+
symbol_literal_node?(key)
|
113
112
|
}
|
114
113
|
else
|
115
114
|
false
|
@@ -122,6 +121,17 @@ module RBS
|
|
122
121
|
args_node&.children || [0, nil, nil, nil, 0, nil, nil, nil, nil, nil]
|
123
122
|
end
|
124
123
|
|
124
|
+
def symbol_literal_node?(node)
|
125
|
+
case node.type
|
126
|
+
when :LIT
|
127
|
+
if node.children[0].is_a?(Symbol)
|
128
|
+
node.children[0]
|
129
|
+
end
|
130
|
+
when :SYM
|
131
|
+
node.children[0]
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
125
135
|
def untyped
|
126
136
|
@untyped ||= Types::Bases::Any.new(location: nil)
|
127
137
|
end
|
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
|