rbs 4.0.0.dev.4 → 4.0.0.dev.5

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 (223) 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 +11 -8
  5. data/.github/workflows/comments.yml +3 -3
  6. data/.github/workflows/dependabot.yml +1 -1
  7. data/.github/workflows/ruby.yml +17 -34
  8. data/.github/workflows/typecheck.yml +2 -2
  9. data/.github/workflows/valgrind.yml +42 -0
  10. data/.github/workflows/windows.yml +2 -2
  11. data/.rubocop.yml +1 -1
  12. data/README.md +1 -1
  13. data/Rakefile +32 -5
  14. data/config.yml +46 -0
  15. data/core/array.rbs +96 -46
  16. data/core/binding.rbs +0 -2
  17. data/core/builtin.rbs +2 -2
  18. data/core/comparable.rbs +13 -6
  19. data/core/complex.rbs +55 -41
  20. data/core/dir.rbs +4 -4
  21. data/core/encoding.rbs +7 -10
  22. data/core/enumerable.rbs +90 -3
  23. data/core/enumerator/arithmetic_sequence.rbs +70 -0
  24. data/core/enumerator.rbs +63 -1
  25. data/core/errno.rbs +8 -0
  26. data/core/errors.rbs +28 -1
  27. data/core/exception.rbs +2 -2
  28. data/core/fiber.rbs +40 -20
  29. data/core/file.rbs +108 -78
  30. data/core/file_test.rbs +1 -1
  31. data/core/float.rbs +225 -69
  32. data/core/gc.rbs +417 -281
  33. data/core/hash.rbs +1023 -727
  34. data/core/integer.rbs +104 -110
  35. data/core/io/buffer.rbs +21 -10
  36. data/core/io/wait.rbs +11 -33
  37. data/core/io.rbs +82 -19
  38. data/core/kernel.rbs +70 -59
  39. data/core/marshal.rbs +1 -1
  40. data/core/match_data.rbs +1 -1
  41. data/core/math.rbs +42 -3
  42. data/core/method.rbs +63 -27
  43. data/core/module.rbs +103 -26
  44. data/core/nil_class.rbs +3 -3
  45. data/core/numeric.rbs +43 -35
  46. data/core/object.rbs +3 -3
  47. data/core/object_space.rbs +21 -15
  48. data/core/pathname.rbs +1272 -0
  49. data/core/proc.rbs +30 -25
  50. data/core/process.rbs +4 -2
  51. data/core/ractor.rbs +361 -509
  52. data/core/random.rbs +17 -0
  53. data/core/range.rbs +113 -16
  54. data/core/rational.rbs +56 -85
  55. data/core/rbs/unnamed/argf.rbs +2 -2
  56. data/core/rbs/unnamed/env_class.rbs +1 -1
  57. data/core/rbs/unnamed/random.rbs +4 -113
  58. data/core/regexp.rbs +25 -20
  59. data/core/ruby.rbs +53 -0
  60. data/core/ruby_vm.rbs +6 -4
  61. data/core/rubygems/errors.rbs +3 -70
  62. data/core/rubygems/rubygems.rbs +11 -79
  63. data/core/rubygems/version.rbs +2 -3
  64. data/core/set.rbs +488 -359
  65. data/core/signal.rbs +24 -14
  66. data/core/string.rbs +3171 -1241
  67. data/core/struct.rbs +1 -1
  68. data/core/symbol.rbs +17 -11
  69. data/core/thread.rbs +95 -33
  70. data/core/time.rbs +35 -9
  71. data/core/trace_point.rbs +7 -4
  72. data/core/unbound_method.rbs +14 -6
  73. data/docs/aliases.md +79 -0
  74. data/docs/collection.md +2 -2
  75. data/docs/encoding.md +56 -0
  76. data/docs/gem.md +0 -1
  77. data/docs/inline.md +470 -0
  78. data/docs/sigs.md +3 -3
  79. data/docs/syntax.md +33 -4
  80. data/docs/type_fingerprint.md +21 -0
  81. data/exe/rbs +1 -1
  82. data/ext/rbs_extension/ast_translation.c +77 -3
  83. data/ext/rbs_extension/ast_translation.h +3 -0
  84. data/ext/rbs_extension/class_constants.c +8 -2
  85. data/ext/rbs_extension/class_constants.h +4 -0
  86. data/ext/rbs_extension/extconf.rb +5 -1
  87. data/ext/rbs_extension/legacy_location.c +5 -5
  88. data/ext/rbs_extension/main.c +37 -20
  89. data/include/rbs/ast.h +85 -38
  90. data/include/rbs/defines.h +27 -0
  91. data/include/rbs/lexer.h +30 -11
  92. data/include/rbs/parser.h +6 -6
  93. data/include/rbs/string.h +0 -2
  94. data/include/rbs/util/rbs_allocator.h +34 -13
  95. data/include/rbs/util/rbs_assert.h +12 -1
  96. data/include/rbs/util/rbs_encoding.h +2 -0
  97. data/include/rbs/util/rbs_unescape.h +2 -1
  98. data/lib/rbs/ast/annotation.rb +1 -1
  99. data/lib/rbs/ast/comment.rb +1 -1
  100. data/lib/rbs/ast/declarations.rb +10 -10
  101. data/lib/rbs/ast/members.rb +14 -14
  102. data/lib/rbs/ast/ruby/annotations.rb +137 -0
  103. data/lib/rbs/ast/ruby/comment_block.rb +24 -0
  104. data/lib/rbs/ast/ruby/declarations.rb +198 -3
  105. data/lib/rbs/ast/ruby/helpers/constant_helper.rb +4 -0
  106. data/lib/rbs/ast/ruby/members.rb +159 -1
  107. data/lib/rbs/ast/type_param.rb +24 -4
  108. data/lib/rbs/buffer.rb +20 -15
  109. data/lib/rbs/cli/diff.rb +16 -15
  110. data/lib/rbs/cli/validate.rb +38 -51
  111. data/lib/rbs/cli.rb +52 -19
  112. data/lib/rbs/collection/config/lockfile_generator.rb +8 -0
  113. data/lib/rbs/collection/sources/git.rb +1 -0
  114. data/lib/rbs/definition.rb +1 -1
  115. data/lib/rbs/definition_builder/ancestor_builder.rb +62 -9
  116. data/lib/rbs/definition_builder/method_builder.rb +20 -0
  117. data/lib/rbs/definition_builder.rb +91 -2
  118. data/lib/rbs/diff.rb +7 -1
  119. data/lib/rbs/environment.rb +227 -74
  120. data/lib/rbs/environment_loader.rb +0 -6
  121. data/lib/rbs/errors.rb +27 -7
  122. data/lib/rbs/inline_parser.rb +341 -5
  123. data/lib/rbs/location_aux.rb +1 -1
  124. data/lib/rbs/locator.rb +5 -1
  125. data/lib/rbs/method_type.rb +5 -3
  126. data/lib/rbs/parser_aux.rb +2 -2
  127. data/lib/rbs/prototype/rb.rb +2 -2
  128. data/lib/rbs/prototype/rbi.rb +2 -0
  129. data/lib/rbs/prototype/runtime.rb +8 -0
  130. data/lib/rbs/resolver/constant_resolver.rb +2 -2
  131. data/lib/rbs/resolver/type_name_resolver.rb +116 -38
  132. data/lib/rbs/subtractor.rb +3 -1
  133. data/lib/rbs/test/type_check.rb +16 -2
  134. data/lib/rbs/type_name.rb +1 -1
  135. data/lib/rbs/types.rb +27 -27
  136. data/lib/rbs/validator.rb +2 -2
  137. data/lib/rbs/version.rb +1 -1
  138. data/lib/rbs.rb +1 -1
  139. data/lib/rdoc/discover.rb +1 -1
  140. data/lib/rdoc_plugin/parser.rb +1 -1
  141. data/rbs.gemspec +3 -2
  142. data/schema/typeParam.json +17 -1
  143. data/sig/ast/ruby/annotations.rbs +124 -0
  144. data/sig/ast/ruby/comment_block.rbs +8 -0
  145. data/sig/ast/ruby/declarations.rbs +102 -4
  146. data/sig/ast/ruby/members.rbs +87 -1
  147. data/sig/cli/diff.rbs +5 -11
  148. data/sig/cli/validate.rbs +13 -4
  149. data/sig/cli.rbs +18 -18
  150. data/sig/definition.rbs +6 -1
  151. data/sig/environment.rbs +70 -12
  152. data/sig/errors.rbs +13 -6
  153. data/sig/inline_parser.rbs +39 -2
  154. data/sig/locator.rbs +0 -2
  155. data/sig/manifest.yaml +0 -1
  156. data/sig/method_builder.rbs +3 -1
  157. data/sig/method_types.rbs +1 -1
  158. data/sig/parser.rbs +16 -2
  159. data/sig/resolver/type_name_resolver.rbs +35 -7
  160. data/sig/source.rbs +3 -3
  161. data/sig/type_param.rbs +13 -8
  162. data/sig/types.rbs +4 -4
  163. data/src/ast.c +80 -1
  164. data/src/lexer.c +1392 -1313
  165. data/src/lexer.re +3 -0
  166. data/src/lexstate.c +58 -37
  167. data/src/location.c +4 -4
  168. data/src/parser.c +412 -145
  169. data/src/string.c +0 -48
  170. data/src/util/rbs_allocator.c +89 -71
  171. data/src/util/rbs_assert.c +1 -1
  172. data/src/util/rbs_buffer.c +2 -2
  173. data/src/util/rbs_constant_pool.c +10 -10
  174. data/src/util/rbs_encoding.c +4 -8
  175. data/src/util/rbs_unescape.c +56 -20
  176. data/stdlib/bigdecimal/0/big_decimal.rbs +100 -82
  177. data/stdlib/bigdecimal-math/0/big_math.rbs +169 -8
  178. data/stdlib/cgi/0/core.rbs +9 -393
  179. data/stdlib/cgi/0/manifest.yaml +1 -0
  180. data/stdlib/cgi-escape/0/escape.rbs +171 -0
  181. data/stdlib/coverage/0/coverage.rbs +3 -1
  182. data/stdlib/date/0/date.rbs +67 -59
  183. data/stdlib/date/0/date_time.rbs +1 -1
  184. data/stdlib/delegate/0/delegator.rbs +10 -7
  185. data/stdlib/digest/0/digest.rbs +110 -0
  186. data/stdlib/erb/0/erb.rbs +737 -347
  187. data/stdlib/fileutils/0/fileutils.rbs +20 -14
  188. data/stdlib/forwardable/0/forwardable.rbs +3 -0
  189. data/stdlib/json/0/json.rbs +82 -28
  190. data/stdlib/net-http/0/net-http.rbs +3 -0
  191. data/stdlib/objspace/0/objspace.rbs +9 -27
  192. data/stdlib/open-uri/0/open-uri.rbs +40 -0
  193. data/stdlib/open3/0/open3.rbs +459 -1
  194. data/stdlib/openssl/0/openssl.rbs +331 -228
  195. data/stdlib/optparse/0/optparse.rbs +8 -3
  196. data/stdlib/pathname/0/pathname.rbs +9 -1379
  197. data/stdlib/psych/0/psych.rbs +4 -4
  198. data/stdlib/random-formatter/0/random-formatter.rbs +277 -0
  199. data/stdlib/rdoc/0/code_object.rbs +2 -1
  200. data/stdlib/rdoc/0/parser.rbs +1 -1
  201. data/stdlib/rdoc/0/rdoc.rbs +1 -1
  202. data/stdlib/rdoc/0/store.rbs +1 -1
  203. data/stdlib/resolv/0/resolv.rbs +25 -68
  204. data/stdlib/ripper/0/ripper.rbs +2 -2
  205. data/stdlib/securerandom/0/manifest.yaml +2 -0
  206. data/stdlib/securerandom/0/securerandom.rbs +6 -19
  207. data/stdlib/singleton/0/singleton.rbs +3 -0
  208. data/stdlib/socket/0/socket.rbs +13 -1
  209. data/stdlib/socket/0/tcp_socket.rbs +10 -2
  210. data/stdlib/stringio/0/stringio.rbs +1176 -85
  211. data/stdlib/strscan/0/string_scanner.rbs +31 -31
  212. data/stdlib/tempfile/0/tempfile.rbs +3 -3
  213. data/stdlib/time/0/time.rbs +1 -1
  214. data/stdlib/timeout/0/timeout.rbs +63 -7
  215. data/stdlib/tsort/0/cyclic.rbs +3 -0
  216. data/stdlib/uri/0/common.rbs +16 -2
  217. data/stdlib/uri/0/file.rbs +1 -1
  218. data/stdlib/uri/0/generic.rbs +24 -16
  219. data/stdlib/uri/0/rfc2396_parser.rbs +6 -7
  220. data/stdlib/zlib/0/gzip_reader.rbs +2 -2
  221. data/stdlib/zlib/0/gzip_writer.rbs +1 -1
  222. data/stdlib/zlib/0/zstream.rbs +1 -0
  223. metadata +30 -4
data/lib/rbs/errors.rb CHANGED
@@ -93,7 +93,7 @@ module RBS
93
93
  params =
94
94
  case
95
95
  when type_name.class?
96
- decl = env.normalized_module_class_entry(type_name) or raise
96
+ decl = env.module_class_entry(type_name, normalized: true) or raise
97
97
  decl.type_params
98
98
  when type_name.interface?
99
99
  env.interface_decls.fetch(type_name).decl.type_params
@@ -475,7 +475,7 @@ module RBS
475
475
  @type_name = type_name
476
476
  @member = member
477
477
 
478
- super "#{Location.to_string member.location}: Cannot #{mixin_name} a class `#{member.name}` in the definition of `#{type_name}`"
478
+ super "#{Location.to_string member.location}: Cannot #{mixin_name} a class `#{member_name(member)}` in the definition of `#{type_name}`"
479
479
  end
480
480
 
481
481
  def location
@@ -483,23 +483,43 @@ module RBS
483
483
  end
484
484
 
485
485
  def self.check!(type_name:, env:, member:)
486
- if env.class_decl?(member.name)
486
+ name = case member
487
+ when AST::Members::Include, AST::Members::Extend, AST::Members::Prepend
488
+ member.name
489
+ when AST::Ruby::Members::IncludeMember, AST::Ruby::Members::ExtendMember, AST::Ruby::Members::PrependMember
490
+ member.module_name
491
+ else
492
+ raise "Unknown member type: #{member.class}"
493
+ end
494
+
495
+ if env.class_decl?(name)
487
496
  raise new(type_name: type_name, member: member)
488
497
  end
489
498
  end
490
499
 
491
500
  private
492
501
 
502
+ def member_name(member)
503
+ case member
504
+ when AST::Members::Include, AST::Members::Extend, AST::Members::Prepend
505
+ member.name
506
+ when AST::Ruby::Members::IncludeMember, AST::Ruby::Members::ExtendMember, AST::Ruby::Members::PrependMember
507
+ member.module_name
508
+ else
509
+ raise "Unknown member type: #{member.class}"
510
+ end
511
+ end
512
+
493
513
  def mixin_name
494
514
  case member
495
- when AST::Members::Prepend
515
+ when AST::Members::Prepend, AST::Ruby::Members::PrependMember
496
516
  "prepend"
497
- when AST::Members::Include
517
+ when AST::Members::Include, AST::Ruby::Members::IncludeMember
498
518
  "include"
499
- when AST::Members::Extend
519
+ when AST::Members::Extend, AST::Ruby::Members::ExtendMember
500
520
  "extend"
501
521
  else
502
- raise
522
+ raise "Unknown member type: #{member.class}"
503
523
  end
504
524
  end
505
525
  end
@@ -11,6 +11,10 @@ module RBS
11
11
  @declarations = []
12
12
  @diagnostics = []
13
13
  end
14
+
15
+ def type_fingerprint
16
+ declarations.map(&:type_fingerprint)
17
+ end
14
18
  end
15
19
 
16
20
  module Diagnostic
@@ -26,15 +30,26 @@ module RBS
26
30
  NotImplementedYet = _ = Class.new(Base)
27
31
  NonConstantClassName = _ = Class.new(Base)
28
32
  NonConstantModuleName = _ = Class.new(Base)
33
+ NonConstantSuperClassName = _ = Class.new(Base)
29
34
  TopLevelMethodDefinition = _ = Class.new(Base)
35
+ TopLevelAttributeDefinition = _ = Class.new(Base)
36
+ NonConstantConstantDeclaration = _ = Class.new(Base)
30
37
  UnusedInlineAnnotation = _ = Class.new(Base)
31
38
  AnnotationSyntaxError = _ = Class.new(Base)
39
+ MixinMultipleArguments = _ = Class.new(Base)
40
+ MixinNonConstantModule = _ = Class.new(Base)
41
+ AttributeNonSymbolName = _ = Class.new(Base)
42
+ ClassModuleAliasDeclarationMissingTypeName = _ = Class.new(Base)
32
43
  end
33
44
 
34
45
  def self.parse(buffer, prism)
35
46
  result = Result.new(buffer, prism)
36
47
 
37
- Parser.new(result).visit(prism.value)
48
+ parser = Parser.new(result)
49
+ parser.visit(prism.value)
50
+ parser.comments.each_unassociated_block do |block|
51
+ parser.report_unused_block(block)
52
+ end
38
53
 
39
54
  result
40
55
  end
@@ -96,15 +111,46 @@ module RBS
96
111
  return
97
112
  end
98
113
 
99
- class_decl = AST::Ruby::Declarations::ClassDecl.new(buffer, class_name, node)
114
+ # Parse super class if present
115
+ super_class = if node.superclass
116
+ node.inheritance_operator_loc or raise
117
+ parse_super_class(node.superclass, node.inheritance_operator_loc)
118
+ end
119
+
120
+ class_decl = AST::Ruby::Declarations::ClassDecl.new(buffer, class_name, node, super_class)
100
121
  insert_declaration(class_decl)
101
122
  push_module_nesting(class_decl) do
102
123
  visit_child_nodes(node)
124
+
125
+ node.child_nodes.each do |child_node|
126
+ if child_node
127
+ comments.each_enclosed_block(child_node) do |block|
128
+ report_unused_block(block)
129
+ end
130
+ end
131
+ end
103
132
  end
104
133
 
105
134
  comments.each_enclosed_block(node) do |block|
106
- report_unused_block(block)
135
+ unused_annotations = [] #: Array[AST::Ruby::CommentBlock::AnnotationSyntaxError | AST::Ruby::Annotations::leading_annotation]
136
+
137
+ block.each_paragraph([]) do |paragraph|
138
+ case paragraph
139
+ when AST::Ruby::Annotations::InstanceVariableAnnotation
140
+ class_decl.members << AST::Ruby::Members::InstanceVariableMember.new(buffer, paragraph)
141
+ when Location
142
+ # Skip
143
+ when AST::Ruby::CommentBlock::AnnotationSyntaxError
144
+ unused_annotations << paragraph
145
+ else
146
+ unused_annotations << paragraph
147
+ end
148
+ end
149
+
150
+ report_unused_annotation(*unused_annotations)
107
151
  end
152
+
153
+ class_decl.members.sort_by! { _1.location.start_line }
108
154
  end
109
155
 
110
156
  def visit_module_node(node)
@@ -153,12 +199,12 @@ module RBS
153
199
  method_type, leading_unuseds, trailing_unused = AST::Ruby::Members::MethodTypeAnnotation.build(leading_block, trailing_block, [])
154
200
  report_unused_annotation(trailing_unused, *leading_unuseds)
155
201
 
156
- defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type)
202
+ defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type, leading_block)
157
203
  current.members << defn
158
204
 
159
205
  # Skip other comments in `def` node
160
206
  comments.each_enclosed_block(node) do |block|
161
- comments.associated_blocks << block
207
+ report_unused_block(block)
162
208
  end
163
209
  else
164
210
  diagnostics << Diagnostic::TopLevelMethodDefinition.new(
@@ -168,6 +214,261 @@ module RBS
168
214
  end
169
215
  end
170
216
 
217
+ def visit_call_node(node)
218
+ return unless node.receiver.nil? # Only handle top-level calls like include, extend, prepend, attr_*
219
+
220
+ case node.name
221
+ when :include, :extend, :prepend
222
+ return if skip_node?(node)
223
+
224
+ case current = current_module
225
+ when AST::Ruby::Declarations::ClassDecl, AST::Ruby::Declarations::ModuleDecl
226
+ parse_mixin_call(node)
227
+ end
228
+ when :attr_reader, :attr_writer, :attr_accessor
229
+ return if skip_node?(node)
230
+
231
+ case current = current_module
232
+ when AST::Ruby::Declarations::ClassDecl, AST::Ruby::Declarations::ModuleDecl
233
+ parse_attribute_call(node)
234
+ when nil
235
+ # Top-level attribute definition
236
+ diagnostics << Diagnostic::TopLevelAttributeDefinition.new(
237
+ rbs_location(node.message_loc || node.location),
238
+ "Top-level attribute definition is not supported"
239
+ )
240
+ end
241
+ else
242
+ visit_child_nodes(node)
243
+ end
244
+ end
245
+
246
+ def visit_constant_write_node(node)
247
+ return if skip_node?(node)
248
+
249
+ # Parse constant declaration (both top-level and in classes/modules)
250
+ parse_constant_declaration(node)
251
+ end
252
+
253
+ def visit_constant_path_write_node(node)
254
+ return if skip_node?(node)
255
+
256
+ parse_constant_declaration(node)
257
+ end
258
+
259
+ def parse_mixin_call(node)
260
+ # Check for multiple arguments
261
+ if node.arguments && node.arguments.arguments.length > 1
262
+ diagnostics << Diagnostic::MixinMultipleArguments.new(
263
+ rbs_location(node.location),
264
+ "Mixing multiple modules with one call is not supported"
265
+ )
266
+ return
267
+ end
268
+
269
+ # Check for missing arguments
270
+ unless node.arguments && node.arguments.arguments.length == 1
271
+ # This shouldn't happen in valid Ruby code, but handle it gracefully
272
+ return
273
+ end
274
+
275
+ first_arg = node.arguments.arguments.first
276
+
277
+ # Check if the argument is a constant
278
+ unless module_name = constant_as_type_name(first_arg)
279
+ diagnostics << Diagnostic::MixinNonConstantModule.new(
280
+ rbs_location(first_arg.location),
281
+ "Module name must be a constant"
282
+ )
283
+ return
284
+ end
285
+
286
+ # Look for type application annotation in trailing comments
287
+ # For single-line calls like "include Bar #[String]", the annotation is trailing
288
+ trailing_block = comments.trailing_block!(node.location)
289
+ annotation = nil
290
+
291
+ if trailing_block
292
+ case trailing_annotation = trailing_block.trailing_annotation([])
293
+ when AST::Ruby::Annotations::TypeApplicationAnnotation
294
+ annotation = trailing_annotation
295
+ else
296
+ report_unused_annotation(trailing_annotation)
297
+ end
298
+ end
299
+
300
+ # Create the appropriate member based on the method name
301
+ member = case node.name
302
+ when :include
303
+ AST::Ruby::Members::IncludeMember.new(buffer, node, module_name, annotation)
304
+ when :extend
305
+ AST::Ruby::Members::ExtendMember.new(buffer, node, module_name, annotation)
306
+ when :prepend
307
+ AST::Ruby::Members::PrependMember.new(buffer, node, module_name, annotation)
308
+ else
309
+ raise "Unexpected mixin method: #{node.name}"
310
+ end
311
+
312
+ current_module!.members << member
313
+ end
314
+
315
+ def parse_attribute_call(node)
316
+ # Get the name nodes (arguments to attr_*)
317
+ unless node.arguments && !node.arguments.arguments.empty?
318
+ return # No arguments, nothing to do
319
+ end
320
+
321
+ name_nodes = [] #: Array[Prism::SymbolNode]
322
+ node.arguments.arguments.each do |arg|
323
+ case arg
324
+ when Prism::SymbolNode
325
+ name_nodes << arg
326
+ else
327
+ # Non-symbol argument, report error
328
+ diagnostics << Diagnostic::AttributeNonSymbolName.new(
329
+ rbs_location(arg.location),
330
+ "Attribute name must be a symbol"
331
+ )
332
+ end
333
+ end
334
+
335
+ return if name_nodes.empty?
336
+
337
+ # Look for leading comment block
338
+ leading_block = comments.leading_block!(node)
339
+
340
+ # Look for trailing type annotation (#: Type)
341
+ trailing_block = comments.trailing_block!(node.location)
342
+ type_annotation = nil
343
+
344
+ if trailing_block
345
+ case annotation = trailing_block.trailing_annotation([])
346
+ when AST::Ruby::Annotations::NodeTypeAssertion
347
+ type_annotation = annotation
348
+ when AST::Ruby::CommentBlock::AnnotationSyntaxError
349
+ diagnostics << Diagnostic::AnnotationSyntaxError.new(
350
+ annotation.location, "Syntax error: " + annotation.error.error_message
351
+ )
352
+ end
353
+ end
354
+
355
+ # Report unused leading annotations since @rbs annotations are not used for attributes
356
+ if leading_block
357
+ report_unused_block(leading_block)
358
+ end
359
+
360
+ # Create the appropriate member type
361
+ member = case node.name
362
+ when :attr_reader
363
+ AST::Ruby::Members::AttrReaderMember.new(buffer, node, name_nodes, leading_block, type_annotation)
364
+ when :attr_writer
365
+ AST::Ruby::Members::AttrWriterMember.new(buffer, node, name_nodes, leading_block, type_annotation)
366
+ when :attr_accessor
367
+ AST::Ruby::Members::AttrAccessorMember.new(buffer, node, name_nodes, leading_block, type_annotation)
368
+ else
369
+ raise "Unexpected attribute method: #{node.name}"
370
+ end
371
+
372
+ current_module!.members << member
373
+ end
374
+
375
+ def parse_constant_declaration(node)
376
+ # Create TypeName for the constant
377
+ unless constant_name = constant_as_type_name(node)
378
+ location =
379
+ case node
380
+ when Prism::ConstantWriteNode
381
+ node.name_loc
382
+ when Prism::ConstantPathWriteNode
383
+ node.target.location
384
+ end
385
+
386
+ diagnostics << Diagnostic::NonConstantConstantDeclaration.new(
387
+ rbs_location(location),
388
+ "Constant name must be a constant"
389
+ )
390
+ return
391
+ end
392
+
393
+ # Look for leading comment block
394
+ leading_block = comments.leading_block!(node)
395
+ report_unused_block(leading_block) if leading_block
396
+
397
+ # Look for trailing type annotation (#: Type)
398
+ trailing_block = comments.trailing_block!(node.location)
399
+ type_annotation = nil
400
+ alias_annotation = nil
401
+
402
+ if trailing_block
403
+ case annotation = trailing_block.trailing_annotation([])
404
+ when AST::Ruby::Annotations::NodeTypeAssertion
405
+ type_annotation = annotation
406
+ when AST::Ruby::Annotations::ClassAliasAnnotation, AST::Ruby::Annotations::ModuleAliasAnnotation
407
+ alias_annotation = annotation
408
+ when AST::Ruby::CommentBlock::AnnotationSyntaxError
409
+ diagnostics << Diagnostic::AnnotationSyntaxError.new(
410
+ annotation.location, "Syntax error: " + annotation.error.error_message
411
+ )
412
+ end
413
+ end
414
+
415
+ # Handle class/module alias declarations
416
+ if alias_annotation
417
+ # Try to infer the old name from the right-hand side
418
+ infered_old_name = constant_as_type_name(node.value)
419
+
420
+ # Check if we have either an explicit type name or can infer one
421
+ if alias_annotation.type_name.nil? && infered_old_name.nil?
422
+ message =
423
+ if alias_annotation.is_a?(AST::Ruby::Annotations::ClassAliasAnnotation)
424
+ "Class name is missing in class alias declaration"
425
+ else
426
+ "Module name is missing in module alias declaration"
427
+ end
428
+
429
+ diagnostics << Diagnostic::ClassModuleAliasDeclarationMissingTypeName.new(
430
+ alias_annotation.location,
431
+ message
432
+ )
433
+ return
434
+ end
435
+
436
+ # Create class/module alias declaration
437
+ alias_decl = AST::Ruby::Declarations::ClassModuleAliasDecl.new(
438
+ buffer,
439
+ node,
440
+ constant_name,
441
+ infered_old_name,
442
+ leading_block,
443
+ alias_annotation
444
+ )
445
+
446
+ # Insert the alias declaration appropriately
447
+
448
+ if current_module
449
+ current_module.members << alias_decl
450
+ else
451
+ result.declarations << alias_decl
452
+ end
453
+ else
454
+ # Create regular constant declaration
455
+ constant_decl = AST::Ruby::Declarations::ConstantDecl.new(
456
+ buffer,
457
+ constant_name,
458
+ node,
459
+ leading_block,
460
+ type_annotation
461
+ )
462
+
463
+ # Insert the constant declaration appropriately
464
+ if current_module
465
+ current_module.members << constant_decl
466
+ else
467
+ result.declarations << constant_decl
468
+ end
469
+ end
470
+ end
471
+
171
472
  def insert_declaration(decl)
172
473
  if current_module
173
474
  current_module.members << decl
@@ -192,6 +493,8 @@ module RBS
192
493
  end
193
494
 
194
495
  def report_unused_block(block)
496
+ return unless block.leading?
497
+
195
498
  block.each_paragraph([]) do |paragraph|
196
499
  case paragraph
197
500
  when Location
@@ -201,6 +504,39 @@ module RBS
201
504
  end
202
505
  end
203
506
  end
507
+
508
+ def parse_super_class(super_class_expr, inheritance_operator_loc)
509
+ # Check if the superclass is a constant
510
+ unless super_class_name = constant_as_type_name(super_class_expr)
511
+ diagnostics << Diagnostic::NonConstantSuperClassName.new(
512
+ rbs_location(super_class_expr.location),
513
+ "Super class name must be a constant"
514
+ )
515
+ return nil
516
+ end
517
+
518
+ # Look for type application annotation in trailing comments
519
+ # For example: class StringArray < Array #[String]
520
+ trailing_block = comments.trailing_block!(super_class_expr.location)
521
+ type_annotation = nil
522
+
523
+ if trailing_block
524
+ case annotation = trailing_block.trailing_annotation([])
525
+ when AST::Ruby::Annotations::TypeApplicationAnnotation
526
+ type_annotation = annotation
527
+ else
528
+ report_unused_annotation(annotation)
529
+ end
530
+ end
531
+
532
+ # Create SuperClass object
533
+ AST::Ruby::Declarations::ClassDecl::SuperClass.new(
534
+ rbs_location(super_class_expr.location),
535
+ rbs_location(inheritance_operator_loc),
536
+ super_class_name,
537
+ type_annotation
538
+ )
539
+ end
204
540
  end
205
541
  end
206
542
  end
@@ -83,7 +83,7 @@ module RBS
83
83
  other.end_pos == end_pos
84
84
  end
85
85
 
86
- def to_json(state = _ = nil)
86
+ def to_json(state = nil)
87
87
  {
88
88
  start: {
89
89
  line: start_line,
data/lib/rbs/locator.rb CHANGED
@@ -177,6 +177,10 @@ module RBS
177
177
  find_in_type(pos, type: upper_bound, array: array) and return true
178
178
  end
179
179
 
180
+ if lower_bound = type_param.lower_bound_type
181
+ find_in_type(pos, type: lower_bound, array: array) and return true
182
+ end
183
+
180
184
  if default_type = type_param.default_type
181
185
  find_in_type(pos, type: default_type, array: array) and return true
182
186
  end
@@ -234,7 +238,7 @@ module RBS
234
238
 
235
239
  def test_loc(pos, location:)
236
240
  if location
237
- location.range === pos
241
+ location.start_pos <= pos && pos <= location.end_pos
238
242
  else
239
243
  false
240
244
  end
@@ -21,7 +21,7 @@ module RBS
21
21
  other.block == block
22
22
  end
23
23
 
24
- def to_json(state = _ = nil)
24
+ def to_json(state = nil)
25
25
  {
26
26
  type_params: type_params,
27
27
  type: type,
@@ -129,11 +129,13 @@ module RBS
129
129
  end
130
130
 
131
131
  def with_nonreturn_void?
132
- if type.with_nonreturn_void?
132
+ if type.with_nonreturn_void? # steep:ignore DeprecatedReference
133
133
  true
134
134
  else
135
135
  if block = block()
136
- block.type.with_nonreturn_void? || block.self_type&.with_nonreturn_void? || false
136
+ block.type.with_nonreturn_void? || # steep:ignore DeprecatedReference
137
+ block.self_type&.with_nonreturn_void? || # steep:ignore DeprecatedReference
138
+ false
137
139
  else
138
140
  false
139
141
  end
@@ -5,9 +5,9 @@ require_relative "parser/token"
5
5
 
6
6
  module RBS
7
7
  class Parser
8
- def self.parse_type(source, range: 0..., variables: [], require_eof: false)
8
+ def self.parse_type(source, range: 0..., variables: [], require_eof: false, void_allowed: true, self_allowed: true)
9
9
  buf = buffer(source)
10
- _parse_type(buf, range.begin || 0, range.end || buf.last_position, variables, require_eof)
10
+ _parse_type(buf, range.begin || 0, range.end || buf.last_position, variables, require_eof, void_allowed, self_allowed)
11
11
  end
12
12
 
13
13
  def self.parse_method_type(source, range: 0..., variables: [], require_eof: false)
@@ -372,8 +372,8 @@ module RBS
372
372
  end
373
373
 
374
374
  value_node = node.children.last
375
- type = if value_node.nil?
376
- # Give up type prediction when node is MASGN.
375
+ type = if value_node.nil? || value_node.type == :SELF
376
+ # Give up type prediction when node is MASGN or SELF.
377
377
  Types::Bases::Any.new(location: nil)
378
378
  else
379
379
  literal_to_type(value_node)
@@ -235,6 +235,7 @@ module RBS
235
235
  variance: variance || :invariant,
236
236
  location: nil,
237
237
  upper_bound: nil,
238
+ lower_bound: nil,
238
239
  default_type: nil
239
240
  )
240
241
  end
@@ -332,6 +333,7 @@ module RBS
332
333
  name: name,
333
334
  variance: :invariant,
334
335
  upper_bound: nil,
336
+ lower_bound: nil,
335
337
  location: nil,
336
338
  default_type: nil
337
339
  )
@@ -27,6 +27,10 @@ module RBS
27
27
  method_definition = @builder.build_singleton(module_name.absolute!).methods[method.name]
28
28
  return false unless method_definition
29
29
 
30
+ return false unless method_definition.defs.any? do |type_def|
31
+ type_def.implemented_in&.relative!.to_s == method.owner.to_s.delete_prefix("#<Class:").delete_suffix(">")
32
+ end
33
+
30
34
  method_definition.accessibility == accessibility
31
35
  end
32
36
 
@@ -36,6 +40,10 @@ module RBS
36
40
  method_definition = @builder.build_instance(module_name.absolute!).methods[method.name]
37
41
  return false unless method_definition
38
42
 
43
+ return false unless method_definition.defs.any? do |type_def|
44
+ type_def.implemented_in&.relative!.to_s == method.owner.to_s
45
+ end
46
+
39
47
  method_definition.accessibility == accessibility
40
48
  end
41
49
 
@@ -32,7 +32,7 @@ module RBS
32
32
  end
33
33
 
34
34
  environment.class_alias_decls.each do |name, entry|
35
- normalized_entry = environment.normalized_module_class_entry(name) or next
35
+ normalized_entry = environment.module_class_entry(name, normalized: true) or next
36
36
  constant = constant_of_module(name, normalized_entry)
37
37
 
38
38
  # Insert class/module aliases into `children_table` and `toplevel` table
@@ -176,7 +176,7 @@ module RBS
176
176
  end
177
177
 
178
178
  def constants_from_ancestors(module_name, constants:)
179
- entry = builder.env.normalized_module_class_entry(module_name) or raise
179
+ entry = builder.env.module_class_entry(module_name, normalized: true) or raise
180
180
 
181
181
  if entry.is_a?(Environment::ClassEntry) || entry.is_a?(Environment::ModuleEntry)
182
182
  constants.merge!(table.children(BuiltinNames::Object.name) || raise)