rbs 4.1.0 → 4.2.0

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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.github/dependabot.yml +1 -1
  4. data/.github/workflows/bundle-update.yml +3 -3
  5. data/.github/workflows/c-check.yml +2 -2
  6. data/.github/workflows/changelog.yml +121 -0
  7. data/.github/workflows/comments.yml +2 -2
  8. data/.github/workflows/dependabot.yml +1 -1
  9. data/.github/workflows/jruby.yml +4 -9
  10. data/.github/workflows/release-gems.yml +234 -0
  11. data/.github/workflows/ruby.yml +6 -6
  12. data/.github/workflows/rust.yml +12 -12
  13. data/.github/workflows/truffleruby.yml +2 -2
  14. data/.github/workflows/typecheck.yml +2 -2
  15. data/.github/workflows/wasm.yml +3 -3
  16. data/.github/workflows/windows.yml +2 -2
  17. data/.rubocop.yml +0 -1
  18. data/CHANGELOG.md +83 -0
  19. data/README.md +1 -1
  20. data/Rakefile +443 -86
  21. data/config.yml +7 -0
  22. data/core/io.rbs +2 -1
  23. data/docs/CONTRIBUTING.md +1 -1
  24. data/docs/release.md +265 -31
  25. data/docs/stdlib.md +8 -0
  26. data/docs/syntax.md +12 -0
  27. data/ext/rbs_extension/ast_translation.c +15 -0
  28. data/ext/rbs_extension/class_constants.c +2 -0
  29. data/ext/rbs_extension/class_constants.h +1 -0
  30. data/ext/rbs_extension/main.c +55 -19
  31. data/include/rbs/ast.h +25 -17
  32. data/include/rbs/defines.h +8 -3
  33. data/include/rbs/lexer.h +13 -12
  34. data/include/rbs/parser.h +37 -3
  35. data/lib/rbs/ast/declarations.rb +1 -1
  36. data/lib/rbs/ast/type_param.rb +1 -1
  37. data/lib/rbs/definition_builder/ancestor_builder.rb +8 -5
  38. data/lib/rbs/definition_builder/method_builder.rb +4 -4
  39. data/lib/rbs/definition_builder.rb +5 -2
  40. data/lib/rbs/environment/class_entry.rb +12 -0
  41. data/lib/rbs/environment/module_entry.rb +26 -1
  42. data/lib/rbs/parser_aux.rb +2 -2
  43. data/lib/rbs/prototype/helpers.rb +19 -52
  44. data/lib/rbs/prototype/runtime/value_object_generator.rb +0 -1
  45. data/lib/rbs/prototype/runtime.rb +1 -1
  46. data/lib/rbs/types.rb +44 -2
  47. data/lib/rbs/unit_test/type_assertions.rb +5 -5
  48. data/lib/rbs/version.rb +1 -1
  49. data/lib/rbs/wasm/parser.rb +62 -25
  50. data/lib/rbs/wasm/runtime.rb +19 -4
  51. data/lib/rbs/wasm/serialization_schema.rb +3 -2
  52. data/rbs.gemspec +1 -5
  53. data/schema/function.json +12 -1
  54. data/sig/environment/class_entry.rbs +6 -0
  55. data/sig/environment/module_entry.rbs +15 -0
  56. data/sig/parser.rbs +4 -4
  57. data/sig/types.rbs +11 -1
  58. data/sig/unit_test/type_assertions.rbs +2 -2
  59. data/src/ast.c +19 -3
  60. data/src/lexer.c +1562 -1560
  61. data/src/lexer.re +50 -18
  62. data/src/lexstate.c +2 -1
  63. data/src/parser.c +136 -73
  64. data/src/serialize.c +20 -13
  65. data/src/util/rbs_encoding.c +195 -49
  66. data/stdlib/erb/0/erb.rbs +4 -4
  67. data/stdlib/monitor/0/monitor.rbs +4 -4
  68. data/stdlib/singleton/0/singleton.rbs +3 -0
  69. data/stdlib/stringio/0/stringio.rbs +2 -1
  70. data/stdlib/zlib/0/gzip_file.rbs +1 -1
  71. data/stdlib/zlib/0/gzip_writer.rbs +2 -1
  72. data/wasm/README.md +53 -4
  73. data/wasm/rbs_wasm.c +93 -37
  74. metadata +6 -4
  75. data/.github/workflows/milestone.yml +0 -91
data/include/rbs/ast.h CHANGED
@@ -125,18 +125,19 @@ enum rbs_node_type {
125
125
  RBS_TYPES_CLASS_INSTANCE = 63,
126
126
  RBS_TYPES_CLASS_SINGLETON = 64,
127
127
  RBS_TYPES_FUNCTION = 65,
128
- RBS_TYPES_FUNCTION_PARAM = 66,
129
- RBS_TYPES_INTERFACE = 67,
130
- RBS_TYPES_INTERSECTION = 68,
131
- RBS_TYPES_LITERAL = 69,
132
- RBS_TYPES_OPTIONAL = 70,
133
- RBS_TYPES_PROC = 71,
134
- RBS_TYPES_RECORD = 72,
135
- RBS_TYPES_RECORD_FIELD_TYPE = 73,
136
- RBS_TYPES_TUPLE = 74,
137
- RBS_TYPES_UNION = 75,
138
- RBS_TYPES_UNTYPED_FUNCTION = 76,
139
- RBS_TYPES_VARIABLE = 77,
128
+ RBS_TYPES_FUNCTION_FORWARDING_PARAM = 66,
129
+ RBS_TYPES_FUNCTION_PARAM = 67,
130
+ RBS_TYPES_INTERFACE = 68,
131
+ RBS_TYPES_INTERSECTION = 69,
132
+ RBS_TYPES_LITERAL = 70,
133
+ RBS_TYPES_OPTIONAL = 71,
134
+ RBS_TYPES_PROC = 72,
135
+ RBS_TYPES_RECORD = 73,
136
+ RBS_TYPES_RECORD_FIELD_TYPE = 74,
137
+ RBS_TYPES_TUPLE = 75,
138
+ RBS_TYPES_UNION = 76,
139
+ RBS_TYPES_UNTYPED_FUNCTION = 77,
140
+ RBS_TYPES_VARIABLE = 78,
140
141
  RBS_AST_SYMBOL,
141
142
  };
142
143
 
@@ -583,7 +584,7 @@ typedef struct rbs_ast_ruby_annotations_class_alias_annotation {
583
584
 
584
585
  rbs_location_range prefix_location;
585
586
  rbs_location_range keyword_location;
586
- struct rbs_type_name *RBS_NONNULL type_name;
587
+ struct rbs_type_name *RBS_NULLABLE type_name;
587
588
  rbs_location_range type_name_location;
588
589
  } rbs_ast_ruby_annotations_class_alias_annotation_t;
589
590
 
@@ -631,7 +632,7 @@ typedef struct rbs_ast_ruby_annotations_module_alias_annotation {
631
632
 
632
633
  rbs_location_range prefix_location;
633
634
  rbs_location_range keyword_location;
634
- struct rbs_type_name *RBS_NONNULL type_name;
635
+ struct rbs_type_name *RBS_NULLABLE type_name;
635
636
  rbs_location_range type_name_location;
636
637
  } rbs_ast_ruby_annotations_module_alias_annotation_t;
637
638
 
@@ -854,9 +855,15 @@ typedef struct rbs_types_function {
854
855
  struct rbs_hash *RBS_NONNULL required_keywords;
855
856
  struct rbs_hash *RBS_NONNULL optional_keywords;
856
857
  struct rbs_node *RBS_NULLABLE rest_keywords;
858
+ struct rbs_node *RBS_NULLABLE forwarding;
857
859
  struct rbs_node *RBS_NONNULL return_type;
858
860
  } rbs_types_function_t;
859
861
 
862
+ typedef struct rbs_types_function_forwarding_param {
863
+ rbs_node_t base;
864
+
865
+ } rbs_types_function_forwarding_param_t;
866
+
860
867
  typedef struct rbs_types_function_param {
861
868
  rbs_node_t base;
862
869
 
@@ -998,12 +1005,12 @@ rbs_ast_members_prepend_t *RBS_NONNULL rbs_ast_members_prepend_new(rbs_allocator
998
1005
  rbs_ast_members_private_t *RBS_NONNULL rbs_ast_members_private_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location);
999
1006
  rbs_ast_members_public_t *RBS_NONNULL rbs_ast_members_public_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location);
1000
1007
  rbs_ast_ruby_annotations_block_param_type_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_block_param_type_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range ampersand_location, rbs_location_range name_location, rbs_location_range colon_location, rbs_location_range question_location, rbs_location_range type_location, rbs_node_t *RBS_NONNULL type_, rbs_location_range comment_location);
1001
- rbs_ast_ruby_annotations_class_alias_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_class_alias_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_type_name_t *RBS_NONNULL type_name, rbs_location_range type_name_location);
1008
+ rbs_ast_ruby_annotations_class_alias_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_class_alias_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_type_name_t *RBS_NULLABLE type_name, rbs_location_range type_name_location);
1002
1009
  rbs_ast_ruby_annotations_colon_method_type_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_colon_method_type_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_node_list_t *RBS_NONNULL annotations, rbs_node_t *RBS_NONNULL method_type);
1003
1010
  rbs_ast_ruby_annotations_double_splat_param_type_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_double_splat_param_type_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range star2_location, rbs_location_range name_location, rbs_location_range colon_location, rbs_node_t *RBS_NONNULL param_type, rbs_location_range comment_location);
1004
1011
  rbs_ast_ruby_annotations_instance_variable_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_instance_variable_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_ast_symbol_t *RBS_NONNULL ivar_name, rbs_location_range ivar_name_location, rbs_location_range colon_location, rbs_node_t *RBS_NONNULL type, rbs_location_range comment_location);
1005
1012
  rbs_ast_ruby_annotations_method_types_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_method_types_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_node_list_t *RBS_NONNULL overloads, rbs_location_range_list_t *RBS_NONNULL vertical_bar_locations, rbs_location_range dot3_location);
1006
- rbs_ast_ruby_annotations_module_alias_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_module_alias_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_type_name_t *RBS_NONNULL type_name, rbs_location_range type_name_location);
1013
+ rbs_ast_ruby_annotations_module_alias_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_module_alias_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_type_name_t *RBS_NULLABLE type_name, rbs_location_range type_name_location);
1007
1014
  rbs_ast_ruby_annotations_module_self_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_module_self_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_location_range colon_location, rbs_type_name_t *RBS_NONNULL name, rbs_node_list_t *RBS_NONNULL args, rbs_location_range open_bracket_location, rbs_location_range close_bracket_location, rbs_location_range_list_t *RBS_NONNULL args_comma_locations, rbs_location_range comment_location);
1008
1015
  rbs_ast_ruby_annotations_node_type_assertion_t *RBS_NONNULL rbs_ast_ruby_annotations_node_type_assertion_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_node_t *RBS_NONNULL type);
1009
1016
  rbs_ast_ruby_annotations_param_type_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_param_type_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range name_location, rbs_location_range colon_location, rbs_node_t *RBS_NONNULL param_type, rbs_location_range comment_location);
@@ -1030,7 +1037,8 @@ rbs_types_bases_void_t *RBS_NONNULL rbs_types_bases_void_new(rbs_allocator_t *RB
1030
1037
  rbs_types_block_t *RBS_NONNULL rbs_types_block_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_t *RBS_NONNULL type, bool required, rbs_node_t *RBS_NULLABLE self_type);
1031
1038
  rbs_types_class_instance_t *RBS_NONNULL rbs_types_class_instance_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_type_name_t *RBS_NONNULL name, rbs_node_list_t *RBS_NONNULL args, rbs_location_range name_range);
1032
1039
  rbs_types_class_singleton_t *RBS_NONNULL rbs_types_class_singleton_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_type_name_t *RBS_NONNULL name, rbs_node_list_t *RBS_NONNULL args, rbs_location_range name_range);
1033
- rbs_types_function_t *RBS_NONNULL rbs_types_function_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_list_t *RBS_NONNULL required_positionals, rbs_node_list_t *RBS_NONNULL optional_positionals, rbs_node_t *RBS_NULLABLE rest_positionals, rbs_node_list_t *RBS_NONNULL trailing_positionals, rbs_hash_t *RBS_NONNULL required_keywords, rbs_hash_t *RBS_NONNULL optional_keywords, rbs_node_t *RBS_NULLABLE rest_keywords, rbs_node_t *RBS_NONNULL return_type);
1040
+ rbs_types_function_t *RBS_NONNULL rbs_types_function_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_list_t *RBS_NONNULL required_positionals, rbs_node_list_t *RBS_NONNULL optional_positionals, rbs_node_t *RBS_NULLABLE rest_positionals, rbs_node_list_t *RBS_NONNULL trailing_positionals, rbs_hash_t *RBS_NONNULL required_keywords, rbs_hash_t *RBS_NONNULL optional_keywords, rbs_node_t *RBS_NULLABLE rest_keywords, rbs_node_t *RBS_NULLABLE forwarding, rbs_node_t *RBS_NONNULL return_type);
1041
+ rbs_types_function_forwarding_param_t *RBS_NONNULL rbs_types_function_forwarding_param_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location);
1034
1042
  rbs_types_function_param_t *RBS_NONNULL rbs_types_function_param_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_t *RBS_NONNULL type, rbs_ast_symbol_t *RBS_NULLABLE name);
1035
1043
  rbs_types_interface_t *RBS_NONNULL rbs_types_interface_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_type_name_t *RBS_NONNULL name, rbs_node_list_t *RBS_NONNULL args, rbs_location_range name_range);
1036
1044
  rbs_types_intersection_t *RBS_NONNULL rbs_types_intersection_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_list_t *RBS_NONNULL types);
@@ -69,9 +69,9 @@
69
69
  **********************************************************************************************************************/
70
70
 
71
71
  #if defined(_MSC_VER)
72
- #define NODISCARD _Check_return_
72
+ #define RBS_NODISCARD _Check_return_
73
73
  #else
74
- #define NODISCARD __attribute__((warn_unused_result))
74
+ #define RBS_NODISCARD __attribute__((warn_unused_result))
75
75
  #endif
76
76
 
77
77
  /**
@@ -87,8 +87,13 @@
87
87
  * Nullability annotations for pointer types.
88
88
  * Clang supports _Nullable and _Nonnull to indicate whether a pointer may be NULL.
89
89
  * On other compilers, these expand to nothing.
90
+ *
91
+ * They are Clang extensions, so a strict ISO C compilation rejects them with
92
+ * `-Wnullability-extension`, which is an error under `-pedantic-errors`. Expand
93
+ * them to nothing in that case, so that embedders compiling these headers with a
94
+ * conforming dialect (`-std=c99` and friends define `__STRICT_ANSI__`) still build.
90
95
  */
91
- #ifdef __clang__
96
+ #if defined(__clang__) && !defined(__STRICT_ANSI__)
92
97
  #define RBS_NULLABLE _Nullable
93
98
  #define RBS_NONNULL _Nonnull
94
99
  #else
data/include/rbs/lexer.h CHANGED
@@ -72,18 +72,19 @@ enum RBSTokenType {
72
72
  kRETURN, /* return */
73
73
  kMODULESELF, /* module-self */
74
74
 
75
- tLIDENT, /* Identifiers starting with lower case */
76
- tUIDENT, /* Identifiers starting with upper case */
77
- tULIDENT, /* Identifiers starting with `_` followed by upper case */
78
- tULLIDENT, /* Identifiers starting with `_` followed by lower case */
79
- tGIDENT, /* Identifiers starting with `$` */
80
- tAIDENT, /* Identifiers starting with `@` */
81
- tA2IDENT, /* Identifiers starting with `@@` */
82
- tBANGIDENT, /* Identifiers ending with `!` */
83
- tEQIDENT, /* Identifiers ending with `=` */
84
- tQIDENT, /* Quoted identifier */
85
- pAREF_OPR, /* [] */
86
- tOPERATOR, /* Operator identifier */
75
+ tLIDENT, /* Identifiers starting with lower case */
76
+ tUIDENT, /* Identifiers starting with upper case */
77
+ tULIDENT, /* Identifiers starting with `_` followed by upper case */
78
+ tULLIDENT, /* Identifiers starting with `_` followed by lower case */
79
+ tNONASCIIIDENT, /* Identifiers starting with a character outside ASCII */
80
+ tGIDENT, /* Identifiers starting with `$` */
81
+ tAIDENT, /* Identifiers starting with `@` */
82
+ tA2IDENT, /* Identifiers starting with `@@` */
83
+ tBANGIDENT, /* Identifiers ending with `!` */
84
+ tEQIDENT, /* Identifiers ending with `=` */
85
+ tQIDENT, /* Quoted identifier */
86
+ pAREF_OPR, /* [] */
87
+ tOPERATOR, /* Operator identifier */
87
88
 
88
89
  tCOMMENT, /* Comment */
89
90
  tLINECOMMENT, /* Comment of all line */
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