rbs 3.10.4 → 4.0.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 (267) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +14 -14
  3. data/.github/workflows/bundle-update.yml +60 -0
  4. data/.github/workflows/c-check.yml +7 -5
  5. data/.github/workflows/comments.yml +2 -2
  6. data/.github/workflows/dependabot.yml +2 -2
  7. data/.github/workflows/ruby.yml +16 -26
  8. data/.github/workflows/rust.yml +95 -0
  9. data/.github/workflows/typecheck.yml +1 -1
  10. data/.github/workflows/windows.yml +2 -2
  11. data/.rubocop.yml +2 -2
  12. data/.vscode/extensions.json +5 -0
  13. data/.vscode/settings.json +19 -0
  14. data/CHANGELOG.md +202 -2
  15. data/Rakefile +9 -23
  16. data/Steepfile +2 -0
  17. data/config.yml +457 -13
  18. data/core/array.rbs +218 -188
  19. data/core/basic_object.rbs +9 -8
  20. data/core/binding.rbs +0 -2
  21. data/core/builtin.rbs +2 -2
  22. data/core/class.rbs +6 -5
  23. data/core/comparable.rbs +45 -31
  24. data/core/complex.rbs +66 -55
  25. data/core/dir.rbs +57 -45
  26. data/core/encoding.rbs +6 -6
  27. data/core/enumerable.rbs +105 -91
  28. data/core/enumerator/arithmetic_sequence.rbs +70 -0
  29. data/core/enumerator.rbs +24 -3
  30. data/core/errno.rbs +3 -2
  31. data/core/errors.rbs +31 -29
  32. data/core/exception.rbs +12 -12
  33. data/core/fiber.rbs +47 -36
  34. data/core/file.rbs +242 -169
  35. data/core/file_test.rbs +2 -2
  36. data/core/float.rbs +42 -68
  37. data/core/gc.rbs +78 -70
  38. data/core/hash.rbs +70 -60
  39. data/core/integer.rbs +32 -75
  40. data/core/io/buffer.rbs +36 -36
  41. data/core/io/wait.rbs +7 -7
  42. data/core/io.rbs +192 -146
  43. data/core/kernel.rbs +198 -147
  44. data/core/marshal.rbs +3 -3
  45. data/core/match_data.rbs +14 -12
  46. data/core/math.rbs +69 -67
  47. data/core/method.rbs +6 -8
  48. data/core/module.rbs +148 -88
  49. data/core/nil_class.rbs +4 -3
  50. data/core/numeric.rbs +53 -50
  51. data/core/object.rbs +6 -8
  52. data/core/object_space.rbs +11 -10
  53. data/core/pathname.rbs +131 -81
  54. data/core/proc.rbs +65 -34
  55. data/core/process.rbs +221 -201
  56. data/core/ractor.rbs +15 -11
  57. data/core/random.rbs +21 -3
  58. data/core/range.rbs +152 -49
  59. data/core/rational.rbs +5 -56
  60. data/core/rbs/unnamed/argf.rbs +58 -51
  61. data/core/rbs/unnamed/env_class.rbs +18 -13
  62. data/core/rbs/unnamed/main_class.rbs +123 -0
  63. data/core/rbs/unnamed/random.rbs +7 -116
  64. data/core/regexp.rbs +236 -197
  65. data/core/ruby.rbs +1 -1
  66. data/core/ruby_vm.rbs +32 -30
  67. data/core/rubygems/config_file.rbs +5 -5
  68. data/core/rubygems/errors.rbs +1 -1
  69. data/core/rubygems/requirement.rbs +5 -5
  70. data/core/rubygems/rubygems.rbs +5 -3
  71. data/core/set.rbs +17 -16
  72. data/core/signal.rbs +2 -2
  73. data/core/string.rbs +318 -298
  74. data/core/struct.rbs +26 -25
  75. data/core/symbol.rbs +25 -24
  76. data/core/thread.rbs +40 -41
  77. data/core/time.rbs +47 -42
  78. data/core/trace_point.rbs +34 -31
  79. data/core/true_class.rbs +2 -2
  80. data/core/unbound_method.rbs +10 -10
  81. data/core/warning.rbs +7 -7
  82. data/docs/collection.md +1 -1
  83. data/docs/config.md +171 -0
  84. data/docs/inline.md +576 -0
  85. data/docs/syntax.md +46 -16
  86. data/docs/type_fingerprint.md +21 -0
  87. data/exe/rbs +1 -1
  88. data/ext/rbs_extension/ast_translation.c +595 -98
  89. data/ext/rbs_extension/class_constants.c +30 -0
  90. data/ext/rbs_extension/class_constants.h +15 -0
  91. data/ext/rbs_extension/legacy_location.c +30 -53
  92. data/ext/rbs_extension/legacy_location.h +37 -0
  93. data/ext/rbs_extension/main.c +125 -24
  94. data/include/rbs/ast.h +485 -150
  95. data/include/rbs/lexer.h +11 -4
  96. data/include/rbs/location.h +25 -44
  97. data/include/rbs/parser.h +20 -2
  98. data/include/rbs/util/rbs_constant_pool.h +0 -3
  99. data/include/rbs.h +8 -0
  100. data/lib/rbs/ast/annotation.rb +1 -1
  101. data/lib/rbs/ast/comment.rb +1 -1
  102. data/lib/rbs/ast/declarations.rb +10 -10
  103. data/lib/rbs/ast/members.rb +14 -14
  104. data/lib/rbs/ast/ruby/annotations.rb +409 -0
  105. data/lib/rbs/ast/ruby/comment_block.rb +245 -0
  106. data/lib/rbs/ast/ruby/declarations.rb +281 -0
  107. data/lib/rbs/ast/ruby/helpers/constant_helper.rb +28 -0
  108. data/lib/rbs/ast/ruby/helpers/location_helper.rb +15 -0
  109. data/lib/rbs/ast/ruby/members.rb +723 -0
  110. data/lib/rbs/ast/type_param.rb +24 -4
  111. data/lib/rbs/buffer.rb +105 -20
  112. data/lib/rbs/cli/diff.rb +16 -15
  113. data/lib/rbs/cli/validate.rb +62 -125
  114. data/lib/rbs/cli.rb +55 -23
  115. data/lib/rbs/collection/config/lockfile_generator.rb +8 -4
  116. data/lib/rbs/collection/sources/git.rb +1 -0
  117. data/lib/rbs/collection.rb +0 -1
  118. data/lib/rbs/definition.rb +6 -1
  119. data/lib/rbs/definition_builder/ancestor_builder.rb +119 -63
  120. data/lib/rbs/definition_builder/method_builder.rb +65 -30
  121. data/lib/rbs/definition_builder.rb +177 -20
  122. data/lib/rbs/diff.rb +7 -1
  123. data/lib/rbs/environment/class_entry.rb +69 -0
  124. data/lib/rbs/environment/module_entry.rb +66 -0
  125. data/lib/rbs/environment.rb +338 -155
  126. data/lib/rbs/environment_loader.rb +2 -2
  127. data/lib/rbs/errors.rb +30 -20
  128. data/lib/rbs/inline_parser/comment_association.rb +117 -0
  129. data/lib/rbs/inline_parser.rb +542 -0
  130. data/lib/rbs/location_aux.rb +36 -4
  131. data/lib/rbs/locator.rb +5 -1
  132. data/lib/rbs/method_type.rb +5 -3
  133. data/lib/rbs/namespace.rb +0 -7
  134. data/lib/rbs/parser_aux.rb +31 -8
  135. data/lib/rbs/prototype/helpers.rb +57 -0
  136. data/lib/rbs/prototype/rb.rb +3 -28
  137. data/lib/rbs/prototype/rbi.rb +3 -20
  138. data/lib/rbs/prototype/runtime.rb +10 -2
  139. data/lib/rbs/resolver/type_name_resolver.rb +0 -8
  140. data/lib/rbs/source.rb +99 -0
  141. data/lib/rbs/subtractor.rb +4 -3
  142. data/lib/rbs/test/type_check.rb +5 -2
  143. data/lib/rbs/type_name.rb +1 -8
  144. data/lib/rbs/types.rb +88 -78
  145. data/lib/rbs/unit_test/convertibles.rb +1 -0
  146. data/lib/rbs/unit_test/type_assertions.rb +35 -8
  147. data/lib/rbs/validator.rb +2 -2
  148. data/lib/rbs/version.rb +1 -1
  149. data/lib/rbs.rb +12 -1
  150. data/rbs.gemspec +3 -2
  151. data/rust/.gitignore +1 -0
  152. data/rust/Cargo.lock +378 -0
  153. data/rust/Cargo.toml +7 -0
  154. data/rust/ruby-rbs/Cargo.toml +22 -0
  155. data/rust/ruby-rbs/build.rs +764 -0
  156. data/rust/ruby-rbs/examples/locations.rs +60 -0
  157. data/rust/ruby-rbs/src/lib.rs +1 -0
  158. data/rust/ruby-rbs/src/node/mod.rs +742 -0
  159. data/rust/ruby-rbs/tests/sanity.rs +47 -0
  160. data/rust/ruby-rbs/vendor/rbs/config.yml +1 -0
  161. data/rust/ruby-rbs-sys/Cargo.toml +23 -0
  162. data/rust/ruby-rbs-sys/build.rs +204 -0
  163. data/rust/ruby-rbs-sys/src/lib.rs +50 -0
  164. data/rust/ruby-rbs-sys/vendor/rbs/include +1 -0
  165. data/rust/ruby-rbs-sys/vendor/rbs/src +1 -0
  166. data/rust/ruby-rbs-sys/wrapper.h +1 -0
  167. data/schema/typeParam.json +17 -1
  168. data/sig/ancestor_builder.rbs +1 -1
  169. data/sig/ast/ruby/annotations.rbs +421 -0
  170. data/sig/ast/ruby/comment_block.rbs +127 -0
  171. data/sig/ast/ruby/declarations.rbs +158 -0
  172. data/sig/ast/ruby/helpers/constant_helper.rbs +11 -0
  173. data/sig/ast/ruby/helpers/location_helper.rbs +15 -0
  174. data/sig/ast/ruby/members.rbs +178 -0
  175. data/sig/buffer.rbs +63 -5
  176. data/sig/cli/diff.rbs +5 -11
  177. data/sig/cli/validate.rbs +12 -8
  178. data/sig/cli.rbs +18 -18
  179. data/sig/definition.rbs +6 -0
  180. data/sig/definition_builder.rbs +3 -1
  181. data/sig/environment/class_entry.rbs +50 -0
  182. data/sig/environment/module_entry.rbs +50 -0
  183. data/sig/environment.rbs +37 -81
  184. data/sig/errors.rbs +26 -20
  185. data/sig/inline_parser/comment_association.rbs +71 -0
  186. data/sig/inline_parser.rbs +124 -0
  187. data/sig/location.rbs +32 -7
  188. data/sig/locator.rbs +0 -2
  189. data/sig/method_builder.rbs +9 -4
  190. data/sig/namespace.rbs +0 -5
  191. data/sig/parser.rbs +47 -13
  192. data/sig/prototype/helpers.rbs +2 -0
  193. data/sig/resolver/type_name_resolver.rbs +0 -3
  194. data/sig/source.rbs +48 -0
  195. data/sig/type_param.rbs +13 -8
  196. data/sig/typename.rbs +0 -5
  197. data/sig/types.rbs +6 -7
  198. data/sig/unit_test/spy.rbs +0 -8
  199. data/sig/unit_test/type_assertions.rbs +11 -0
  200. data/src/ast.c +491 -143
  201. data/src/lexer.c +1552 -1314
  202. data/src/lexer.re +7 -0
  203. data/src/lexstate.c +8 -1
  204. data/src/location.c +8 -48
  205. data/src/parser.c +1107 -409
  206. data/src/util/rbs_constant_pool.c +0 -4
  207. data/stdlib/bigdecimal/0/big_decimal.rbs +16 -16
  208. data/stdlib/cgi-escape/0/escape.rbs +4 -4
  209. data/stdlib/coverage/0/coverage.rbs +4 -3
  210. data/stdlib/date/0/date.rbs +33 -28
  211. data/stdlib/date/0/date_time.rbs +24 -23
  212. data/stdlib/did_you_mean/0/did_you_mean.rbs +17 -16
  213. data/stdlib/digest/0/digest.rbs +110 -0
  214. data/stdlib/erb/0/erb.rbs +64 -53
  215. data/stdlib/etc/0/etc.rbs +55 -50
  216. data/stdlib/fileutils/0/fileutils.rbs +140 -126
  217. data/stdlib/forwardable/0/forwardable.rbs +10 -10
  218. data/stdlib/io-console/0/io-console.rbs +2 -2
  219. data/stdlib/json/0/json.rbs +158 -131
  220. data/stdlib/monitor/0/monitor.rbs +3 -3
  221. data/stdlib/net-http/0/net-http.rbs +159 -134
  222. data/stdlib/objspace/0/objspace.rbs +8 -30
  223. data/stdlib/open-uri/0/open-uri.rbs +8 -8
  224. data/stdlib/open3/0/open3.rbs +469 -10
  225. data/stdlib/openssl/0/openssl.rbs +144 -129
  226. data/stdlib/optparse/0/optparse.rbs +23 -14
  227. data/stdlib/pathname/0/pathname.rbs +2 -2
  228. data/stdlib/pp/0/pp.rbs +9 -8
  229. data/stdlib/prettyprint/0/prettyprint.rbs +7 -7
  230. data/stdlib/pstore/0/pstore.rbs +35 -30
  231. data/stdlib/psych/0/psych.rbs +62 -9
  232. data/stdlib/psych/0/store.rbs +2 -4
  233. data/stdlib/pty/0/pty.rbs +9 -6
  234. data/stdlib/random-formatter/0/random-formatter.rbs +277 -0
  235. data/stdlib/rdoc/0/code_object.rbs +2 -1
  236. data/stdlib/rdoc/0/parser.rbs +1 -1
  237. data/stdlib/rdoc/0/store.rbs +1 -1
  238. data/stdlib/ripper/0/ripper.rbs +20 -17
  239. data/stdlib/securerandom/0/manifest.yaml +2 -0
  240. data/stdlib/securerandom/0/securerandom.rbs +7 -20
  241. data/stdlib/shellwords/0/shellwords.rbs +2 -2
  242. data/stdlib/socket/0/addrinfo.rbs +9 -9
  243. data/stdlib/socket/0/basic_socket.rbs +3 -3
  244. data/stdlib/socket/0/ip_socket.rbs +10 -8
  245. data/stdlib/socket/0/socket.rbs +10 -9
  246. data/stdlib/socket/0/tcp_server.rbs +1 -1
  247. data/stdlib/socket/0/tcp_socket.rbs +1 -1
  248. data/stdlib/socket/0/udp_socket.rbs +1 -1
  249. data/stdlib/socket/0/unix_server.rbs +1 -1
  250. data/stdlib/stringio/0/stringio.rbs +55 -54
  251. data/stdlib/strscan/0/string_scanner.rbs +46 -44
  252. data/stdlib/tempfile/0/tempfile.rbs +24 -20
  253. data/stdlib/time/0/time.rbs +7 -5
  254. data/stdlib/tsort/0/tsort.rbs +7 -6
  255. data/stdlib/uri/0/common.rbs +31 -18
  256. data/stdlib/uri/0/file.rbs +2 -2
  257. data/stdlib/uri/0/generic.rbs +9 -2
  258. data/stdlib/uri/0/http.rbs +2 -2
  259. data/stdlib/uri/0/ldap.rbs +2 -2
  260. data/stdlib/uri/0/mailto.rbs +3 -3
  261. data/stdlib/uri/0/rfc2396_parser.rbs +6 -5
  262. data/stdlib/zlib/0/deflate.rbs +4 -3
  263. data/stdlib/zlib/0/gzip_reader.rbs +6 -6
  264. data/stdlib/zlib/0/gzip_writer.rbs +14 -12
  265. data/stdlib/zlib/0/inflate.rbs +1 -1
  266. data/stdlib/zlib/0/need_dict.rbs +1 -1
  267. metadata +66 -3
@@ -0,0 +1,409 @@
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
+
35
+ def type_fingerprint
36
+ [
37
+ "annots/node_type_assertion",
38
+ type.to_s
39
+ ]
40
+ end
41
+ end
42
+
43
+ class AliasAnnotation < Base
44
+ attr_reader :keyword_location, :type_name_location, :type_name
45
+
46
+ def initialize(location:, prefix_location:, keyword_location:, type_name:, type_name_location:)
47
+ super(location, prefix_location)
48
+ @keyword_location = keyword_location
49
+ @type_name = type_name
50
+ @type_name_location = type_name_location
51
+ end
52
+
53
+ def map_type_name
54
+ self.class.new(
55
+ location:,
56
+ prefix_location:,
57
+ keyword_location:,
58
+ type_name: type_name ? yield(type_name) : nil,
59
+ type_name_location:
60
+ ) #: self
61
+ end
62
+ end
63
+
64
+ class ClassAliasAnnotation < AliasAnnotation
65
+ def type_fingerprint
66
+ [
67
+ "annots/class-alias",
68
+ type_name&.to_s
69
+ ]
70
+ end
71
+ end
72
+
73
+ class ModuleAliasAnnotation < AliasAnnotation
74
+ def type_fingerprint
75
+ [
76
+ "annots/module-alias",
77
+ type_name&.to_s
78
+ ]
79
+ end
80
+ end
81
+
82
+ class ColonMethodTypeAnnotation < Base
83
+ attr_reader :annotations, :method_type
84
+
85
+ def initialize(location:, prefix_location:, annotations:, method_type:)
86
+ super(location, prefix_location)
87
+ @annotations = annotations
88
+ @method_type = method_type
89
+ end
90
+
91
+ def map_type_name
92
+ self.class.new(
93
+ location:,
94
+ prefix_location:,
95
+ annotations: annotations,
96
+ method_type: method_type.map_type {|type| type.map_type_name { yield _1 }}
97
+ ) #: self
98
+ end
99
+
100
+ def type_fingerprint
101
+ [
102
+ "annots/colon_method_type",
103
+ annotations.map(&:to_s),
104
+ method_type.to_s
105
+ ]
106
+ end
107
+ end
108
+
109
+ class MethodTypesAnnotation < Base
110
+ Overload = AST::Members::MethodDefinition::Overload
111
+
112
+ attr_reader :overloads, :vertical_bar_locations, :dot3_location
113
+
114
+ def initialize(location:, prefix_location:, overloads:, vertical_bar_locations:, dot3_location:)
115
+ super(location, prefix_location)
116
+ @overloads = overloads
117
+ @vertical_bar_locations = vertical_bar_locations
118
+ @dot3_location = dot3_location
119
+ end
120
+
121
+ def map_type_name(&block)
122
+ ovs = overloads.map do |overload|
123
+ Overload.new(
124
+ method_type: overload.method_type.map_type {|type| type.map_type_name { yield _1 } },
125
+ annotations: overload.annotations
126
+ )
127
+ end
128
+
129
+ self.class.new(location:, prefix_location:, overloads: ovs, vertical_bar_locations:, dot3_location:) #: self
130
+ end
131
+
132
+ def type_fingerprint
133
+ [
134
+ "annots/method_types",
135
+ overloads.map { |o| [o.annotations.map(&:to_s), o.method_type.to_s] },
136
+ overloading: dot3_location ? true : false
137
+ ]
138
+ end
139
+ end
140
+
141
+ class SkipAnnotation < Base
142
+ attr_reader :skip_location, :comment_location
143
+
144
+ def initialize(location:, prefix_location:, skip_location:, comment_location:)
145
+ super(location, prefix_location)
146
+ @skip_location = skip_location
147
+ @comment_location = comment_location
148
+ end
149
+
150
+ def type_fingerprint
151
+ "annots/skip"
152
+ end
153
+ end
154
+
155
+ class ReturnTypeAnnotation < Base
156
+ attr_reader :return_location
157
+
158
+ attr_reader :colon_location
159
+
160
+ attr_reader :return_type
161
+
162
+ attr_reader :comment_location
163
+
164
+ def initialize(location:, prefix_location:, return_location:, colon_location:, return_type:, comment_location:)
165
+ super(location, prefix_location)
166
+ @return_location = return_location
167
+ @colon_location = colon_location
168
+ @return_type = return_type
169
+ @comment_location = comment_location
170
+ end
171
+
172
+ def map_type_name(&block)
173
+ self.class.new(
174
+ location:,
175
+ prefix_location:,
176
+ return_location: return_location,
177
+ colon_location: colon_location,
178
+ return_type: return_type.map_type_name { yield _1 },
179
+ comment_location: comment_location
180
+ ) #: self
181
+ end
182
+
183
+ def type_fingerprint
184
+ [
185
+ "annots/return_type",
186
+ return_type.to_s,
187
+ comment_location&.source
188
+ ]
189
+ end
190
+ end
191
+
192
+ class TypeApplicationAnnotation < Base
193
+ attr_reader :type_args, :close_bracket_location, :comma_locations
194
+
195
+ def initialize(location:, prefix_location:, type_args:, close_bracket_location:, comma_locations:)
196
+ super(location, prefix_location)
197
+ @type_args = type_args
198
+ @close_bracket_location = close_bracket_location
199
+ @comma_locations = comma_locations
200
+ end
201
+
202
+ def map_type_name(&block)
203
+ mapped_type_args = type_args.map { |type| type.map_type_name { yield _1 } }
204
+
205
+ self.class.new(
206
+ location:,
207
+ prefix_location:,
208
+ type_args: mapped_type_args,
209
+ close_bracket_location:,
210
+ comma_locations:
211
+ ) #: self
212
+ end
213
+
214
+ def type_fingerprint
215
+ [
216
+ "annots/type_application",
217
+ type_args.map(&:to_s)
218
+ ]
219
+ end
220
+ end
221
+
222
+ class InstanceVariableAnnotation < Base
223
+ attr_reader :ivar_name, :ivar_name_location, :colon_location, :type, :comment_location
224
+
225
+ def initialize(location:, prefix_location:, ivar_name:, ivar_name_location:, colon_location:, type:, comment_location:)
226
+ super(location, prefix_location)
227
+ @ivar_name = ivar_name
228
+ @ivar_name_location = ivar_name_location
229
+ @colon_location = colon_location
230
+ @type = type
231
+ @comment_location = comment_location
232
+ end
233
+
234
+ def map_type_name(&block)
235
+ self.class.new(
236
+ location:,
237
+ prefix_location:,
238
+ ivar_name:,
239
+ ivar_name_location:,
240
+ colon_location:,
241
+ type: type.map_type_name { yield _1 },
242
+ comment_location:
243
+ ) #: self
244
+ end
245
+
246
+ def type_fingerprint
247
+ [
248
+ "annots/instance_variable",
249
+ ivar_name.to_s,
250
+ type.to_s,
251
+ comment_location&.source
252
+ ]
253
+ end
254
+ end
255
+
256
+ class ParamTypeAnnotation < Base
257
+ attr_reader :name_location, :colon_location, :param_type, :comment_location
258
+
259
+ def initialize(location:, prefix_location:, name_location:, colon_location:, param_type:, comment_location:)
260
+ super(location, prefix_location)
261
+ @name_location = name_location
262
+ @colon_location = colon_location
263
+ @param_type = param_type
264
+ @comment_location = comment_location
265
+ end
266
+
267
+ def map_type_name(&block)
268
+ self.class.new(
269
+ location:,
270
+ prefix_location:,
271
+ name_location: name_location,
272
+ colon_location: colon_location,
273
+ param_type: param_type.map_type_name { yield _1 },
274
+ comment_location: comment_location
275
+ ) #: self
276
+ end
277
+
278
+ def type_fingerprint
279
+ [
280
+ "annots/param_type",
281
+ name_location.source,
282
+ param_type.to_s,
283
+ comment_location&.source
284
+ ]
285
+ end
286
+ end
287
+
288
+ class SplatParamTypeAnnotation < Base
289
+ attr_reader :star_location, :name_location, :colon_location, :param_type, :comment_location
290
+
291
+ def initialize(location:, prefix_location:, star_location:, name_location:, colon_location:, param_type:, comment_location:)
292
+ super(location, prefix_location)
293
+ @star_location = star_location
294
+ @name_location = name_location
295
+ @colon_location = colon_location
296
+ @param_type = param_type
297
+ @comment_location = comment_location
298
+ end
299
+
300
+ def map_type_name(&block)
301
+ self.class.new(
302
+ location:,
303
+ prefix_location:,
304
+ star_location: star_location,
305
+ name_location: name_location,
306
+ colon_location: colon_location,
307
+ param_type: param_type.map_type_name { yield _1 },
308
+ comment_location: comment_location
309
+ ) #: self
310
+ end
311
+
312
+ def type_fingerprint
313
+ [
314
+ "annots/splat_param_type",
315
+ name_location&.source,
316
+ param_type.to_s,
317
+ comment_location&.source
318
+ ]
319
+ end
320
+ end
321
+
322
+ class DoubleSplatParamTypeAnnotation < Base
323
+ attr_reader :star2_location, :name_location, :colon_location, :param_type, :comment_location
324
+
325
+ def initialize(location:, prefix_location:, star2_location:, name_location:, colon_location:, param_type:, comment_location:)
326
+ super(location, prefix_location)
327
+ @star2_location = star2_location
328
+ @name_location = name_location
329
+ @colon_location = colon_location
330
+ @param_type = param_type
331
+ @comment_location = comment_location
332
+ end
333
+
334
+ def map_type_name(&block)
335
+ self.class.new(
336
+ location:,
337
+ prefix_location:,
338
+ star2_location: star2_location,
339
+ name_location: name_location,
340
+ colon_location: colon_location,
341
+ param_type: param_type.map_type_name { yield _1 },
342
+ comment_location: comment_location
343
+ ) #: self
344
+ end
345
+
346
+ def type_fingerprint
347
+ [
348
+ "annots/double_splat_param_type",
349
+ name_location&.source,
350
+ param_type.to_s,
351
+ comment_location&.source
352
+ ]
353
+ end
354
+ end
355
+
356
+ class BlockParamTypeAnnotation < Base
357
+ attr_reader :ampersand_location, :name_location, :colon_location, :question_location, :type_location, :type, :comment_location
358
+
359
+ def initialize(location:, prefix_location:, ampersand_location:, name_location:, colon_location:, question_location:, type_location:, type:, comment_location:)
360
+ super(location, prefix_location)
361
+ @ampersand_location = ampersand_location
362
+ @name_location = name_location
363
+ @colon_location = colon_location
364
+ @question_location = question_location
365
+ @type_location = type_location
366
+ @type = type
367
+ @comment_location = comment_location
368
+ end
369
+
370
+ def map_type_name(&block)
371
+ self.class.new(
372
+ location:,
373
+ prefix_location:,
374
+ ampersand_location: ampersand_location,
375
+ name_location: name_location,
376
+ colon_location: colon_location,
377
+ question_location: question_location,
378
+ type_location: type_location,
379
+ type: type.map_type_name { yield _1 },
380
+ comment_location: comment_location
381
+ ) #: self
382
+ end
383
+
384
+ def name
385
+ name_location&.source&.to_sym
386
+ end
387
+
388
+ def optional?
389
+ question_location ? true : false
390
+ end
391
+
392
+ def required?
393
+ !optional?
394
+ end
395
+
396
+ def type_fingerprint
397
+ [
398
+ "annots/block_param_type",
399
+ name_location&.source,
400
+ type.to_s,
401
+ optional? ? "optional" : "required",
402
+ comment_location&.source
403
+ ]
404
+ end
405
+ end
406
+ end
407
+ end
408
+ end
409
+ end
@@ -0,0 +1,245 @@
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 location()
181
+ first_comment = comments[0] or raise
182
+ last_comment = comments[-1] or raise
183
+
184
+ comment_buffer.rbs_location(first_comment.location.join last_comment.location)
185
+ end
186
+
187
+ def parse_annotation_lines(start_line, end_line, variables)
188
+ start_pos = comment_buffer.ranges[start_line].begin
189
+ end_pos = comment_buffer.ranges[end_line].end
190
+ begin
191
+ Parser.parse_inline_leading_annotation(comment_buffer, start_pos...end_pos, variables: variables)
192
+ rescue ParsingError => error
193
+ AnnotationSyntaxError.new(line_location(start_line, end_line), error)
194
+ end
195
+ end
196
+
197
+ def trailing_annotation(variables)
198
+ if trailing?
199
+ comment = comments[0] or raise
200
+ if comment.location.slice.start_with?(/#[:\[]/)
201
+ begin
202
+ Parser.parse_inline_trailing_annotation(comment_buffer, 0...comment_buffer.last_position, variables: variables)
203
+ rescue ParsingError => error
204
+ location = line_location(0, offsets.size - 1)
205
+ AnnotationSyntaxError.new(location, error)
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ def comments
212
+ offsets.map { _1[0]}
213
+ end
214
+
215
+ def leading_annotation?(index)
216
+ if index < comment_buffer.line_count
217
+ text(index).start_with?(/@rbs\b/) and return true
218
+
219
+ comment = offsets[index][0]
220
+ comment.location.slice.start_with?(/\#:/) and return true
221
+ end
222
+
223
+ false
224
+ end
225
+
226
+ def as_comment
227
+ lines = [] #: Array[String]
228
+
229
+ each_paragraph([]) do |paragraph|
230
+ case paragraph
231
+ when Location
232
+ lines << paragraph.local_source
233
+ end
234
+ end
235
+
236
+ string = lines.join("\n")
237
+
238
+ unless string.strip.empty?
239
+ AST::Comment.new(string: string, location: location)
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end
245
+ end