rbs 3.9.2 → 4.0.0.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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -1
  3. data/.github/workflows/windows.yml +1 -1
  4. data/CHANGELOG.md +0 -13
  5. data/Rakefile +28 -21
  6. data/Steepfile +1 -0
  7. data/config.yml +232 -62
  8. data/ext/rbs_extension/ast_translation.c +1149 -0
  9. data/ext/rbs_extension/ast_translation.h +30 -0
  10. data/{src/constants.c → ext/rbs_extension/class_constants.c} +15 -1
  11. data/{include/rbs/constants.h → ext/rbs_extension/class_constants.h} +10 -1
  12. data/ext/rbs_extension/extconf.rb +3 -1
  13. data/ext/rbs_extension/{location.c → legacy_location.c} +25 -34
  14. data/ext/rbs_extension/legacy_location.h +40 -0
  15. data/ext/rbs_extension/main.c +402 -8
  16. data/ext/rbs_extension/rbs_extension.h +3 -21
  17. data/ext/rbs_extension/rbs_string_bridging.c +9 -0
  18. data/ext/rbs_extension/rbs_string_bridging.h +20 -0
  19. data/include/rbs/ast.h +748 -0
  20. data/include/rbs/defines.h +60 -0
  21. data/{ext/rbs_extension → include/rbs}/lexer.h +40 -32
  22. data/include/rbs/location.h +59 -0
  23. data/include/rbs/parser.h +151 -0
  24. data/include/rbs/string.h +49 -0
  25. data/include/rbs/util/rbs_allocator.h +38 -0
  26. data/include/rbs/util/rbs_assert.h +9 -0
  27. data/include/rbs/util/rbs_buffer.h +83 -0
  28. data/include/rbs/util/rbs_constant_pool.h +3 -64
  29. data/include/rbs/util/rbs_encoding.h +280 -0
  30. data/include/rbs/util/rbs_unescape.h +23 -0
  31. data/include/rbs.h +1 -2
  32. data/lib/rbs/annotate/formatter.rb +3 -13
  33. data/lib/rbs/annotate/rdoc_annotator.rb +3 -1
  34. data/lib/rbs/annotate/rdoc_source.rb +1 -1
  35. data/lib/rbs/ast/ruby/annotations.rb +119 -0
  36. data/lib/rbs/ast/ruby/comment_block.rb +221 -0
  37. data/lib/rbs/ast/ruby/declarations.rb +86 -0
  38. data/lib/rbs/ast/ruby/helpers/constant_helper.rb +24 -0
  39. data/lib/rbs/ast/ruby/helpers/location_helper.rb +15 -0
  40. data/lib/rbs/ast/ruby/members.rb +213 -0
  41. data/lib/rbs/buffer.rb +104 -24
  42. data/lib/rbs/cli/validate.rb +39 -34
  43. data/lib/rbs/cli.rb +4 -5
  44. data/lib/rbs/definition.rb +6 -1
  45. data/lib/rbs/definition_builder/ancestor_builder.rb +63 -60
  46. data/lib/rbs/definition_builder/method_builder.rb +45 -30
  47. data/lib/rbs/definition_builder.rb +44 -9
  48. data/lib/rbs/environment/class_entry.rb +69 -0
  49. data/lib/rbs/environment/module_entry.rb +66 -0
  50. data/lib/rbs/environment.rb +185 -154
  51. data/lib/rbs/environment_loader.rb +2 -2
  52. data/lib/rbs/errors.rb +4 -3
  53. data/lib/rbs/inline_parser/comment_association.rb +117 -0
  54. data/lib/rbs/inline_parser.rb +206 -0
  55. data/lib/rbs/location_aux.rb +35 -3
  56. data/lib/rbs/parser_aux.rb +11 -1
  57. data/lib/rbs/prototype/runtime.rb +2 -2
  58. data/lib/rbs/source.rb +99 -0
  59. data/lib/rbs/subtractor.rb +4 -3
  60. data/lib/rbs/version.rb +1 -1
  61. data/lib/rbs.rb +12 -0
  62. data/lib/rdoc/discover.rb +1 -1
  63. data/lib/rdoc_plugin/parser.rb +2 -2
  64. data/rbs.gemspec +1 -0
  65. data/sig/ancestor_builder.rbs +1 -1
  66. data/sig/annotate/formatter.rbs +2 -2
  67. data/sig/annotate/rdoc_annotater.rbs +1 -1
  68. data/sig/ast/ruby/annotations.rbs +110 -0
  69. data/sig/ast/ruby/comment_block.rbs +119 -0
  70. data/sig/ast/ruby/declarations.rbs +60 -0
  71. data/sig/ast/ruby/helpers/constant_helper.rbs +11 -0
  72. data/sig/ast/ruby/helpers/location_helper.rbs +15 -0
  73. data/sig/ast/ruby/members.rbs +72 -0
  74. data/sig/buffer.rbs +63 -5
  75. data/sig/definition.rbs +1 -0
  76. data/sig/definition_builder.rbs +1 -1
  77. data/sig/environment/class_entry.rbs +50 -0
  78. data/sig/environment/module_entry.rbs +50 -0
  79. data/sig/environment.rbs +22 -76
  80. data/sig/errors.rbs +13 -6
  81. data/sig/inline_parser/comment_association.rbs +71 -0
  82. data/sig/inline_parser.rbs +87 -0
  83. data/sig/location.rbs +32 -7
  84. data/sig/method_builder.rbs +7 -4
  85. data/sig/parser.rbs +16 -0
  86. data/sig/source.rbs +48 -0
  87. data/src/ast.c +1345 -0
  88. data/src/lexer.c +2867 -0
  89. data/src/lexer.re +151 -0
  90. data/{ext/rbs_extension → src}/lexstate.c +58 -42
  91. data/src/location.c +71 -0
  92. data/src/parser.c +3739 -0
  93. data/src/string.c +89 -0
  94. data/src/util/rbs_allocator.c +149 -0
  95. data/src/util/rbs_assert.c +19 -0
  96. data/src/util/rbs_buffer.c +54 -0
  97. data/src/util/rbs_constant_pool.c +13 -81
  98. data/src/util/rbs_encoding.c +5273 -0
  99. data/src/util/rbs_unescape.c +130 -0
  100. data/stdlib/rdoc/0/code_object.rbs +2 -2
  101. data/stdlib/rdoc/0/comment.rbs +2 -0
  102. data/stdlib/rdoc/0/options.rbs +76 -0
  103. data/stdlib/rdoc/0/rdoc.rbs +6 -4
  104. data/stdlib/rdoc/0/store.rbs +1 -1
  105. metadata +70 -17
  106. data/ext/rbs_extension/lexer.c +0 -2728
  107. data/ext/rbs_extension/lexer.re +0 -147
  108. data/ext/rbs_extension/location.h +0 -85
  109. data/ext/rbs_extension/parser.c +0 -2982
  110. data/ext/rbs_extension/parser.h +0 -18
  111. data/ext/rbs_extension/parserstate.c +0 -411
  112. data/ext/rbs_extension/parserstate.h +0 -163
  113. data/ext/rbs_extension/unescape.c +0 -32
  114. data/include/rbs/ruby_objs.h +0 -72
  115. data/src/ruby_objs.c +0 -799
@@ -0,0 +1,280 @@
1
+ /**
2
+ * @file encoding.h
3
+ *
4
+ * The encoding interface and implementations used by the parser.
5
+ */
6
+ #ifndef RBS_RBS_ENCODING_H
7
+ #define RBS_RBS_ENCODING_H
8
+
9
+ #include <assert.h>
10
+ #include <stdbool.h>
11
+ #include <stddef.h>
12
+ #include <stdint.h>
13
+
14
+ /**
15
+ * This struct defines the functions necessary to implement the encoding
16
+ * interface so we can determine how many bytes the subsequent character takes.
17
+ * Each callback should return the number of bytes, or 0 if the next bytes are
18
+ * invalid for the encoding and type.
19
+ */
20
+ typedef struct {
21
+ /**
22
+ * Return the number of bytes that the next character takes if it is valid
23
+ * in the encoding. Does not read more than n bytes. It is assumed that n is
24
+ * at least 1.
25
+ */
26
+ size_t (*char_width)(const uint8_t *b, ptrdiff_t n);
27
+
28
+ /**
29
+ * Return the number of bytes that the next character takes if it is valid
30
+ * in the encoding and is alphabetical. Does not read more than n bytes. It
31
+ * is assumed that n is at least 1.
32
+ */
33
+ size_t (*alpha_char)(const uint8_t *b, ptrdiff_t n);
34
+
35
+ /**
36
+ * Return the number of bytes that the next character takes if it is valid
37
+ * in the encoding and is alphanumeric. Does not read more than n bytes. It
38
+ * is assumed that n is at least 1.
39
+ */
40
+ size_t (*alnum_char)(const uint8_t *b, ptrdiff_t n);
41
+
42
+ /**
43
+ * Return true if the next character is valid in the encoding and is an
44
+ * uppercase character. Does not read more than n bytes. It is assumed that
45
+ * n is at least 1.
46
+ */
47
+ bool (*isupper_char)(const uint8_t *b, ptrdiff_t n);
48
+
49
+ /**
50
+ * The name of the encoding. This should correspond to a value that can be
51
+ * passed to Encoding.find in Ruby.
52
+ */
53
+ const char *name;
54
+
55
+ /**
56
+ * Return true if the encoding is a multibyte encoding.
57
+ */
58
+ bool multibyte;
59
+ } rbs_encoding_t;
60
+
61
+ /**
62
+ * All of the lookup tables use the first bit of each embedded byte to indicate
63
+ * whether the codepoint is alphabetical.
64
+ */
65
+ #define RBS_ENCODING_ALPHABETIC_BIT 1 << 0
66
+
67
+ /**
68
+ * All of the lookup tables use the second bit of each embedded byte to indicate
69
+ * whether the codepoint is alphanumeric.
70
+ */
71
+ #define RBS_ENCODING_ALPHANUMERIC_BIT 1 << 1
72
+
73
+ /**
74
+ * All of the lookup tables use the third bit of each embedded byte to indicate
75
+ * whether the codepoint is uppercase.
76
+ */
77
+ #define RBS_ENCODING_UPPERCASE_BIT 1 << 2
78
+
79
+ /**
80
+ * Return the size of the next character in the UTF-8 encoding.
81
+ *
82
+ * @param b The bytes to read.
83
+ * @param n The number of bytes that can be read.
84
+ * @returns The number of bytes that the next character takes if it is valid in
85
+ * the encoding, or 0 if it is not.
86
+ */
87
+ size_t rbs_encoding_utf_8_char_width(const uint8_t *b, ptrdiff_t n);
88
+
89
+ /**
90
+ * Return the size of the next character in the UTF-8 encoding if it is an
91
+ * alphabetical character.
92
+ *
93
+ * @param b The bytes to read.
94
+ * @param n The number of bytes that can be read.
95
+ * @returns The number of bytes that the next character takes if it is valid in
96
+ * the encoding, or 0 if it is not.
97
+ */
98
+ size_t rbs_encoding_utf_8_alpha_char(const uint8_t *b, ptrdiff_t n);
99
+
100
+ /**
101
+ * Return the size of the next character in the UTF-8 encoding if it is an
102
+ * alphanumeric character.
103
+ *
104
+ * @param b The bytes to read.
105
+ * @param n The number of bytes that can be read.
106
+ * @returns The number of bytes that the next character takes if it is valid in
107
+ * the encoding, or 0 if it is not.
108
+ */
109
+ size_t rbs_encoding_utf_8_alnum_char(const uint8_t *b, ptrdiff_t n);
110
+
111
+ /**
112
+ * Return true if the next character in the UTF-8 encoding if it is an uppercase
113
+ * character.
114
+ *
115
+ * @param b The bytes to read.
116
+ * @param n The number of bytes that can be read.
117
+ * @returns True if the next character is valid in the encoding and is an
118
+ * uppercase character, or false if it is not.
119
+ */
120
+ bool rbs_encoding_utf_8_isupper_char(const uint8_t *b, ptrdiff_t n);
121
+
122
+ /**
123
+ * This lookup table is referenced in both the UTF-8 encoding file and the
124
+ * parser directly in order to speed up the default encoding processing. It is
125
+ * used to indicate whether a character is alphabetical, alphanumeric, or
126
+ * uppercase in unicode mappings.
127
+ */
128
+ extern const uint8_t rbs_encoding_unicode_table[256];
129
+
130
+ /**
131
+ * These are all of the encodings that prism supports.
132
+ */
133
+ typedef enum {
134
+ RBS_ENCODING_UTF_8 = 0,
135
+ RBS_ENCODING_US_ASCII,
136
+ RBS_ENCODING_ASCII_8BIT,
137
+ RBS_ENCODING_EUC_JP,
138
+ RBS_ENCODING_WINDOWS_31J,
139
+
140
+ // We optionally support excluding the full set of encodings to only support the
141
+ // minimum necessary to process Ruby code without encoding comments.
142
+ #ifndef RBS_ENCODING_EXCLUDE_FULL
143
+ RBS_ENCODING_BIG5,
144
+ RBS_ENCODING_BIG5_HKSCS,
145
+ RBS_ENCODING_BIG5_UAO,
146
+ RBS_ENCODING_CESU_8,
147
+ RBS_ENCODING_CP51932,
148
+ RBS_ENCODING_CP850,
149
+ RBS_ENCODING_CP852,
150
+ RBS_ENCODING_CP855,
151
+ RBS_ENCODING_CP949,
152
+ RBS_ENCODING_CP950,
153
+ RBS_ENCODING_CP951,
154
+ RBS_ENCODING_EMACS_MULE,
155
+ RBS_ENCODING_EUC_JP_MS,
156
+ RBS_ENCODING_EUC_JIS_2004,
157
+ RBS_ENCODING_EUC_KR,
158
+ RBS_ENCODING_EUC_TW,
159
+ RBS_ENCODING_GB12345,
160
+ RBS_ENCODING_GB18030,
161
+ RBS_ENCODING_GB1988,
162
+ RBS_ENCODING_GB2312,
163
+ RBS_ENCODING_GBK,
164
+ RBS_ENCODING_IBM437,
165
+ RBS_ENCODING_IBM720,
166
+ RBS_ENCODING_IBM737,
167
+ RBS_ENCODING_IBM775,
168
+ RBS_ENCODING_IBM852,
169
+ RBS_ENCODING_IBM855,
170
+ RBS_ENCODING_IBM857,
171
+ RBS_ENCODING_IBM860,
172
+ RBS_ENCODING_IBM861,
173
+ RBS_ENCODING_IBM862,
174
+ RBS_ENCODING_IBM863,
175
+ RBS_ENCODING_IBM864,
176
+ RBS_ENCODING_IBM865,
177
+ RBS_ENCODING_IBM866,
178
+ RBS_ENCODING_IBM869,
179
+ RBS_ENCODING_ISO_8859_1,
180
+ RBS_ENCODING_ISO_8859_2,
181
+ RBS_ENCODING_ISO_8859_3,
182
+ RBS_ENCODING_ISO_8859_4,
183
+ RBS_ENCODING_ISO_8859_5,
184
+ RBS_ENCODING_ISO_8859_6,
185
+ RBS_ENCODING_ISO_8859_7,
186
+ RBS_ENCODING_ISO_8859_8,
187
+ RBS_ENCODING_ISO_8859_9,
188
+ RBS_ENCODING_ISO_8859_10,
189
+ RBS_ENCODING_ISO_8859_11,
190
+ RBS_ENCODING_ISO_8859_13,
191
+ RBS_ENCODING_ISO_8859_14,
192
+ RBS_ENCODING_ISO_8859_15,
193
+ RBS_ENCODING_ISO_8859_16,
194
+ RBS_ENCODING_KOI8_R,
195
+ RBS_ENCODING_KOI8_U,
196
+ RBS_ENCODING_MAC_CENT_EURO,
197
+ RBS_ENCODING_MAC_CROATIAN,
198
+ RBS_ENCODING_MAC_CYRILLIC,
199
+ RBS_ENCODING_MAC_GREEK,
200
+ RBS_ENCODING_MAC_ICELAND,
201
+ RBS_ENCODING_MAC_JAPANESE,
202
+ RBS_ENCODING_MAC_ROMAN,
203
+ RBS_ENCODING_MAC_ROMANIA,
204
+ RBS_ENCODING_MAC_THAI,
205
+ RBS_ENCODING_MAC_TURKISH,
206
+ RBS_ENCODING_MAC_UKRAINE,
207
+ RBS_ENCODING_SHIFT_JIS,
208
+ RBS_ENCODING_SJIS_DOCOMO,
209
+ RBS_ENCODING_SJIS_KDDI,
210
+ RBS_ENCODING_SJIS_SOFTBANK,
211
+ RBS_ENCODING_STATELESS_ISO_2022_JP,
212
+ RBS_ENCODING_STATELESS_ISO_2022_JP_KDDI,
213
+ RBS_ENCODING_TIS_620,
214
+ RBS_ENCODING_UTF8_MAC,
215
+ RBS_ENCODING_UTF8_DOCOMO,
216
+ RBS_ENCODING_UTF8_KDDI,
217
+ RBS_ENCODING_UTF8_SOFTBANK,
218
+ RBS_ENCODING_WINDOWS_1250,
219
+ RBS_ENCODING_WINDOWS_1251,
220
+ RBS_ENCODING_WINDOWS_1252,
221
+ RBS_ENCODING_WINDOWS_1253,
222
+ RBS_ENCODING_WINDOWS_1254,
223
+ RBS_ENCODING_WINDOWS_1255,
224
+ RBS_ENCODING_WINDOWS_1256,
225
+ RBS_ENCODING_WINDOWS_1257,
226
+ RBS_ENCODING_WINDOWS_1258,
227
+ RBS_ENCODING_WINDOWS_874,
228
+ #endif
229
+
230
+ RBS_ENCODING_MAXIMUM
231
+ } rbs_encoding_type_t;
232
+
233
+ /**
234
+ * This is the table of all of the encodings that prism supports.
235
+ */
236
+ extern const rbs_encoding_t rbs_encodings[RBS_ENCODING_MAXIMUM];
237
+
238
+ /**
239
+ * This is the default UTF-8 encoding. We need a reference to it to quickly
240
+ * create parsers.
241
+ */
242
+ #define RBS_ENCODING_UTF_8_ENTRY (&rbs_encodings[RBS_ENCODING_UTF_8])
243
+
244
+ /**
245
+ * This is the US-ASCII encoding. We need a reference to it to be able to
246
+ * compare against it when a string is being created because it could possibly
247
+ * need to fall back to ASCII-8BIT.
248
+ */
249
+ #define RBS_ENCODING_US_ASCII_ENTRY (&rbs_encodings[RBS_ENCODING_US_ASCII])
250
+
251
+ /**
252
+ * This is the ASCII-8BIT encoding. We need a reference to it so that rbs_strpbrk
253
+ * can compare against it because invalid multibyte characters are not a thing
254
+ * in this encoding. It is also needed for handling Regexp encoding flags.
255
+ */
256
+ #define RBS_ENCODING_ASCII_8BIT_ENTRY (&rbs_encodings[RBS_ENCODING_ASCII_8BIT])
257
+
258
+ /**
259
+ * This is the EUC-JP encoding. We need a reference to it to quickly process
260
+ * regular expression modifiers.
261
+ */
262
+ #define RBS_ENCODING_EUC_JP_ENTRY (&rbs_encodings[RBS_ENCODING_EUC_JP])
263
+
264
+ /**
265
+ * This is the Windows-31J encoding. We need a reference to it to quickly
266
+ * process regular expression modifiers.
267
+ */
268
+ #define RBS_ENCODING_WINDOWS_31J_ENTRY (&rbs_encodings[RBS_ENCODING_WINDOWS_31J])
269
+
270
+ /**
271
+ * Parse the given name of an encoding and return a pointer to the corresponding
272
+ * encoding struct if one can be found, otherwise return NULL.
273
+ *
274
+ * @param start A pointer to the first byte of the name.
275
+ * @param end A pointer to the last byte of the name.
276
+ * @returns A pointer to the encoding struct if one is found, otherwise NULL.
277
+ */
278
+ const rbs_encoding_t * rbs_encoding_find(const uint8_t *start, const uint8_t *end);
279
+
280
+ #endif
@@ -0,0 +1,23 @@
1
+ #ifndef RBS_RBS_UNESCAPE_H
2
+ #define RBS_RBS_UNESCAPE_H
3
+
4
+ #include <stddef.h>
5
+ #include "rbs/util/rbs_allocator.h"
6
+ #include "rbs/string.h"
7
+
8
+ /**
9
+ * Receives `rbs_parser_t` and `range`, which represents a string token or symbol token, and returns a string VALUE.
10
+ *
11
+ * Input token | Output string
12
+ * ------------+-------------
13
+ * "foo\\n" | foo\n
14
+ * 'foo' | foo
15
+ * `bar` | bar
16
+ * :"baz\\t" | baz\t
17
+ * :'baz' | baz
18
+ *
19
+ * @returns A new owned string that will be freed when the allocator is freed.
20
+ * */
21
+ rbs_string_t rbs_unquote_string(rbs_allocator_t *, const rbs_string_t input);
22
+
23
+ #endif // RBS_RBS_UNESCAPE_H
data/include/rbs.h CHANGED
@@ -1,7 +1,6 @@
1
1
  #ifndef RBS_H
2
2
  #define RBS_H
3
3
 
4
- #include "rbs/constants.h"
5
- #include "rbs/ruby_objs.h"
4
+ #include "rbs/parser.h"
6
5
 
7
6
  #endif
@@ -59,20 +59,10 @@ module RBS
59
59
 
60
60
  def self.each_part(doc, &block)
61
61
  if block
62
- document =
63
- case doc
64
- when String
65
- raise
66
- when RDoc::Comment
67
- document = doc.parse
68
- when RDoc::Markup::Document
69
- document = doc
70
- end
71
-
72
- if document.file
73
- yield document
62
+ if doc.file
63
+ yield doc
74
64
  else
75
- document.each do |d|
65
+ doc.each do |d|
76
66
  each_part(d, &block)
77
67
  end
78
68
  end
@@ -39,7 +39,9 @@ module RBS
39
39
  def each_part(subjects, tester:)
40
40
  if block_given?
41
41
  subjects.each do |subject, docs|
42
- Formatter.each_part(subject.comment) do |doc|
42
+ comment = subject.comment
43
+ raise if comment.is_a?(String)
44
+ Formatter.each_part(comment.parse) do |doc|
43
45
  if tester.test_path(doc.file || raise)
44
46
  yield [doc, subject]
45
47
  end
@@ -23,7 +23,7 @@ module RBS
23
23
  @stores.clear()
24
24
 
25
25
  RDoc::RI::Paths.each(with_system_dir, with_site_dir, with_home_dir, with_gems_dir ? :latest : false, *extra_dirs.map(&:to_s)) do |path, type|
26
- store = RDoc::Store.new(path, type)
26
+ store = RDoc::Store.new(RDoc::Options.new, path:, type:)
27
27
  store.load_all
28
28
 
29
29
  @stores << store
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBS
4
+ module AST
5
+ module Ruby
6
+ module Annotations
7
+ class Base
8
+ attr_reader :location, :prefix_location
9
+
10
+ def initialize(location, prefix_location)
11
+ @location = location
12
+ @prefix_location = prefix_location
13
+ end
14
+
15
+ def buffer
16
+ location.buffer
17
+ end
18
+ end
19
+
20
+ class NodeTypeAssertion < Base
21
+ attr_reader :type
22
+
23
+ def initialize(location:, prefix_location:, type:)
24
+ super(location, prefix_location)
25
+ @type = type
26
+ end
27
+
28
+ def map_type_name
29
+ self.class.new(
30
+ location:, prefix_location:,
31
+ type: type.map_type_name { yield _1 }
32
+ ) #: self
33
+ end
34
+ end
35
+
36
+ class ColonMethodTypeAnnotation < Base
37
+ attr_reader :annotations, :method_type
38
+
39
+ def initialize(location:, prefix_location:, annotations:, method_type:)
40
+ super(location, prefix_location)
41
+ @annotations = annotations
42
+ @method_type = method_type
43
+ end
44
+
45
+ def map_type_name
46
+ self.class.new(
47
+ location:,
48
+ prefix_location:,
49
+ annotations: annotations,
50
+ method_type: method_type.map_type {|type| type.map_type_name { yield _1 }}
51
+ ) #: self
52
+ end
53
+ end
54
+
55
+ class MethodTypesAnnotation < Base
56
+ Overload = AST::Members::MethodDefinition::Overload
57
+
58
+ attr_reader :overloads, :vertical_bar_locations
59
+
60
+ def initialize(location:, prefix_location:, overloads:, vertical_bar_locations:)
61
+ super(location, prefix_location)
62
+ @overloads = overloads
63
+ @vertical_bar_locations = vertical_bar_locations
64
+ end
65
+
66
+ def map_type_name(&block)
67
+ ovs = overloads.map do |overload|
68
+ Overload.new(
69
+ method_type: overload.method_type.map_type {|type| type.map_type_name { yield _1 } },
70
+ annotations: overload.annotations
71
+ )
72
+ end
73
+
74
+ self.class.new(location:, prefix_location:, overloads: ovs, vertical_bar_locations:) #: self
75
+ end
76
+ end
77
+
78
+ class SkipAnnotation < Base
79
+ attr_reader :skip_location, :comment_location
80
+
81
+ def initialize(location:, prefix_location:, skip_location:, comment_location:)
82
+ super(location, prefix_location)
83
+ @skip_location = skip_location
84
+ @comment_location = comment_location
85
+ end
86
+ end
87
+
88
+ class ReturnTypeAnnotation < Base
89
+ attr_reader :return_location
90
+
91
+ attr_reader :colon_location
92
+
93
+ attr_reader :return_type
94
+
95
+ attr_reader :comment_location
96
+
97
+ def initialize(location:, prefix_location:, return_location:, colon_location:, return_type:, comment_location:)
98
+ super(location, prefix_location)
99
+ @return_location = return_location
100
+ @colon_location = colon_location
101
+ @return_type = return_type
102
+ @comment_location = comment_location
103
+ end
104
+
105
+ def map_type_name(&block)
106
+ self.class.new(
107
+ location:,
108
+ prefix_location:,
109
+ return_location: return_location,
110
+ colon_location: colon_location,
111
+ return_type: return_type.map_type_name { yield _1 },
112
+ comment_location: comment_location
113
+ ) #: self
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,221 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBS
4
+ module AST
5
+ module Ruby
6
+ class CommentBlock
7
+ attr_reader :name, :offsets, :comment_buffer
8
+
9
+ def initialize(source_buffer, comments)
10
+ @name = source_buffer.name
11
+
12
+ @offsets = []
13
+
14
+ # Assume the comment starts with a prefix whitespace
15
+ prefix_str = "# "
16
+
17
+ ranges = [] #: Array[Range[Integer]]
18
+
19
+ comments.each do |comment|
20
+ tuple = [comment, 2] #: [Prism::Comment, Integer]
21
+
22
+ unless comment.location.slice.start_with?(prefix_str)
23
+ tuple[1] = 1
24
+ end
25
+
26
+ offsets << tuple
27
+
28
+ start_char = comment.location.start_character_offset + tuple[1]
29
+ end_char = comment.location.end_character_offset
30
+ ranges << (start_char ... end_char)
31
+ end
32
+
33
+ @comment_buffer = source_buffer.sub_buffer(lines: ranges)
34
+ end
35
+
36
+ def leading?
37
+ comment = offsets[0][0] or raise
38
+ comment.location.start_line_slice.index(/\S/) ? false : true
39
+ end
40
+
41
+ def trailing?
42
+ comment = offsets[0][0] or raise
43
+ comment.location.start_line_slice.index(/\S/) ? true : false
44
+ end
45
+
46
+ def start_line
47
+ comments[0].location.start_line
48
+ end
49
+
50
+ def end_line
51
+ comments[-1].location.end_line
52
+ end
53
+
54
+ def line_starts
55
+ offsets.map do |comment, prefix_size|
56
+ comment.location.start_character_offset + prefix_size
57
+ end
58
+ end
59
+
60
+ def self.build(buffer, comments)
61
+ blocks = [] #: Array[CommentBlock]
62
+
63
+ comments = comments.filter {|comment| comment.is_a?(Prism::InlineComment) }
64
+
65
+ until comments.empty?
66
+ block_comments = [] #: Array[Prism::Comment]
67
+
68
+ until comments.empty?
69
+ comment = comments.first or raise
70
+ last_comment = block_comments.last
71
+
72
+ if last_comment
73
+ if last_comment.location.end_line + 1 == comment.location.start_line
74
+ if last_comment.location.start_column == comment.location.start_column
75
+ unless comment.location.start_line_slice.index(/\S/)
76
+ block_comments << comments.shift
77
+ next
78
+ end
79
+ end
80
+ end
81
+
82
+ break
83
+ else
84
+ block_comments << comments.shift
85
+ end
86
+ end
87
+
88
+ unless block_comments.empty?
89
+ blocks << CommentBlock.new(buffer, block_comments.dup)
90
+ end
91
+ end
92
+
93
+ blocks
94
+ end
95
+
96
+ AnnotationSyntaxError = _ = Struct.new(:location, :error)
97
+
98
+ def each_paragraph(variables, &block)
99
+ if block
100
+ if leading_annotation?(0)
101
+ yield_annotation(0, 0, 0, variables, &block)
102
+ else
103
+ yield_paragraph(0, 0, variables, &block)
104
+ end
105
+ else
106
+ enum_for :each_paragraph, variables
107
+ end
108
+ end
109
+
110
+ def yield_paragraph(start_line, current_line, variables, &block)
111
+ # We already know at start_line..current_line are paragraph.
112
+
113
+ while true
114
+ next_line = current_line + 1
115
+
116
+ if next_line >= comment_buffer.line_count
117
+ yield line_location(start_line, current_line)
118
+ return
119
+ end
120
+
121
+ if leading_annotation?(next_line)
122
+ yield line_location(start_line, current_line)
123
+ return yield_annotation(next_line, next_line, next_line, variables, &block)
124
+ else
125
+ current_line = next_line
126
+ end
127
+ end
128
+ end
129
+
130
+ def yield_annotation(start_line, end_line, current_line, variables, &block)
131
+ # We already know at start_line..end_line are annotation.
132
+ while true
133
+ next_line = current_line + 1
134
+
135
+ if next_line >= comment_buffer.line_count
136
+ annotation = parse_annotation_lines(start_line, end_line, variables)
137
+ yield annotation
138
+
139
+ if end_line > current_line
140
+ yield_paragraph(end_line + 1, end_line + 1, variables, &block)
141
+ end
142
+
143
+ return
144
+ end
145
+
146
+ line_text = text(next_line)
147
+ if leading_spaces = line_text.index(/\S/)
148
+ if leading_spaces == 0
149
+ # End of annotation
150
+ yield parse_annotation_lines(start_line, end_line, variables)
151
+
152
+ if leading_annotation?(end_line + 1)
153
+ yield_annotation(end_line + 1, end_line + 1, end_line + 1, variables, &block)
154
+ else
155
+ yield_paragraph(end_line + 1, end_line + 1, variables, &block)
156
+ end
157
+
158
+ return
159
+ else
160
+ current_line = next_line
161
+ end_line = next_line
162
+ end
163
+ else
164
+ current_line = next_line
165
+ end
166
+ end
167
+ end
168
+
169
+ def text(comment_index)
170
+ range = comment_buffer.ranges[comment_index]
171
+ comment_buffer.content[range] or raise
172
+ end
173
+
174
+ def line_location(start_line, end_line)
175
+ start_offset = comment_buffer.ranges[start_line].begin
176
+ end_offset = comment_buffer.ranges[end_line].end
177
+ Location.new(comment_buffer, start_offset, end_offset)
178
+ end
179
+
180
+ def parse_annotation_lines(start_line, end_line, variables)
181
+ start_pos = comment_buffer.ranges[start_line].begin
182
+ end_pos = comment_buffer.ranges[end_line].end
183
+ begin
184
+ Parser.parse_inline_leading_annotation(comment_buffer, start_pos...end_pos, variables: variables)
185
+ rescue ParsingError => error
186
+ AnnotationSyntaxError.new(line_location(start_line, end_line), error)
187
+ end
188
+ end
189
+
190
+ def trailing_annotation(variables)
191
+ if trailing?
192
+ comment = comments[0] or raise
193
+ if comment.location.slice.start_with?(/#[:\[]/)
194
+ begin
195
+ Parser.parse_inline_trailing_annotation(comment_buffer, 0...comment_buffer.last_position, variables: variables)
196
+ rescue ParsingError => error
197
+ location = line_location(0, offsets.size - 1)
198
+ AnnotationSyntaxError.new(location, error)
199
+ end
200
+ end
201
+ end
202
+ end
203
+
204
+ def comments
205
+ offsets.map { _1[0]}
206
+ end
207
+
208
+ def leading_annotation?(index)
209
+ if index < comment_buffer.line_count
210
+ text(index).start_with?(/@rbs\b/) and return true
211
+
212
+ comment = offsets[index][0]
213
+ comment.location.slice.start_with?(/\#:/) and return true
214
+ end
215
+
216
+ false
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end