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,542 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBS
4
+ class InlineParser
5
+ class Result
6
+ attr_reader :buffer, :prism_result, :declarations, :diagnostics
7
+
8
+ def initialize(buffer, prism)
9
+ @buffer = buffer
10
+ @prism_result = prism
11
+ @declarations = []
12
+ @diagnostics = []
13
+ end
14
+
15
+ def type_fingerprint
16
+ declarations.map(&:type_fingerprint)
17
+ end
18
+ end
19
+
20
+ module Diagnostic
21
+ class Base
22
+ attr_reader :message, :location
23
+
24
+ def initialize(location, message)
25
+ @location = location
26
+ @message = message
27
+ end
28
+ end
29
+
30
+ NotImplementedYet = _ = Class.new(Base)
31
+ NonConstantClassName = _ = Class.new(Base)
32
+ NonConstantModuleName = _ = Class.new(Base)
33
+ NonConstantSuperClassName = _ = Class.new(Base)
34
+ TopLevelMethodDefinition = _ = Class.new(Base)
35
+ TopLevelAttributeDefinition = _ = Class.new(Base)
36
+ NonConstantConstantDeclaration = _ = Class.new(Base)
37
+ UnusedInlineAnnotation = _ = Class.new(Base)
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)
43
+ end
44
+
45
+ def self.parse(buffer, prism)
46
+ result = Result.new(buffer, prism)
47
+
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
53
+
54
+ result
55
+ end
56
+
57
+ class Parser < Prism::Visitor
58
+ attr_reader :module_nesting, :result, :comments
59
+
60
+ include AST::Ruby::Helpers::ConstantHelper
61
+ include AST::Ruby::Helpers::LocationHelper
62
+
63
+ def initialize(result)
64
+ @result = result
65
+ @module_nesting = []
66
+ @comments = CommentAssociation.build(result.buffer, result.prism_result)
67
+ end
68
+
69
+ def buffer
70
+ result.buffer
71
+ end
72
+
73
+ def current_module
74
+ module_nesting.last
75
+ end
76
+
77
+ def current_module!
78
+ current_module || raise("#current_module is nil")
79
+ end
80
+
81
+ def diagnostics
82
+ result.diagnostics
83
+ end
84
+
85
+ def push_module_nesting(mod)
86
+ module_nesting.push(mod)
87
+ yield
88
+ ensure
89
+ module_nesting.pop()
90
+ end
91
+
92
+ def skip_node?(node)
93
+ if ref = comments.leading_block(node)
94
+ if ref.block.each_paragraph([]).any? { _1.is_a?(AST::Ruby::Annotations::SkipAnnotation) }
95
+ ref.associate!
96
+ return true
97
+ end
98
+ end
99
+
100
+ false
101
+ end
102
+
103
+ def visit_class_node(node)
104
+ return if skip_node?(node)
105
+
106
+ unless class_name = constant_as_type_name(node.constant_path)
107
+ diagnostics << Diagnostic::NonConstantClassName.new(
108
+ rbs_location(node.constant_path.location),
109
+ "Class name must be a constant"
110
+ )
111
+ return
112
+ end
113
+
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)
121
+ insert_declaration(class_decl)
122
+ push_module_nesting(class_decl) do
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
132
+ end
133
+
134
+ comments.each_enclosed_block(node) do |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)
151
+ end
152
+
153
+ class_decl.members.sort_by! { _1.location.start_line }
154
+ end
155
+
156
+ def visit_module_node(node)
157
+ return if skip_node?(node)
158
+
159
+ unless module_name = constant_as_type_name(node.constant_path)
160
+ diagnostics << Diagnostic::NonConstantModuleName.new(
161
+ rbs_location(node.constant_path.location),
162
+ "Module name must be a constant"
163
+ )
164
+ return
165
+ end
166
+
167
+ module_decl = AST::Ruby::Declarations::ModuleDecl.new(buffer, module_name, node)
168
+ insert_declaration(module_decl)
169
+ push_module_nesting(module_decl) do
170
+ visit_child_nodes(node)
171
+ end
172
+
173
+ comments.each_enclosed_block(node) do |block|
174
+ report_unused_block(block)
175
+ end
176
+ end
177
+
178
+ def visit_def_node(node)
179
+ return if skip_node?(node)
180
+
181
+ if node.receiver
182
+ diagnostics << Diagnostic::NotImplementedYet.new(
183
+ rbs_location(node.receiver.location),
184
+ "Singleton method definition is not supported yet"
185
+ )
186
+ return
187
+ end
188
+
189
+ case current = current_module
190
+ when AST::Ruby::Declarations::ClassDecl, AST::Ruby::Declarations::ModuleDecl
191
+ leading_block = comments.leading_block!(node)
192
+
193
+ if node.end_keyword_loc
194
+ # Not an end-less def
195
+ end_loc = node.rparen_loc || node.parameters&.location || node.name_loc
196
+ trailing_block = comments.trailing_block!(end_loc)
197
+ end
198
+
199
+ method_type, leading_unuseds, trailing_unused = AST::Ruby::Members::MethodTypeAnnotation.build(leading_block, trailing_block, [], node)
200
+ report_unused_annotation(trailing_unused, *leading_unuseds)
201
+
202
+ defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type, leading_block)
203
+ current.members << defn
204
+
205
+ # Skip other comments in `def` node
206
+ comments.each_enclosed_block(node) do |block|
207
+ report_unused_block(block)
208
+ end
209
+ else
210
+ diagnostics << Diagnostic::TopLevelMethodDefinition.new(
211
+ rbs_location(node.name_loc),
212
+ "Top-level method definition is not supported"
213
+ )
214
+ end
215
+ end
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
+
472
+ def insert_declaration(decl)
473
+ if current_module
474
+ current_module.members << decl
475
+ else
476
+ result.declarations << decl
477
+ end
478
+ end
479
+
480
+ def report_unused_annotation(*annotations)
481
+ annotations.each do |annotation|
482
+ case annotation
483
+ when AST::Ruby::CommentBlock::AnnotationSyntaxError
484
+ diagnostics << Diagnostic::AnnotationSyntaxError.new(
485
+ annotation.location, "Syntax error: " + annotation.error.error_message
486
+ )
487
+ when AST::Ruby::Annotations::Base
488
+ diagnostics << Diagnostic::UnusedInlineAnnotation.new(
489
+ annotation.location, "Unused inline rbs annotation"
490
+ )
491
+ end
492
+ end
493
+ end
494
+
495
+ def report_unused_block(block)
496
+ return unless block.leading?
497
+
498
+ block.each_paragraph([]) do |paragraph|
499
+ case paragraph
500
+ when Location
501
+ # noop
502
+ else
503
+ report_unused_annotation(paragraph)
504
+ end
505
+ end
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
540
+ end
541
+ end
542
+ end
@@ -28,6 +28,14 @@ module RBS
28
28
 
29
29
  WithChildren = self
30
30
 
31
+ def start_pos
32
+ buffer.absolute_position(_start_pos) || raise
33
+ end
34
+
35
+ def end_pos
36
+ buffer.absolute_position(_end_pos) || raise
37
+ end
38
+
31
39
  def name
32
40
  buffer.name
33
41
  end
@@ -49,11 +57,11 @@ module RBS
49
57
  end
50
58
 
51
59
  def start_loc
52
- @start_loc ||= buffer.pos_to_loc(start_pos)
60
+ @start_loc ||= buffer.top_buffer.pos_to_loc(start_pos)
53
61
  end
54
62
 
55
63
  def end_loc
56
- @end_loc ||= buffer.pos_to_loc(end_pos)
64
+ @end_loc ||= buffer.top_buffer.pos_to_loc(end_pos)
57
65
  end
58
66
 
59
67
  def range
@@ -61,7 +69,7 @@ module RBS
61
69
  end
62
70
 
63
71
  def source
64
- @source ||= (buffer.content[range] || raise)
72
+ @source ||= (buffer.top_buffer.content[range] || raise)
65
73
  end
66
74
 
67
75
  def to_s
@@ -75,7 +83,7 @@ module RBS
75
83
  other.end_pos == end_pos
76
84
  end
77
85
 
78
- def to_json(state = _ = nil)
86
+ def to_json(state = nil)
79
87
  {
80
88
  start: {
81
89
  line: start_line,
@@ -134,5 +142,29 @@ module RBS
134
142
  def required_key?(name)
135
143
  _required_keys.include?(name)
136
144
  end
145
+
146
+ def local_location
147
+ loc = Location.new(buffer.detach, _start_pos, _end_pos)
148
+
149
+ each_optional_key do |key|
150
+ value = self[key]
151
+ if value
152
+ loc.add_optional_child(key, value._start_pos...value._end_pos)
153
+ else
154
+ loc.add_optional_child(key, nil)
155
+ end
156
+ end
157
+
158
+ each_required_key do |key|
159
+ value = self[key] or raise
160
+ loc.add_required_child(key, value._start_pos...value._end_pos)
161
+ end
162
+
163
+ loc #: self
164
+ end
165
+
166
+ def local_source
167
+ local_location.source
168
+ end
137
169
  end
138
170
  end
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
data/lib/rbs/namespace.rb CHANGED
@@ -116,10 +116,3 @@ module RBS
116
116
  end
117
117
  end
118
118
  end
119
-
120
- module Kernel
121
- def Namespace(name)
122
- warn "Kernel#Namespace() is deprecated. Use RBS::Namespace.parse instead.", category: :deprecated
123
- RBS::Namespace.parse(name)
124
- end
125
- end