rbs 4.0.0.dev.5 → 4.0.1.dev.1
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/workflows/c-check.yml +8 -4
- data/.github/workflows/comments.yml +3 -1
- data/.github/workflows/dependabot.yml +1 -1
- data/.github/workflows/ruby.yml +10 -0
- data/.github/workflows/rust.yml +95 -0
- data/CHANGELOG.md +323 -0
- data/Rakefile +12 -29
- data/Steepfile +1 -0
- data/config.yml +393 -37
- data/core/array.rbs +218 -188
- data/core/basic_object.rbs +9 -8
- data/core/class.rbs +6 -5
- data/core/comparable.rbs +45 -31
- data/core/complex.rbs +52 -40
- data/core/dir.rbs +57 -45
- data/core/encoding.rbs +5 -5
- data/core/enumerable.rbs +96 -91
- data/core/enumerator.rbs +4 -3
- data/core/errno.rbs +3 -2
- data/core/errors.rbs +31 -29
- data/core/exception.rbs +12 -12
- data/core/fiber.rbs +36 -36
- data/core/file.rbs +186 -113
- data/core/file_test.rbs +2 -2
- data/core/float.rbs +41 -32
- data/core/gc.rbs +78 -70
- data/core/hash.rbs +70 -60
- data/core/integer.rbs +32 -28
- data/core/io/buffer.rbs +36 -36
- data/core/io/wait.rbs +7 -7
- data/core/io.rbs +120 -135
- data/core/kernel.rbs +189 -139
- data/core/marshal.rbs +3 -3
- data/core/match_data.rbs +14 -12
- data/core/math.rbs +69 -67
- data/core/method.rbs +6 -6
- data/core/module.rbs +146 -85
- data/core/nil_class.rbs +4 -3
- data/core/numeric.rbs +35 -32
- data/core/object.rbs +6 -8
- data/core/object_space.rbs +11 -10
- data/core/pathname.rbs +131 -81
- data/core/proc.rbs +65 -33
- data/core/process.rbs +219 -201
- data/core/ractor.rbs +15 -11
- data/core/random.rbs +4 -3
- data/core/range.rbs +52 -47
- data/core/rational.rbs +5 -5
- data/core/rbs/unnamed/argf.rbs +58 -51
- data/core/rbs/unnamed/env_class.rbs +18 -13
- data/core/rbs/unnamed/main_class.rbs +123 -0
- data/core/rbs/unnamed/random.rbs +7 -5
- data/core/regexp.rbs +236 -197
- data/core/ruby.rbs +1 -1
- data/core/ruby_vm.rbs +32 -30
- data/core/rubygems/config_file.rbs +5 -5
- data/core/rubygems/errors.rbs +1 -1
- data/core/rubygems/requirement.rbs +5 -5
- data/core/rubygems/rubygems.rbs +5 -3
- data/core/set.rbs +17 -16
- data/core/signal.rbs +2 -2
- data/core/string.rbs +311 -292
- data/core/struct.rbs +26 -25
- data/core/symbol.rbs +25 -24
- data/core/thread.rbs +40 -34
- data/core/time.rbs +47 -42
- data/core/trace_point.rbs +34 -31
- data/core/true_class.rbs +2 -2
- data/core/unbound_method.rbs +10 -10
- data/core/warning.rbs +7 -7
- data/docs/collection.md +1 -1
- data/docs/config.md +171 -0
- data/docs/inline.md +110 -4
- data/docs/syntax.md +13 -12
- data/ext/rbs_extension/ast_translation.c +489 -135
- data/ext/rbs_extension/class_constants.c +8 -0
- data/ext/rbs_extension/class_constants.h +4 -0
- data/ext/rbs_extension/legacy_location.c +28 -51
- data/ext/rbs_extension/legacy_location.h +37 -0
- data/ext/rbs_extension/main.c +12 -20
- data/include/rbs/ast.h +423 -195
- data/include/rbs/lexer.h +2 -2
- data/include/rbs/location.h +25 -44
- data/include/rbs/parser.h +2 -2
- data/include/rbs/util/rbs_constant_pool.h +0 -3
- data/include/rbs.h +8 -0
- data/lib/rbs/ast/ruby/annotations.rb +157 -4
- data/lib/rbs/ast/ruby/members.rb +374 -22
- data/lib/rbs/cli/validate.rb +5 -60
- data/lib/rbs/collection/config/lockfile_generator.rb +6 -2
- data/lib/rbs/definition_builder.rb +60 -27
- data/lib/rbs/errors.rb +0 -11
- data/lib/rbs/inline_parser.rb +1 -1
- data/lib/rbs/parser_aux.rb +20 -7
- data/lib/rbs/prototype/helpers.rb +57 -0
- data/lib/rbs/prototype/rb.rb +1 -26
- data/lib/rbs/prototype/rbi.rb +1 -20
- data/lib/rbs/test/type_check.rb +3 -0
- data/lib/rbs/types.rb +62 -52
- data/lib/rbs/unit_test/type_assertions.rb +35 -8
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs.rb +0 -1
- data/rbs.gemspec +1 -1
- data/rust/.gitignore +1 -0
- data/rust/Cargo.lock +378 -0
- data/rust/Cargo.toml +7 -0
- data/rust/ruby-rbs/Cargo.toml +22 -0
- data/rust/ruby-rbs/build.rs +764 -0
- data/rust/ruby-rbs/examples/locations.rs +60 -0
- data/rust/ruby-rbs/src/lib.rs +1 -0
- data/rust/ruby-rbs/src/node/mod.rs +742 -0
- data/rust/ruby-rbs/tests/sanity.rs +47 -0
- data/rust/ruby-rbs/vendor/rbs/config.yml +1 -0
- data/rust/ruby-rbs-sys/Cargo.toml +23 -0
- data/rust/ruby-rbs-sys/build.rs +204 -0
- data/rust/ruby-rbs-sys/src/lib.rs +50 -0
- data/rust/ruby-rbs-sys/vendor/rbs/include +1 -0
- data/rust/ruby-rbs-sys/vendor/rbs/src +1 -0
- data/rust/ruby-rbs-sys/wrapper.h +1 -0
- data/sig/ast/ruby/annotations.rbs +191 -4
- data/sig/ast/ruby/members.rbs +21 -1
- data/sig/cli/validate.rbs +1 -6
- data/sig/definition_builder.rbs +2 -0
- data/sig/errors.rbs +0 -8
- data/sig/method_types.rbs +1 -1
- data/sig/parser.rbs +17 -13
- data/sig/prototype/helpers.rbs +2 -0
- data/sig/types.rbs +10 -11
- data/sig/unit_test/spy.rbs +0 -8
- data/sig/unit_test/type_assertions.rbs +11 -0
- data/src/ast.c +339 -161
- data/src/lexstate.c +1 -1
- data/src/location.c +7 -47
- data/src/parser.c +674 -480
- data/src/util/rbs_constant_pool.c +0 -4
- data/stdlib/bigdecimal/0/big_decimal.rbs +16 -16
- data/stdlib/cgi-escape/0/escape.rbs +4 -4
- data/stdlib/coverage/0/coverage.rbs +4 -3
- data/stdlib/date/0/date.rbs +33 -28
- data/stdlib/date/0/date_time.rbs +24 -23
- data/stdlib/did_you_mean/0/did_you_mean.rbs +17 -16
- data/stdlib/erb/0/erb.rbs +64 -53
- data/stdlib/etc/0/etc.rbs +55 -50
- data/stdlib/fileutils/0/fileutils.rbs +138 -125
- data/stdlib/forwardable/0/forwardable.rbs +10 -10
- data/stdlib/io-console/0/io-console.rbs +2 -2
- data/stdlib/json/0/json.rbs +135 -108
- data/stdlib/monitor/0/monitor.rbs +3 -3
- data/stdlib/net-http/0/net-http.rbs +159 -134
- data/stdlib/objspace/0/objspace.rbs +8 -7
- data/stdlib/open-uri/0/open-uri.rbs +8 -8
- data/stdlib/open3/0/open3.rbs +36 -35
- data/stdlib/openssl/0/openssl.rbs +144 -129
- data/stdlib/optparse/0/optparse.rbs +18 -14
- data/stdlib/pathname/0/pathname.rbs +2 -2
- 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 +61 -8
- data/stdlib/psych/0/store.rbs +2 -4
- data/stdlib/pty/0/pty.rbs +9 -6
- data/stdlib/random-formatter/0/random-formatter.rbs +2 -2
- data/stdlib/ripper/0/ripper.rbs +20 -17
- data/stdlib/securerandom/0/securerandom.rbs +1 -1
- data/stdlib/shellwords/0/shellwords.rbs +2 -2
- 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 +10 -9
- data/stdlib/socket/0/tcp_server.rbs +1 -1
- data/stdlib/socket/0/tcp_socket.rbs +1 -1
- data/stdlib/socket/0/udp_socket.rbs +1 -1
- data/stdlib/socket/0/unix_server.rbs +1 -1
- data/stdlib/stringio/0/stringio.rbs +55 -54
- data/stdlib/strscan/0/string_scanner.rbs +46 -44
- data/stdlib/tempfile/0/tempfile.rbs +24 -20
- data/stdlib/time/0/time.rbs +7 -5
- data/stdlib/tsort/0/tsort.rbs +7 -6
- data/stdlib/uri/0/common.rbs +26 -18
- data/stdlib/uri/0/file.rbs +2 -2
- data/stdlib/uri/0/generic.rbs +2 -2
- 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 +6 -5
- data/stdlib/zlib/0/deflate.rbs +4 -3
- data/stdlib/zlib/0/gzip_reader.rbs +4 -4
- 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
- metadata +23 -5
- data/.github/workflows/valgrind.yml +0 -42
|
@@ -398,6 +398,19 @@ module RBS
|
|
|
398
398
|
.update(type_params: class_params + method_type.type_params)
|
|
399
399
|
end
|
|
400
400
|
|
|
401
|
+
method_type = method_type.map_type do |type|
|
|
402
|
+
case type
|
|
403
|
+
when Types::Bases::Self
|
|
404
|
+
Types::ClassInstance.new(
|
|
405
|
+
name: type_name,
|
|
406
|
+
args: entry.type_params.map {|param| Types::Variable.new(name: param.name, location: param.location) },
|
|
407
|
+
location: nil
|
|
408
|
+
)
|
|
409
|
+
else
|
|
410
|
+
type
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
|
|
401
414
|
method_type = method_type.update(
|
|
402
415
|
type: method_type.type.with_return_type(
|
|
403
416
|
Types::ClassInstance.new(
|
|
@@ -695,12 +708,14 @@ module RBS
|
|
|
695
708
|
)
|
|
696
709
|
end
|
|
697
710
|
|
|
711
|
+
accessibility = special_accessibility(original.instance?, original.new_name) || original_method.accessibility
|
|
712
|
+
|
|
698
713
|
method_definition = Definition::Method.new(
|
|
699
714
|
super_method: existing_method,
|
|
700
715
|
defs: original_method.defs.map do |defn|
|
|
701
716
|
defn.update(defined_in: defined_in, implemented_in: implemented_in)
|
|
702
717
|
end,
|
|
703
|
-
accessibility:
|
|
718
|
+
accessibility: accessibility,
|
|
704
719
|
alias_of: original_method,
|
|
705
720
|
alias_member: original
|
|
706
721
|
)
|
|
@@ -727,13 +742,9 @@ module RBS
|
|
|
727
742
|
end
|
|
728
743
|
end
|
|
729
744
|
|
|
730
|
-
#
|
|
731
|
-
accessibility =
|
|
732
|
-
|
|
733
|
-
:private
|
|
734
|
-
else
|
|
735
|
-
method.accessibility
|
|
736
|
-
end
|
|
745
|
+
# Respect the visibility of the original method definition.
|
|
746
|
+
accessibility = original.visibility || special_accessibility(original.instance?, method.name) || method.accessibility
|
|
747
|
+
|
|
737
748
|
# Skip setting up `super_method` if `implemented_in` is `nil`, that means the type doesn't have implementation.
|
|
738
749
|
# This typically happens if the type is an interface.
|
|
739
750
|
if implemented_in
|
|
@@ -786,6 +797,9 @@ module RBS
|
|
|
786
797
|
super_method = existing_method
|
|
787
798
|
end
|
|
788
799
|
|
|
800
|
+
# Respect the visibility of the original method definition.
|
|
801
|
+
accessibility = original.visibility || special_accessibility(original.kind == :instance, method.name) || method.accessibility
|
|
802
|
+
|
|
789
803
|
method_definition = Definition::Method.new(
|
|
790
804
|
super_method: super_method,
|
|
791
805
|
defs: [
|
|
@@ -796,7 +810,7 @@ module RBS
|
|
|
796
810
|
implemented_in: implemented_in
|
|
797
811
|
)
|
|
798
812
|
],
|
|
799
|
-
accessibility:
|
|
813
|
+
accessibility: accessibility,
|
|
800
814
|
alias_of: nil,
|
|
801
815
|
alias_member: nil
|
|
802
816
|
)
|
|
@@ -864,27 +878,40 @@ module RBS
|
|
|
864
878
|
)
|
|
865
879
|
end
|
|
866
880
|
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
881
|
+
if original.method_type.empty? && existing_method
|
|
882
|
+
# Unannotated method with a parent definition → inherit from the parent, like @rbs ...
|
|
883
|
+
method_definition = Definition::Method.new(
|
|
884
|
+
super_method: existing_method,
|
|
885
|
+
defs: existing_method.defs.map { |defn| defn.update(implemented_in: implemented_in) },
|
|
886
|
+
accessibility: :public,
|
|
887
|
+
alias_of: existing_method.alias_of,
|
|
888
|
+
alias_member: nil
|
|
889
|
+
)
|
|
890
|
+
|
|
891
|
+
method_definition.annotations.replace(existing_method.annotations)
|
|
892
|
+
else
|
|
893
|
+
defs = original.overloads.map do |overload|
|
|
894
|
+
Definition::Method::TypeDef.new(
|
|
895
|
+
type: subst.empty? ? overload.method_type : overload.method_type.sub(subst),
|
|
896
|
+
member: original,
|
|
897
|
+
defined_in: defined_in,
|
|
898
|
+
implemented_in: implemented_in
|
|
899
|
+
).tap do |type_def|
|
|
900
|
+
# Keep the original annotations given to overloads.
|
|
901
|
+
type_def.overload_annotations.replace(overload.annotations)
|
|
902
|
+
end
|
|
876
903
|
end
|
|
877
|
-
end
|
|
878
904
|
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
905
|
+
method_definition = Definition::Method.new(
|
|
906
|
+
super_method: existing_method,
|
|
907
|
+
defs: defs,
|
|
908
|
+
accessibility: :public,
|
|
909
|
+
alias_of: nil,
|
|
910
|
+
alias_member: nil
|
|
911
|
+
)
|
|
886
912
|
|
|
887
|
-
|
|
913
|
+
method_definition.annotations.replace([])
|
|
914
|
+
end
|
|
888
915
|
|
|
889
916
|
when nil
|
|
890
917
|
# Overloading method definition only
|
|
@@ -943,6 +970,12 @@ module RBS
|
|
|
943
970
|
methods[method.name] = method_definition
|
|
944
971
|
end
|
|
945
972
|
|
|
973
|
+
def special_accessibility(is_instance, method_name)
|
|
974
|
+
if is_instance && [:initialize, :initialize_copy, :initialize_clone, :initialize_dup, :respond_to_missing?].include?(method_name)
|
|
975
|
+
:private
|
|
976
|
+
end
|
|
977
|
+
end
|
|
978
|
+
|
|
946
979
|
def try_cache(type_name, cache:)
|
|
947
980
|
cache[type_name] ||= yield
|
|
948
981
|
end
|
data/lib/rbs/errors.rb
CHANGED
|
@@ -611,17 +611,6 @@ module RBS
|
|
|
611
611
|
end
|
|
612
612
|
end
|
|
613
613
|
|
|
614
|
-
class WillSyntaxError < DefinitionError
|
|
615
|
-
include DetailedMessageable
|
|
616
|
-
|
|
617
|
-
attr_reader :location
|
|
618
|
-
|
|
619
|
-
def initialize(message, location:)
|
|
620
|
-
super "#{Location.to_string(location)}: #{message}"
|
|
621
|
-
@location = location
|
|
622
|
-
end
|
|
623
|
-
end
|
|
624
|
-
|
|
625
614
|
class TypeParamDefaultReferenceError < DefinitionError
|
|
626
615
|
include DetailedMessageable
|
|
627
616
|
|
data/lib/rbs/inline_parser.rb
CHANGED
|
@@ -196,7 +196,7 @@ module RBS
|
|
|
196
196
|
trailing_block = comments.trailing_block!(end_loc)
|
|
197
197
|
end
|
|
198
198
|
|
|
199
|
-
method_type, leading_unuseds, trailing_unused = AST::Ruby::Members::MethodTypeAnnotation.build(leading_block, trailing_block, [])
|
|
199
|
+
method_type, leading_unuseds, trailing_unused = AST::Ruby::Members::MethodTypeAnnotation.build(leading_block, trailing_block, [], node)
|
|
200
200
|
report_unused_annotation(trailing_unused, *leading_unuseds)
|
|
201
201
|
|
|
202
202
|
defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type, leading_block)
|
data/lib/rbs/parser_aux.rb
CHANGED
|
@@ -5,14 +5,16 @@ 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, void_allowed: true, self_allowed: true)
|
|
8
|
+
def self.parse_type(source, range: nil, byte_range: 0..., variables: [], require_eof: false, void_allowed: true, self_allowed: true, classish_allowed: true)
|
|
9
9
|
buf = buffer(source)
|
|
10
|
-
|
|
10
|
+
byte_range = byte_range(range, buf.content) if range
|
|
11
|
+
_parse_type(buf, byte_range.begin || 0, byte_range.end || buf.content.bytesize, variables, require_eof, void_allowed, self_allowed, classish_allowed)
|
|
11
12
|
end
|
|
12
13
|
|
|
13
|
-
def self.parse_method_type(source, range: 0..., variables: [], require_eof: false)
|
|
14
|
+
def self.parse_method_type(source, range: nil, byte_range: 0..., variables: [], require_eof: false)
|
|
14
15
|
buf = buffer(source)
|
|
15
|
-
|
|
16
|
+
byte_range = byte_range(range, buf.content) if range
|
|
17
|
+
_parse_method_type(buf, byte_range.begin || 0, byte_range.end || buf.content.bytesize, variables, require_eof)
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
def self.parse_signature(source)
|
|
@@ -25,7 +27,8 @@ module RBS
|
|
|
25
27
|
else
|
|
26
28
|
0
|
|
27
29
|
end
|
|
28
|
-
|
|
30
|
+
content = buf.content
|
|
31
|
+
dirs, decls = _parse_signature(buf, start_pos, content.bytesize)
|
|
29
32
|
|
|
30
33
|
if resolved
|
|
31
34
|
dirs = dirs.dup if dirs.frozen?
|
|
@@ -37,7 +40,7 @@ module RBS
|
|
|
37
40
|
|
|
38
41
|
def self.parse_type_params(source, module_type_params: true)
|
|
39
42
|
buf = buffer(source)
|
|
40
|
-
_parse_type_params(buf, 0, buf.
|
|
43
|
+
_parse_type_params(buf, 0, buf.content.bytesize, module_type_params)
|
|
41
44
|
end
|
|
42
45
|
|
|
43
46
|
def self.magic_comment(buf)
|
|
@@ -66,7 +69,7 @@ module RBS
|
|
|
66
69
|
|
|
67
70
|
def self.lex(source)
|
|
68
71
|
buf = buffer(source)
|
|
69
|
-
list = _lex(buf, buf.
|
|
72
|
+
list = _lex(buf, buf.content.bytesize)
|
|
70
73
|
value = list.map do |type, location|
|
|
71
74
|
Token.new(type: type, location: location)
|
|
72
75
|
end
|
|
@@ -125,5 +128,15 @@ module RBS
|
|
|
125
128
|
buf = buffer(source)
|
|
126
129
|
_parse_inline_trailing_annotation(buf, range.begin || 0, range.end || buf.last_position, variables)
|
|
127
130
|
end
|
|
131
|
+
|
|
132
|
+
def self.byte_range(char_range, content)
|
|
133
|
+
start_offset = char_range.begin
|
|
134
|
+
end_offset = char_range.end
|
|
135
|
+
|
|
136
|
+
start_prefix = content[0, start_offset] or raise if start_offset
|
|
137
|
+
end_prefix = content[0, end_offset] or raise if end_offset
|
|
138
|
+
|
|
139
|
+
start_prefix&.bytesize...end_prefix&.bytesize
|
|
140
|
+
end
|
|
128
141
|
end
|
|
129
142
|
end
|
|
@@ -5,6 +5,63 @@ module RBS
|
|
|
5
5
|
module Helpers
|
|
6
6
|
private
|
|
7
7
|
|
|
8
|
+
# Prism can't parse Ruby 3.2 code
|
|
9
|
+
if RUBY_VERSION >= "3.3"
|
|
10
|
+
def parse_comments(string, include_trailing:)
|
|
11
|
+
Prism.parse_comments(string, version: "current").yield_self do |prism_comments| # steep:ignore UnexpectedKeywordArgument
|
|
12
|
+
prism_comments.each_with_object({}) do |comment, hash| #$ Hash[Integer, AST::Comment]
|
|
13
|
+
# Skip EmbDoc comments
|
|
14
|
+
next unless comment.is_a?(Prism::InlineComment)
|
|
15
|
+
# skip like `module Foo # :nodoc:`
|
|
16
|
+
next if comment.trailing? && !include_trailing
|
|
17
|
+
|
|
18
|
+
line = comment.location.start_line
|
|
19
|
+
body = "#{comment.location.slice}\n"
|
|
20
|
+
body = body[2..-1] or raise
|
|
21
|
+
body = "\n" if body.empty?
|
|
22
|
+
|
|
23
|
+
comment = AST::Comment.new(string: body, location: nil)
|
|
24
|
+
if prev_comment = hash.delete(line - 1)
|
|
25
|
+
hash[line] = AST::Comment.new(string: prev_comment.string + comment.string,
|
|
26
|
+
location: nil)
|
|
27
|
+
else
|
|
28
|
+
hash[line] = comment
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
else
|
|
34
|
+
require "ripper"
|
|
35
|
+
def parse_comments(string, include_trailing:)
|
|
36
|
+
Ripper.lex(string).yield_self do |tokens|
|
|
37
|
+
code_lines = {} #: Hash[Integer, bool]
|
|
38
|
+
tokens.each.with_object({}) do |token, hash| #$ Hash[Integer, AST::Comment]
|
|
39
|
+
case token[1]
|
|
40
|
+
when :on_sp, :on_ignored_nl
|
|
41
|
+
# skip
|
|
42
|
+
when :on_comment
|
|
43
|
+
line = token[0][0]
|
|
44
|
+
# skip like `module Foo # :nodoc:`
|
|
45
|
+
next if code_lines[line] && !include_trailing
|
|
46
|
+
body = token[2][2..-1] or raise
|
|
47
|
+
|
|
48
|
+
body = "\n" if body.empty?
|
|
49
|
+
|
|
50
|
+
comment = AST::Comment.new(string: body, location: nil)
|
|
51
|
+
if prev_comment = hash.delete(line - 1)
|
|
52
|
+
hash[line] = AST::Comment.new(string: prev_comment.string + comment.string,
|
|
53
|
+
location: nil)
|
|
54
|
+
else
|
|
55
|
+
hash[line] = comment
|
|
56
|
+
end
|
|
57
|
+
else
|
|
58
|
+
code_lines[token[0][0]] = true
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
8
65
|
def block_from_body(node)
|
|
9
66
|
_, args_node, body_node = node.children
|
|
10
67
|
_pre_num, _pre_init, _opt, _first_post, _post_num, _post_init, _rest, _kw, _kwrest, block_var = args_from_node(args_node)
|
data/lib/rbs/prototype/rb.rb
CHANGED
|
@@ -74,32 +74,7 @@ module RBS
|
|
|
74
74
|
|
|
75
75
|
def parse(string)
|
|
76
76
|
# @type var comments: Hash[Integer, AST::Comment]
|
|
77
|
-
comments =
|
|
78
|
-
code_lines = {} #: Hash[Integer, bool]
|
|
79
|
-
tokens.each.with_object({}) do |token, hash| #$ Hash[Integer, AST::Comment]
|
|
80
|
-
case token[1]
|
|
81
|
-
when :on_sp, :on_ignored_nl
|
|
82
|
-
# skip
|
|
83
|
-
when :on_comment
|
|
84
|
-
line = token[0][0]
|
|
85
|
-
# skip like `module Foo # :nodoc:`
|
|
86
|
-
next if code_lines[line]
|
|
87
|
-
body = token[2][2..-1] or raise
|
|
88
|
-
|
|
89
|
-
body = "\n" if body.empty?
|
|
90
|
-
|
|
91
|
-
comment = AST::Comment.new(string: body, location: nil)
|
|
92
|
-
if prev_comment = hash.delete(line - 1)
|
|
93
|
-
hash[line] = AST::Comment.new(string: prev_comment.string + comment.string,
|
|
94
|
-
location: nil)
|
|
95
|
-
else
|
|
96
|
-
hash[line] = comment
|
|
97
|
-
end
|
|
98
|
-
else
|
|
99
|
-
code_lines[token[0][0]] = true
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
77
|
+
comments = parse_comments(string, include_trailing: false)
|
|
103
78
|
|
|
104
79
|
process RubyVM::AbstractSyntaxTree.parse(string), decls: source_decls, comments: comments, context: Context.initial
|
|
105
80
|
end
|
data/lib/rbs/prototype/rbi.rb
CHANGED
|
@@ -16,26 +16,7 @@ module RBS
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def parse(string)
|
|
19
|
-
comments =
|
|
20
|
-
tokens.each.with_object({}) do |token, hash| #$ Hash[Integer, AST::Comment]
|
|
21
|
-
if token[1] == :on_comment
|
|
22
|
-
line = token[0][0]
|
|
23
|
-
body = token[2][2..-1] or raise
|
|
24
|
-
|
|
25
|
-
body = "\n" if body.empty?
|
|
26
|
-
|
|
27
|
-
comment = AST::Comment.new(string: body, location: nil)
|
|
28
|
-
if (prev_comment = hash.delete(line - 1))
|
|
29
|
-
hash[line] = AST::Comment.new(
|
|
30
|
-
string: prev_comment.string + comment.string,
|
|
31
|
-
location: nil
|
|
32
|
-
)
|
|
33
|
-
else
|
|
34
|
-
hash[line] = comment
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
19
|
+
comments = parse_comments(string, include_trailing: true)
|
|
39
20
|
process RubyVM::AbstractSyntaxTree.parse(string), comments: comments
|
|
40
21
|
end
|
|
41
22
|
|
data/lib/rbs/test/type_check.rb
CHANGED
|
@@ -264,6 +264,9 @@ module RBS
|
|
|
264
264
|
klass = get_class(type.name) or return false
|
|
265
265
|
if params = builder.env.normalized_module_class_entry(type.name.absolute!)&.type_params
|
|
266
266
|
args = AST::TypeParam.normalize_args(params, type.args)
|
|
267
|
+
if args.size != params.size
|
|
268
|
+
return false
|
|
269
|
+
end
|
|
267
270
|
unless args == type.args
|
|
268
271
|
type = Types::ClassInstance.new(name: type.name, args: args, location: type.location)
|
|
269
272
|
end
|
data/lib/rbs/types.rb
CHANGED
|
@@ -199,58 +199,6 @@ module RBS
|
|
|
199
199
|
end
|
|
200
200
|
end
|
|
201
201
|
|
|
202
|
-
class ClassSingleton
|
|
203
|
-
attr_reader :name
|
|
204
|
-
attr_reader :location
|
|
205
|
-
|
|
206
|
-
def initialize(name:, location:)
|
|
207
|
-
@name = name
|
|
208
|
-
@location = location
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
def ==(other)
|
|
212
|
-
other.is_a?(ClassSingleton) && other.name == name
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
alias eql? ==
|
|
216
|
-
|
|
217
|
-
def hash
|
|
218
|
-
self.class.hash ^ name.hash
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
include NoFreeVariables
|
|
222
|
-
include NoSubst
|
|
223
|
-
|
|
224
|
-
def to_json(state = nil)
|
|
225
|
-
{ class: :class_singleton, name: name, location: location }.to_json(state)
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
def to_s(level = 0)
|
|
229
|
-
"singleton(#{name})"
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
include EmptyEachType
|
|
233
|
-
|
|
234
|
-
def map_type_name(&)
|
|
235
|
-
ClassSingleton.new(
|
|
236
|
-
name: yield(name, location, self),
|
|
237
|
-
location: location
|
|
238
|
-
)
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
def has_self_type?
|
|
242
|
-
false
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
def has_classish_type?
|
|
246
|
-
false
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
def with_nonreturn_void?
|
|
250
|
-
false
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
|
|
254
202
|
module Application
|
|
255
203
|
attr_reader :name
|
|
256
204
|
attr_reader :args
|
|
@@ -309,6 +257,68 @@ module RBS
|
|
|
309
257
|
end
|
|
310
258
|
end
|
|
311
259
|
|
|
260
|
+
class ClassSingleton
|
|
261
|
+
attr_reader :location
|
|
262
|
+
|
|
263
|
+
include Application
|
|
264
|
+
|
|
265
|
+
def initialize(name:, location:, args: [])
|
|
266
|
+
@name = name
|
|
267
|
+
@location = location
|
|
268
|
+
@args = args
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def ==(other)
|
|
272
|
+
other.is_a?(ClassSingleton) && other.name == name && other.args == args
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
alias eql? ==
|
|
276
|
+
|
|
277
|
+
def hash
|
|
278
|
+
self.class.hash ^ name.hash ^ args.hash
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def sub(s)
|
|
282
|
+
return self if s.empty?
|
|
283
|
+
|
|
284
|
+
self.class.new(name: name,
|
|
285
|
+
args: args.map {|ty| ty.sub(s) },
|
|
286
|
+
location: location)
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def to_json(state = _ = nil)
|
|
290
|
+
{ class: :class_singleton, name: name, args: args, location: location }.to_json(state)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def to_s(level = 0)
|
|
294
|
+
if args.empty?
|
|
295
|
+
"singleton(#{name})"
|
|
296
|
+
else
|
|
297
|
+
"singleton(#{name})[#{args.join(", ")}]"
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def map_type_name(&block)
|
|
302
|
+
ClassSingleton.new(
|
|
303
|
+
name: yield(name, location, self),
|
|
304
|
+
args: args.map {|type| type.map_type_name(&block) },
|
|
305
|
+
location: location
|
|
306
|
+
)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def map_type(&block)
|
|
310
|
+
if block
|
|
311
|
+
ClassSingleton.new(
|
|
312
|
+
name: name,
|
|
313
|
+
args: args.map {|type| yield type },
|
|
314
|
+
location: location
|
|
315
|
+
)
|
|
316
|
+
else
|
|
317
|
+
enum_for :map_type
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
312
322
|
class Interface
|
|
313
323
|
attr_reader :location
|
|
314
324
|
|
|
@@ -192,6 +192,31 @@ module RBS
|
|
|
192
192
|
end
|
|
193
193
|
end
|
|
194
194
|
|
|
195
|
+
ruby2_keywords def assert_send_type_error(method_type, error_type, receiver, method, *args, &block)
|
|
196
|
+
send_setup(method_type, receiver, method, args, block) do |method_type, trace, result, exception|
|
|
197
|
+
typecheck = RBS::Test::TypeCheck.new(
|
|
198
|
+
self_class: receiver.class,
|
|
199
|
+
builder: builder,
|
|
200
|
+
sample_size: 100,
|
|
201
|
+
unchecked_classes: [],
|
|
202
|
+
instance_class: instance_class,
|
|
203
|
+
class_class: class_class
|
|
204
|
+
)
|
|
205
|
+
errors = typecheck.method_call(method, method_type, trace, errors: [])
|
|
206
|
+
|
|
207
|
+
assert_empty errors.map {|x| RBS::Test::Errors.to_string(x) }, "Call trace does not match with given method type: #{trace.inspect}"
|
|
208
|
+
|
|
209
|
+
method_defs = method_defs(method)
|
|
210
|
+
all_errors = method_defs.map {|t| typecheck.method_call(method, t.type, trace, errors: [], annotations: t.each_annotation.to_a) }
|
|
211
|
+
assert all_errors.any? {|es| es.empty? }, "Call trace does not match one of method definitions:\n #{trace.inspect}\n #{method_defs.map(&:type).join(" | ")}"
|
|
212
|
+
|
|
213
|
+
# Use `instnace_of?` instead of `is_a?` as we want to check for _the exact exception class_.
|
|
214
|
+
assert exception.instance_of? error_type
|
|
215
|
+
|
|
216
|
+
result
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
195
220
|
ruby2_keywords def refute_send_type(method_type, receiver, method, *args, &block)
|
|
196
221
|
send_setup(method_type, receiver, method, args, block) do |method_type, trace, result, exception|
|
|
197
222
|
method_type = method_type.update(
|
|
@@ -231,15 +256,17 @@ module RBS
|
|
|
231
256
|
type, definition = target
|
|
232
257
|
|
|
233
258
|
case type
|
|
234
|
-
when Types::ClassInstance
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
259
|
+
when Types::ClassInstance, Types::ClassSingleton
|
|
260
|
+
if type.is_a?(Types::ClassSingleton) && type.args.empty?
|
|
261
|
+
definition.methods[method].defs
|
|
262
|
+
else
|
|
263
|
+
subst = RBS::Substitution.build(definition.type_params, type.args)
|
|
264
|
+
definition.methods[method].defs.map do |type_def|
|
|
265
|
+
type_def.update(
|
|
266
|
+
type: type_def.type.sub(subst)
|
|
267
|
+
)
|
|
268
|
+
end
|
|
240
269
|
end
|
|
241
|
-
when Types::ClassSingleton
|
|
242
|
-
definition.methods[method].defs
|
|
243
270
|
else
|
|
244
271
|
raise
|
|
245
272
|
end
|
data/lib/rbs/version.rb
CHANGED
data/lib/rbs.rb
CHANGED
data/rbs.gemspec
CHANGED
data/rust/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/target/
|