rbs 4.1.2-java → 4.2.0-java

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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/bundle-update.yml +2 -2
  4. data/.github/workflows/c-check.yml +2 -2
  5. data/.github/workflows/changelog.yml +121 -0
  6. data/.github/workflows/comments.yml +2 -2
  7. data/.github/workflows/dependabot.yml +1 -1
  8. data/.github/workflows/jruby.yml +3 -3
  9. data/.github/workflows/release-gems.yml +6 -7
  10. data/.github/workflows/ruby.yml +6 -6
  11. data/.github/workflows/rust.yml +12 -12
  12. data/.github/workflows/truffleruby.yml +2 -2
  13. data/.github/workflows/typecheck.yml +2 -2
  14. data/.github/workflows/wasm.yml +3 -3
  15. data/.github/workflows/windows.yml +2 -2
  16. data/.rubocop.yml +0 -1
  17. data/CHANGELOG.md +57 -0
  18. data/Rakefile +50 -21
  19. data/config.yml +5 -0
  20. data/core/io.rbs +2 -1
  21. data/docs/CONTRIBUTING.md +1 -1
  22. data/docs/release.md +57 -1
  23. data/docs/stdlib.md +8 -0
  24. data/docs/syntax.md +12 -0
  25. data/ext/rbs_extension/ast_translation.c +15 -0
  26. data/ext/rbs_extension/class_constants.c +2 -0
  27. data/ext/rbs_extension/class_constants.h +1 -0
  28. data/ext/rbs_extension/main.c +55 -19
  29. data/include/rbs/ast.h +21 -13
  30. data/include/rbs/defines.h +8 -3
  31. data/include/rbs/lexer.h +13 -12
  32. data/include/rbs/parser.h +37 -3
  33. data/lib/rbs/ast/declarations.rb +1 -1
  34. data/lib/rbs/ast/type_param.rb +1 -1
  35. data/lib/rbs/definition_builder/ancestor_builder.rb +8 -5
  36. data/lib/rbs/definition_builder/method_builder.rb +4 -4
  37. data/lib/rbs/definition_builder.rb +5 -2
  38. data/lib/rbs/environment/class_entry.rb +12 -0
  39. data/lib/rbs/environment/module_entry.rb +26 -1
  40. data/lib/rbs/parser_aux.rb +2 -2
  41. data/lib/rbs/prototype/helpers.rb +19 -52
  42. data/lib/rbs/prototype/runtime/value_object_generator.rb +0 -1
  43. data/lib/rbs/prototype/runtime.rb +1 -1
  44. data/lib/rbs/types.rb +44 -2
  45. data/lib/rbs/unit_test/type_assertions.rb +5 -5
  46. data/lib/rbs/version.rb +1 -1
  47. data/lib/rbs/wasm/parser.rb +62 -25
  48. data/lib/rbs/wasm/rbs_parser.wasm +0 -0
  49. data/lib/rbs/wasm/runtime.rb +19 -4
  50. data/lib/rbs/wasm/serialization_schema.rb +3 -2
  51. data/rbs.gemspec +1 -5
  52. data/schema/function.json +12 -1
  53. data/sig/environment/class_entry.rbs +6 -0
  54. data/sig/environment/module_entry.rbs +15 -0
  55. data/sig/parser.rbs +4 -4
  56. data/sig/types.rbs +11 -1
  57. data/sig/unit_test/type_assertions.rbs +2 -2
  58. data/src/ast.c +17 -1
  59. data/src/lexer.c +1562 -1560
  60. data/src/lexer.re +50 -18
  61. data/src/lexstate.c +2 -1
  62. data/src/parser.c +130 -70
  63. data/src/serialize.c +20 -13
  64. data/src/util/rbs_encoding.c +195 -49
  65. data/stdlib/erb/0/erb.rbs +4 -4
  66. data/stdlib/monitor/0/monitor.rbs +4 -4
  67. data/stdlib/singleton/0/singleton.rbs +3 -0
  68. data/stdlib/stringio/0/stringio.rbs +2 -1
  69. data/stdlib/zlib/0/gzip_file.rbs +1 -1
  70. data/stdlib/zlib/0/gzip_writer.rbs +2 -1
  71. data/wasm/README.md +20 -4
  72. data/wasm/rbs_wasm.c +93 -37
  73. metadata +5 -3
data/include/rbs/parser.h CHANGED
@@ -40,6 +40,21 @@ typedef struct rbs_error_t {
40
40
  bool syntax_error;
41
41
  } rbs_error_t;
42
42
 
43
+ /**
44
+ * Options that control which syntax the parser accepts.
45
+ *
46
+ * Zero-initializing the struct gives the default configuration, where
47
+ * every optional syntax is disabled.
48
+ * */
49
+ typedef struct {
50
+ /**
51
+ * Accept `(...)` forwarding parameters in method types.
52
+ *
53
+ * The syntax is experimental and disabled by default.
54
+ * */
55
+ bool enable_forwarding_params;
56
+ } rbs_parser_options_t;
57
+
43
58
  /**
44
59
  * An RBS parser is a LL(3) parser.
45
60
  * */
@@ -57,6 +72,8 @@ typedef struct {
57
72
  rbs_constant_pool_t constant_pool;
58
73
  rbs_allocator_t *allocator;
59
74
  rbs_error_t *error;
75
+
76
+ rbs_parser_options_t options;
60
77
  } rbs_parser_t;
61
78
 
62
79
  /**
@@ -80,7 +97,7 @@ void rbs_parser_push_typevar_table(rbs_parser_t *parser, bool reset);
80
97
  /**
81
98
  * Insert new type variable into the latest table.
82
99
  * */
83
- NODISCARD bool rbs_parser_insert_typevar(rbs_parser_t *parser, rbs_constant_id_t id);
100
+ RBS_NODISCARD bool rbs_parser_insert_typevar(rbs_parser_t *parser, rbs_constant_id_t id);
84
101
 
85
102
  /**
86
103
  * Allocate new rbs_lexer_t object.
@@ -89,8 +106,13 @@ NODISCARD bool rbs_parser_insert_typevar(rbs_parser_t *parser, rbs_constant_id_t
89
106
  * VALUE string = rb_funcall(buffer, rb_intern("content"), 0);
90
107
  * rbs_lexer_new(string, 0, 31) // New rbs_lexer_t with buffer content
91
108
  * ```
109
+ *
110
+ * Returns `NULL` when `start_pos` is not the first byte of a character in
111
+ * `string` -- inside one, or past the end of the buffer. The lexer reaches
112
+ * `start_pos` a character at a time, so nowhere else is a position it can
113
+ * start from.
92
114
  * */
93
- rbs_lexer_t *rbs_lexer_new(rbs_allocator_t *, rbs_string_t string, const rbs_encoding_t *encoding, int start_pos, int end_pos);
115
+ RBS_NODISCARD rbs_lexer_t *rbs_lexer_new(rbs_allocator_t *, rbs_string_t string, const rbs_encoding_t *encoding, int start_pos, int end_pos);
94
116
 
95
117
  /**
96
118
  * Allocate new rbs_parser_t object.
@@ -98,8 +120,20 @@ rbs_lexer_t *rbs_lexer_new(rbs_allocator_t *, rbs_string_t string, const rbs_enc
98
120
  * ```
99
121
  * rbs_parser_new(buffer, string, encoding, 0, 1);
100
122
  * ```
123
+ *
124
+ * Returns `NULL` for a `start_pos` that `rbs_lexer_new` rejects.
125
+ * */
126
+ RBS_NODISCARD rbs_parser_t *rbs_parser_new(rbs_string_t string, const rbs_encoding_t *encoding, int start_pos, int end_pos);
127
+
128
+ /**
129
+ * Allocate new rbs_parser_t object with the given options.
130
+ *
131
+ * `rbs_parser_new` is equivalent to passing a zero-initialized
132
+ * `rbs_parser_options_t`, which disables every optional syntax.
133
+ *
134
+ * Returns `NULL` for a `start_pos` that `rbs_lexer_new` rejects.
101
135
  * */
102
- rbs_parser_t *rbs_parser_new(rbs_string_t string, const rbs_encoding_t *encoding, int start_pos, int end_pos);
136
+ RBS_NODISCARD rbs_parser_t *rbs_parser_new_with_options(rbs_string_t string, const rbs_encoding_t *encoding, int start_pos, int end_pos, rbs_parser_options_t options);
103
137
  void rbs_parser_free(rbs_parser_t *parser);
104
138
 
105
139
  /**
@@ -163,7 +163,7 @@ module RBS
163
163
  alias eql? ==
164
164
 
165
165
  def hash
166
- self.class.hash ^ name.hash ^ args.hash ^ location.hash
166
+ self.class.hash ^ name.hash ^ args.hash
167
167
  end
168
168
 
169
169
  def to_json(state = nil)
@@ -114,7 +114,7 @@ module RBS
114
114
  def self.rename(params, new_names:)
115
115
  raise unless params.size == new_names.size
116
116
 
117
- subst = Substitution.build(new_names, Types::Variable.build(new_names))
117
+ subst = Substitution.build(params.map(&:name), Types::Variable.build(new_names))
118
118
 
119
119
  params.map.with_index do |param, index|
120
120
  new_name = new_names[index]
@@ -179,7 +179,13 @@ module RBS
179
179
 
180
180
  super_types = with_super_classes.map do |decl|
181
181
  super_class = decl.super_class or raise
182
- Types::ClassInstance.new(name: super_class.name, args: super_class.args, location: nil)
182
+ args = super_class.args
183
+
184
+ if align_params = entry.align_params(decl)
185
+ args = args.map {|type| type.sub(align_params) }
186
+ end
187
+
188
+ Types::ClassInstance.new(name: super_class.name, args: args, location: nil)
183
189
  end
184
190
 
185
191
  super_types.uniq!
@@ -473,10 +479,7 @@ module RBS
473
479
 
474
480
  def mixin_ancestors(entry, type_name, included_modules:, included_interfaces:, extended_modules:, prepended_modules:, extended_interfaces:)
475
481
  entry.each_decl do |decl|
476
- align_params = Substitution.build(
477
- decl.type_params.each.map(&:name),
478
- entry.type_params.map {|param| Types::Variable.new(name: param.name, location: param.location) }
479
- )
482
+ align_params = entry.align_params(decl)
480
483
 
481
484
  mixin_ancestors0(decl,
482
485
  type_name,
@@ -104,7 +104,7 @@ module RBS
104
104
  type = Types::ClassInstance.new(name: type_name, args: args, location: nil)
105
105
  Methods.new(type: type).tap do |methods|
106
106
  entry.each_decl do |decl|
107
- subst = Substitution.build(decl.type_params.each.map(&:name), args)
107
+ subst = entry.align_params(decl)
108
108
  case decl
109
109
  when AST::Declarations::Base
110
110
  each_rbs_member_with_accessibility(decl.members) do |member, accessibility|
@@ -115,14 +115,14 @@ module RBS
115
115
  build_method(
116
116
  methods,
117
117
  type,
118
- member: member.update(overloads: member.overloads.map {|overload| overload.sub(subst) }),
118
+ member: subst ? member.update(overloads: member.overloads.map {|overload| overload.sub(subst) }) : member,
119
119
  accessibility: member.visibility || accessibility
120
120
  )
121
121
  when :singleton_instance
122
122
  build_method(
123
123
  methods,
124
124
  type,
125
- member: member.update(overloads: member.overloads.map {|overload| overload.sub(subst) }),
125
+ member: subst ? member.update(overloads: member.overloads.map {|overload| overload.sub(subst) }) : member,
126
126
  accessibility: :private
127
127
  )
128
128
  end
@@ -130,7 +130,7 @@ module RBS
130
130
  if member.kind == :instance
131
131
  build_attribute(methods,
132
132
  type,
133
- member: member.update(type: member.type.sub(subst)),
133
+ member: subst ? member.update(type: member.type.sub(subst)) : member,
134
134
  accessibility: member.visibility || accessibility)
135
135
  end
136
136
  when AST::Members::Alias
@@ -124,10 +124,13 @@ module RBS
124
124
  end
125
125
 
126
126
  entry = env.class_decls[type_name] or raise "Unknown name for build_instance: #{type_name}"
127
- args = entry.type_params.map {|param| Types::Variable.new(name: param.name, location: param.location) }
128
127
 
129
128
  entry.each_decl do |decl|
130
- subst_ = subst + Substitution.build(decl.type_params.each.map(&:name), args)
129
+ if align_params = entry.align_params(decl)
130
+ subst_ = subst + align_params
131
+ else
132
+ subst_ = subst
133
+ end
131
134
 
132
135
  decl.members.each do |member|
133
136
  case member
@@ -64,6 +64,18 @@ module RBS
64
64
  end
65
65
  end
66
66
  end
67
+
68
+ def align_params(decl)
69
+ entry_params = type_params
70
+ decl_param_names = decl.type_params.map(&:name)
71
+
72
+ return nil if decl_param_names == entry_params.map(&:name)
73
+
74
+ Substitution.build(
75
+ decl_param_names,
76
+ entry_params.map {|param| Types::Variable.new(name: param.name, location: param.location) }
77
+ )
78
+ end
67
79
  end
68
80
  end
69
81
  end
@@ -42,10 +42,35 @@ module RBS
42
42
 
43
43
  def self_types
44
44
  each_decl.flat_map do |decl|
45
- decl.self_types
45
+ self_types = decl.self_types
46
+ subst = align_params(decl)
47
+
48
+ if self_types.empty? || subst.nil?
49
+ self_types
50
+ else
51
+ self_types.map do |self_type|
52
+ AST::Declarations::Module::Self.new(
53
+ name: self_type.name,
54
+ args: self_type.args.map {|type| type.sub(subst) },
55
+ location: self_type.location
56
+ )
57
+ end
58
+ end
46
59
  end.uniq
47
60
  end
48
61
 
62
+ def align_params(decl)
63
+ entry_params = type_params
64
+ decl_param_names = decl.type_params.map(&:name)
65
+
66
+ return nil if decl_param_names == entry_params.map(&:name)
67
+
68
+ Substitution.build(
69
+ decl_param_names,
70
+ entry_params.map {|param| Types::Variable.new(name: param.name, location: param.location) }
71
+ )
72
+ end
73
+
49
74
  def validate_type_params
50
75
  unless context_decls.empty?
51
76
  first_decl, *rest_decls = each_decl.to_a
@@ -14,7 +14,7 @@ module RBS
14
14
  def self.parse_method_type(source, range: nil, byte_range: 0..., variables: [], require_eof: false)
15
15
  buf = buffer(source)
16
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)
17
+ _parse_method_type(buf, byte_range.begin || 0, byte_range.end || buf.content.bytesize, variables, require_eof, false)
18
18
  end
19
19
 
20
20
  def self.parse_signature(source)
@@ -28,7 +28,7 @@ module RBS
28
28
  0
29
29
  end
30
30
  content = buf.content
31
- dirs, decls = _parse_signature(buf, start_pos, content.bytesize)
31
+ dirs, decls = _parse_signature(buf, start_pos, content.bytesize, false)
32
32
 
33
33
  if resolved
34
34
  dirs = dirs.dup if dirs.frozen?
@@ -5,58 +5,25 @@ 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
8
+ def parse_comments(string, include_trailing:)
9
+ Prism.parse_comments(string, version: "current").yield_self do |prism_comments| # steep:ignore UnexpectedKeywordArgument
10
+ prism_comments.each_with_object({}) do |comment, hash| #$ Hash[Integer, AST::Comment]
11
+ # Skip EmbDoc comments
12
+ next unless comment.is_a?(Prism::InlineComment)
13
+ # skip like `module Foo # :nodoc:`
14
+ next if comment.trailing? && !include_trailing
15
+
16
+ line = comment.location.start_line
17
+ body = "#{comment.location.slice}\n"
18
+ body = body[2..-1] or raise
19
+ body = "\n" if body.empty?
20
+
21
+ comment = AST::Comment.new(string: body, location: nil)
22
+ if prev_comment = hash.delete(line - 1)
23
+ hash[line] = AST::Comment.new(string: prev_comment.string + comment.string,
24
+ location: nil)
25
+ else
26
+ hash[line] = comment
60
27
  end
61
28
  end
62
29
  end
@@ -212,7 +212,6 @@ module RBS
212
212
 
213
213
  class DataGenerator < ValueObjectBase
214
214
  def self.generatable?(target)
215
- return false unless RUBY_VERSION >= '3.2'
216
215
  return false unless target < Data
217
216
  # Avoid direct inherited class like `class Option < Data`
218
217
  return false unless target.respond_to?(:members)
@@ -527,7 +527,7 @@ module RBS
527
527
 
528
528
  generate_mixin(mod, decl, type_name, type_name_absolute)
529
529
 
530
- unless mod < Struct || (RUBY_VERSION >= '3.2' && mod < Data)
530
+ unless mod < Struct || mod < Data
531
531
  generate_methods(mod, type_name, decl.members) unless outline
532
532
  end
533
533
 
data/lib/rbs/types.rb CHANGED
@@ -959,6 +959,33 @@ module RBS
959
959
  end
960
960
  end
961
961
 
962
+ class ForwardingParam
963
+ attr_reader :location
964
+
965
+ def initialize(location:)
966
+ @location = location
967
+ end
968
+
969
+ def ==(other)
970
+ other.is_a?(ForwardingParam)
971
+ end
972
+
973
+ alias eql? ==
974
+
975
+ def hash
976
+ self.class.hash
977
+ end
978
+
979
+ def to_json(state = nil)
980
+ json = {} #: Hash[Symbol, untyped]
981
+ json.to_json(state)
982
+ end
983
+
984
+ def to_s
985
+ "..."
986
+ end
987
+ end
988
+
962
989
  attr_reader :required_positionals
963
990
  attr_reader :optional_positionals
964
991
  attr_reader :rest_positionals
@@ -966,9 +993,10 @@ module RBS
966
993
  attr_reader :required_keywords
967
994
  attr_reader :optional_keywords
968
995
  attr_reader :rest_keywords
996
+ attr_reader :forwarding
969
997
  attr_reader :return_type
970
998
 
971
- def initialize(required_positionals:, optional_positionals:, rest_positionals:, trailing_positionals:, required_keywords:, optional_keywords:, rest_keywords:, return_type:)
999
+ def initialize(required_positionals:, optional_positionals:, rest_positionals:, trailing_positionals:, required_keywords:, optional_keywords:, rest_keywords:, return_type:, forwarding: nil)
972
1000
  @return_type = return_type
973
1001
  @required_positionals = required_positionals
974
1002
  @optional_positionals = optional_positionals
@@ -977,6 +1005,7 @@ module RBS
977
1005
  @required_keywords = required_keywords
978
1006
  @optional_keywords = optional_keywords
979
1007
  @rest_keywords = rest_keywords
1008
+ @forwarding = forwarding
980
1009
  end
981
1010
 
982
1011
  def ==(other)
@@ -988,6 +1017,7 @@ module RBS
988
1017
  other.required_keywords == required_keywords &&
989
1018
  other.optional_keywords == optional_keywords &&
990
1019
  other.rest_keywords == rest_keywords &&
1020
+ other.forwarding == forwarding &&
991
1021
  other.return_type == return_type
992
1022
  end
993
1023
 
@@ -1002,6 +1032,7 @@ module RBS
1002
1032
  required_keywords.hash ^
1003
1033
  optional_keywords.hash ^
1004
1034
  rest_keywords.hash ^
1035
+ forwarding.hash ^
1005
1036
  return_type.hash
1006
1037
  end
1007
1038
 
@@ -1043,6 +1074,7 @@ module RBS
1043
1074
  required_keywords: hmapv(required_keywords) {|param| param.map_type(&block) },
1044
1075
  optional_keywords: hmapv(optional_keywords) {|param| param.map_type(&block) },
1045
1076
  rest_keywords: rest_keywords&.yield_self {|param| param.map_type(&block) },
1077
+ forwarding: forwarding,
1046
1078
  return_type: yield(return_type)
1047
1079
  )
1048
1080
  else
@@ -1110,6 +1142,7 @@ module RBS
1110
1142
  required_keywords: required_keywords,
1111
1143
  optional_keywords: optional_keywords,
1112
1144
  rest_keywords: rest_keywords,
1145
+ forwarding: forwarding,
1113
1146
  return_type: return_type
1114
1147
  }.to_json(state)
1115
1148
  end
@@ -1129,6 +1162,7 @@ module RBS
1129
1162
  required_keywords: {},
1130
1163
  optional_keywords: {},
1131
1164
  rest_keywords: nil,
1165
+ forwarding: nil,
1132
1166
  return_type: return_type
1133
1167
  )
1134
1168
  end
@@ -1142,12 +1176,13 @@ module RBS
1142
1176
  required_keywords: required_keywords,
1143
1177
  optional_keywords: optional_keywords,
1144
1178
  rest_keywords: rest_keywords,
1179
+ forwarding: forwarding,
1145
1180
  return_type: type
1146
1181
  )
1147
1182
  end
1148
1183
 
1149
1184
  def update(required_positionals: self.required_positionals, optional_positionals: self.optional_positionals, rest_positionals: self.rest_positionals, trailing_positionals: self.trailing_positionals,
1150
- required_keywords: self.required_keywords, optional_keywords: self.optional_keywords, rest_keywords: self.rest_keywords, return_type: self.return_type)
1185
+ required_keywords: self.required_keywords, optional_keywords: self.optional_keywords, rest_keywords: self.rest_keywords, forwarding: self.forwarding, return_type: self.return_type)
1151
1186
  Function.new(
1152
1187
  required_positionals: required_positionals,
1153
1188
  optional_positionals: optional_positionals,
@@ -1156,6 +1191,7 @@ module RBS
1156
1191
  required_keywords: required_keywords,
1157
1192
  optional_keywords: optional_keywords,
1158
1193
  rest_keywords: rest_keywords,
1194
+ forwarding: forwarding,
1159
1195
  return_type: return_type
1160
1196
  )
1161
1197
  end
@@ -1167,6 +1203,7 @@ module RBS
1167
1203
  trailing_positionals.empty? &&
1168
1204
  required_keywords.empty? &&
1169
1205
  optional_keywords.empty? &&
1206
+ !forwarding? &&
1170
1207
  !rest_keywords
1171
1208
  end
1172
1209
 
@@ -1175,6 +1212,7 @@ module RBS
1175
1212
  params = []
1176
1213
 
1177
1214
  params.push(*required_positionals.map(&:to_s))
1215
+ params.push(forwarding.to_s) if forwarding
1178
1216
  params.push(*optional_positionals.map {|p| "?#{p}"})
1179
1217
  params.push("*#{rest_positionals}") if rest_positionals
1180
1218
  params.push(*trailing_positionals.map(&:to_s))
@@ -1185,6 +1223,10 @@ module RBS
1185
1223
  params.join(", ")
1186
1224
  end
1187
1225
 
1226
+ def forwarding?
1227
+ !forwarding.nil?
1228
+ end
1229
+
1188
1230
  def return_to_s
1189
1231
  return_type.to_s(1)
1190
1232
  end
@@ -180,11 +180,11 @@ module RBS
180
180
  )
181
181
  errors = typecheck.method_call(method, method_type, trace, errors: [])
182
182
 
183
- assert_empty errors.map {|x| RBS::Test::Errors.to_string(x) }, "Call trace does not match with given method type: #{trace.inspect}"
183
+ assert_empty errors.map {|x| RBS::Test::Errors.to_string(x) }, -> { "Call trace does not match with given method type: #{trace.inspect}" }
184
184
 
185
185
  method_defs = method_defs(method)
186
186
  all_errors = method_defs.map {|t| typecheck.method_call(method, t.type, trace, errors: [], annotations: t.each_annotation.to_a) }
187
- 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(" | ")}"
187
+ 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(" | ")}" }
188
188
 
189
189
  raise exception if exception
190
190
 
@@ -204,11 +204,11 @@ module RBS
204
204
  )
205
205
  errors = typecheck.method_call(method, method_type, trace, errors: [])
206
206
 
207
- assert_empty errors.map {|x| RBS::Test::Errors.to_string(x) }, "Call trace does not match with given method type: #{trace.inspect}"
207
+ assert_empty errors.map {|x| RBS::Test::Errors.to_string(x) }, -> { "Call trace does not match with given method type: #{trace.inspect}" }
208
208
 
209
209
  method_defs = method_defs(method)
210
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(" | ")}"
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
212
 
213
213
  # Use `instnace_of?` instead of `is_a?` as we want to check for _the exact exception class_.
214
214
  assert exception.instance_of? error_type
@@ -246,7 +246,7 @@ module RBS
246
246
 
247
247
  method_defs = method_defs(method)
248
248
  all_errors = method_defs.map {|t| typecheck.method_call(method, t.type, trace, errors: [], annotations: t.each_annotation.to_a) }
249
- assert all_errors.all? {|es| es.size > 0 }, "Call trace unexpectedly matches one of method definitions:\n #{trace.inspect}\n #{method_defs.map(&:type).join(" | ")}"
249
+ assert all_errors.all? {|es| es.size > 0 }, -> { "Call trace unexpectedly matches one of method definitions:\n #{trace.inspect}\n #{method_defs.map(&:type).join(" | ")}" }
250
250
 
251
251
  result
252
252
  end
data/lib/rbs/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RBS
4
- VERSION = "4.1.2"
4
+ VERSION = "4.2.0"
5
5
  end