steep 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (190) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/exe/rbs +1 -1
  4. data/lib/steep/annotation_parser.rb +4 -4
  5. data/lib/steep/ast/buffer.rb +11 -7
  6. data/lib/steep/ast/builtin.rb +8 -0
  7. data/lib/steep/ast/types/factory.rb +55 -55
  8. data/lib/steep/drivers/check.rb +20 -4
  9. data/lib/steep/drivers/langserver.rb +6 -1
  10. data/lib/steep/drivers/vendor.rb +2 -2
  11. data/lib/steep/project/completion_provider.rb +5 -11
  12. data/lib/steep/project/dsl.rb +14 -0
  13. data/lib/steep/project/file.rb +42 -46
  14. data/lib/steep/project/hover_content.rb +11 -5
  15. data/lib/steep/project/options.rb +25 -3
  16. data/lib/steep/project/target.rb +10 -4
  17. data/lib/steep/signature/errors.rb +1 -1
  18. data/lib/steep/signature/validator.rb +8 -8
  19. data/lib/steep/source.rb +1 -1
  20. data/lib/steep/type_construction.rb +987 -711
  21. data/lib/steep/type_inference/constant_env.rb +1 -1
  22. data/lib/steep/type_inference/context.rb +7 -3
  23. data/lib/steep/type_inference/context_array.rb +111 -0
  24. data/lib/steep/type_inference/local_variable_type_env.rb +226 -0
  25. data/lib/steep/type_inference/logic.rb +130 -0
  26. data/lib/steep/type_inference/type_env.rb +5 -69
  27. data/lib/steep/typing.rb +79 -22
  28. data/lib/steep/version.rb +1 -1
  29. data/lib/steep.rb +6 -1
  30. data/smoke/alias/Steepfile +1 -0
  31. data/smoke/and/Steepfile +1 -0
  32. data/smoke/array/Steepfile +1 -0
  33. data/smoke/array/b.rb +0 -2
  34. data/smoke/block/Steepfile +1 -0
  35. data/smoke/case/Steepfile +1 -0
  36. data/smoke/class/Steepfile +1 -0
  37. data/smoke/const/Steepfile +1 -0
  38. data/smoke/dstr/Steepfile +1 -0
  39. data/smoke/ensure/Steepfile +1 -0
  40. data/smoke/enumerator/Steepfile +1 -0
  41. data/smoke/extension/Steepfile +1 -0
  42. data/smoke/extension/c.rb +1 -0
  43. data/smoke/hash/Steepfile +1 -0
  44. data/smoke/hello/Steepfile +1 -0
  45. data/smoke/if/Steepfile +1 -0
  46. data/smoke/if/a.rb +1 -1
  47. data/smoke/implements/Steepfile +1 -0
  48. data/smoke/initialize/Steepfile +1 -0
  49. data/smoke/integer/Steepfile +1 -0
  50. data/smoke/interface/Steepfile +1 -0
  51. data/smoke/kwbegin/Steepfile +1 -0
  52. data/smoke/lambda/Steepfile +1 -0
  53. data/smoke/literal/Steepfile +1 -0
  54. data/smoke/map/Steepfile +1 -0
  55. data/smoke/method/Steepfile +1 -0
  56. data/smoke/module/Steepfile +1 -0
  57. data/smoke/regexp/Steepfile +1 -0
  58. data/smoke/regression/Steepfile +1 -0
  59. data/smoke/rescue/Steepfile +1 -0
  60. data/smoke/rescue/a.rb +1 -1
  61. data/smoke/self/Steepfile +1 -0
  62. data/smoke/skip/Steepfile +1 -0
  63. data/smoke/stdout/Steepfile +1 -0
  64. data/smoke/super/Steepfile +1 -0
  65. data/smoke/type_case/Steepfile +1 -0
  66. data/smoke/yield/Steepfile +1 -0
  67. data/steep.gemspec +1 -1
  68. data/vendor/ruby-signature/.gitignore +2 -2
  69. data/vendor/ruby-signature/README.md +2 -2
  70. data/vendor/ruby-signature/Rakefile +2 -2
  71. data/vendor/ruby-signature/bin/annotate-with-rdoc +14 -13
  72. data/vendor/ruby-signature/bin/console +1 -1
  73. data/vendor/ruby-signature/bin/sort +7 -6
  74. data/vendor/ruby-signature/bin/test_runner.rb +0 -1
  75. data/vendor/ruby-signature/docs/CONTRIBUTING.md +1 -1
  76. data/vendor/ruby-signature/docs/sigs.md +3 -3
  77. data/vendor/ruby-signature/docs/stdlib.md +1 -1
  78. data/vendor/ruby-signature/docs/syntax.md +9 -9
  79. data/vendor/ruby-signature/exe/rbs +5 -1
  80. data/vendor/ruby-signature/lib/rbs/ast/annotation.rb +27 -0
  81. data/vendor/ruby-signature/lib/rbs/ast/comment.rb +27 -0
  82. data/vendor/ruby-signature/lib/rbs/ast/declarations.rb +395 -0
  83. data/vendor/ruby-signature/lib/rbs/ast/members.rb +362 -0
  84. data/vendor/ruby-signature/lib/rbs/buffer.rb +50 -0
  85. data/vendor/ruby-signature/lib/rbs/builtin_names.rb +55 -0
  86. data/vendor/ruby-signature/lib/rbs/cli.rb +558 -0
  87. data/vendor/ruby-signature/lib/rbs/constant.rb +26 -0
  88. data/vendor/ruby-signature/lib/rbs/constant_table.rb +150 -0
  89. data/vendor/ruby-signature/lib/rbs/definition.rb +170 -0
  90. data/vendor/ruby-signature/lib/rbs/definition_builder.rb +919 -0
  91. data/vendor/ruby-signature/lib/rbs/environment.rb +281 -0
  92. data/vendor/ruby-signature/lib/rbs/environment_loader.rb +136 -0
  93. data/vendor/ruby-signature/lib/rbs/environment_walker.rb +124 -0
  94. data/vendor/ruby-signature/lib/rbs/errors.rb +187 -0
  95. data/vendor/ruby-signature/lib/rbs/location.rb +102 -0
  96. data/vendor/ruby-signature/lib/rbs/method_type.rb +123 -0
  97. data/vendor/ruby-signature/lib/rbs/namespace.rb +91 -0
  98. data/vendor/ruby-signature/lib/{ruby/signature → rbs}/parser.rb +21 -23
  99. data/vendor/ruby-signature/lib/{ruby/signature → rbs}/parser.y +18 -18
  100. data/vendor/ruby-signature/lib/rbs/prototype/rb.rb +553 -0
  101. data/vendor/ruby-signature/lib/rbs/prototype/rbi.rb +587 -0
  102. data/vendor/ruby-signature/lib/rbs/prototype/runtime.rb +381 -0
  103. data/vendor/ruby-signature/lib/rbs/substitution.rb +46 -0
  104. data/vendor/ruby-signature/lib/rbs/test/errors.rb +61 -0
  105. data/vendor/ruby-signature/lib/rbs/test/hook.rb +294 -0
  106. data/vendor/ruby-signature/lib/{ruby/signature → rbs}/test/setup.rb +7 -7
  107. data/vendor/ruby-signature/lib/rbs/test/spy.rb +325 -0
  108. data/vendor/ruby-signature/lib/rbs/test/test_helper.rb +183 -0
  109. data/vendor/ruby-signature/lib/rbs/test/type_check.rb +254 -0
  110. data/vendor/ruby-signature/lib/rbs/test.rb +26 -0
  111. data/vendor/ruby-signature/lib/rbs/type_name.rb +70 -0
  112. data/vendor/ruby-signature/lib/rbs/types.rb +936 -0
  113. data/vendor/ruby-signature/lib/rbs/variance_calculator.rb +138 -0
  114. data/vendor/ruby-signature/lib/rbs/vendorer.rb +47 -0
  115. data/vendor/ruby-signature/lib/rbs/version.rb +3 -0
  116. data/vendor/ruby-signature/lib/rbs/writer.rb +269 -0
  117. data/vendor/ruby-signature/lib/rbs.rb +64 -0
  118. data/vendor/ruby-signature/lib/ruby/signature.rb +4 -61
  119. data/vendor/ruby-signature/{ruby-signature.gemspec → rbs.gemspec} +4 -4
  120. data/vendor/ruby-signature/stdlib/abbrev/abbrev.rbs +58 -1
  121. data/vendor/ruby-signature/stdlib/base64/base64.rbs +69 -13
  122. data/vendor/ruby-signature/stdlib/benchmark/benchmark.rbs +372 -0
  123. data/vendor/ruby-signature/stdlib/builtin/builtin.rbs +9 -0
  124. data/vendor/ruby-signature/stdlib/builtin/dir.rbs +1 -7
  125. data/vendor/ruby-signature/stdlib/builtin/encoding.rbs +2 -1
  126. data/vendor/ruby-signature/stdlib/builtin/exception.rbs +3 -2
  127. data/vendor/ruby-signature/stdlib/builtin/file.rbs +902 -302
  128. data/vendor/ruby-signature/stdlib/builtin/gc.rbs +190 -68
  129. data/vendor/ruby-signature/stdlib/builtin/integer.rbs +3 -6
  130. data/vendor/ruby-signature/stdlib/builtin/kernel.rbs +6 -4
  131. data/vendor/ruby-signature/stdlib/builtin/marshal.rbs +146 -120
  132. data/vendor/ruby-signature/stdlib/builtin/math.rbs +310 -7
  133. data/vendor/ruby-signature/stdlib/builtin/method.rbs +11 -8
  134. data/vendor/ruby-signature/stdlib/builtin/module.rbs +959 -103
  135. data/vendor/ruby-signature/stdlib/builtin/proc.rbs +3 -0
  136. data/vendor/ruby-signature/stdlib/builtin/process.rbs +981 -108
  137. data/vendor/ruby-signature/stdlib/builtin/random.rbs +215 -41
  138. data/vendor/ruby-signature/stdlib/builtin/rb_config.rbs +47 -0
  139. data/vendor/ruby-signature/stdlib/builtin/string.rbs +9 -2
  140. data/vendor/ruby-signature/stdlib/builtin/string_io.rbs +282 -11
  141. data/vendor/ruby-signature/stdlib/builtin/symbol.rbs +11 -13
  142. data/vendor/ruby-signature/stdlib/builtin/thread.rbs +25 -29
  143. data/vendor/ruby-signature/stdlib/builtin/thread_group.rbs +1 -1
  144. data/vendor/ruby-signature/stdlib/builtin/time.rbs +875 -567
  145. data/vendor/ruby-signature/stdlib/builtin/trace_point.rbs +243 -44
  146. data/vendor/ruby-signature/stdlib/builtin/unbound_method.rbs +103 -109
  147. data/vendor/ruby-signature/stdlib/coverage/coverage.rbs +62 -0
  148. data/vendor/ruby-signature/stdlib/csv/csv.rbs +773 -0
  149. data/vendor/ruby-signature/stdlib/erb/erb.rbs +375 -1
  150. data/vendor/ruby-signature/stdlib/find/find.rbs +0 -4
  151. data/vendor/ruby-signature/stdlib/ipaddr/ipaddr.rbs +247 -0
  152. data/vendor/ruby-signature/stdlib/pathname/pathname.rbs +1088 -16
  153. data/vendor/ruby-signature/stdlib/set/set.rbs +251 -27
  154. metadata +49 -44
  155. data/exe/ruby-signature +0 -3
  156. data/vendor/ruby-signature/exe/ruby-signature +0 -7
  157. data/vendor/ruby-signature/lib/ruby/signature/ast/annotation.rb +0 -29
  158. data/vendor/ruby-signature/lib/ruby/signature/ast/comment.rb +0 -29
  159. data/vendor/ruby-signature/lib/ruby/signature/ast/declarations.rb +0 -391
  160. data/vendor/ruby-signature/lib/ruby/signature/ast/members.rb +0 -364
  161. data/vendor/ruby-signature/lib/ruby/signature/buffer.rb +0 -52
  162. data/vendor/ruby-signature/lib/ruby/signature/builtin_names.rb +0 -54
  163. data/vendor/ruby-signature/lib/ruby/signature/cli.rb +0 -555
  164. data/vendor/ruby-signature/lib/ruby/signature/constant.rb +0 -28
  165. data/vendor/ruby-signature/lib/ruby/signature/constant_table.rb +0 -152
  166. data/vendor/ruby-signature/lib/ruby/signature/definition.rb +0 -172
  167. data/vendor/ruby-signature/lib/ruby/signature/definition_builder.rb +0 -921
  168. data/vendor/ruby-signature/lib/ruby/signature/environment.rb +0 -283
  169. data/vendor/ruby-signature/lib/ruby/signature/environment_loader.rb +0 -138
  170. data/vendor/ruby-signature/lib/ruby/signature/environment_walker.rb +0 -126
  171. data/vendor/ruby-signature/lib/ruby/signature/errors.rb +0 -189
  172. data/vendor/ruby-signature/lib/ruby/signature/location.rb +0 -104
  173. data/vendor/ruby-signature/lib/ruby/signature/method_type.rb +0 -125
  174. data/vendor/ruby-signature/lib/ruby/signature/namespace.rb +0 -93
  175. data/vendor/ruby-signature/lib/ruby/signature/prototype/rb.rb +0 -444
  176. data/vendor/ruby-signature/lib/ruby/signature/prototype/rbi.rb +0 -579
  177. data/vendor/ruby-signature/lib/ruby/signature/prototype/runtime.rb +0 -383
  178. data/vendor/ruby-signature/lib/ruby/signature/substitution.rb +0 -48
  179. data/vendor/ruby-signature/lib/ruby/signature/test/errors.rb +0 -63
  180. data/vendor/ruby-signature/lib/ruby/signature/test/hook.rb +0 -290
  181. data/vendor/ruby-signature/lib/ruby/signature/test/spy.rb +0 -327
  182. data/vendor/ruby-signature/lib/ruby/signature/test/test_helper.rb +0 -185
  183. data/vendor/ruby-signature/lib/ruby/signature/test/type_check.rb +0 -256
  184. data/vendor/ruby-signature/lib/ruby/signature/test.rb +0 -28
  185. data/vendor/ruby-signature/lib/ruby/signature/type_name.rb +0 -72
  186. data/vendor/ruby-signature/lib/ruby/signature/types.rb +0 -932
  187. data/vendor/ruby-signature/lib/ruby/signature/variance_calculator.rb +0 -140
  188. data/vendor/ruby-signature/lib/ruby/signature/vendorer.rb +0 -49
  189. data/vendor/ruby-signature/lib/ruby/signature/version.rb +0 -5
  190. data/vendor/ruby-signature/lib/ruby/signature/writer.rb +0 -271
@@ -0,0 +1,558 @@
1
+ require "optparse"
2
+
3
+ module RBS
4
+ class CLI
5
+ class LibraryOptions
6
+ attr_reader :libs
7
+ attr_reader :dirs
8
+ attr_accessor :no_stdlib
9
+
10
+ def initialize()
11
+ @libs = []
12
+ @dirs = []
13
+ @no_stdlib = false
14
+ end
15
+
16
+ def setup(loader)
17
+ libs.each do |lib|
18
+ loader.add(library: lib)
19
+ end
20
+
21
+ dirs.each do |dir|
22
+ loader.add(path: Pathname(dir))
23
+ end
24
+
25
+ loader.no_builtin! if no_stdlib
26
+
27
+ loader
28
+ end
29
+ end
30
+
31
+ attr_reader :stdout
32
+ attr_reader :stderr
33
+
34
+ def initialize(stdout:, stderr:)
35
+ @stdout = stdout
36
+ @stderr = stderr
37
+ end
38
+
39
+ COMMANDS = [:ast, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :version, :parse]
40
+
41
+ def library_parse(opts, options:)
42
+ opts.on("-r LIBRARY") do |lib|
43
+ options.libs << lib
44
+ end
45
+
46
+ opts.on("-I DIR") do |dir|
47
+ options.dirs << dir
48
+ end
49
+
50
+ opts.on("--no-stdlib") do
51
+ options.no_stdlib = true
52
+ end
53
+
54
+ opts
55
+ end
56
+
57
+ def parse_logging_options(opts)
58
+ opts.on("--log-level=LEVEL", "Specify log level (defaults to `warn`)") do |level|
59
+ RBS.logger_level = level
60
+ end
61
+
62
+ opts.on("--log-output=OUTPUT", "Specify the file to output log (defaults to stderr)") do |output|
63
+ RBS.logger_output = File.open(output, "a")
64
+ end
65
+
66
+ opts
67
+ end
68
+
69
+ def run(args)
70
+ options = LibraryOptions.new
71
+
72
+ opts = OptionParser.new
73
+ opts.banner = <<~USAGE
74
+ Usage: rbs [options] COMMAND
75
+ Available commands: #{COMMANDS.join(", ")}
76
+ USAGE
77
+ library_parse(opts, options: options)
78
+ parse_logging_options(opts)
79
+
80
+ opts.order!(args)
81
+
82
+ command = args.shift&.to_sym
83
+
84
+ if COMMANDS.include?(command)
85
+ __send__ :"run_#{command}", args, options
86
+ else
87
+ stdout.puts opts.help
88
+ end
89
+ end
90
+
91
+ def run_ast(args, options)
92
+ loader = EnvironmentLoader.new()
93
+
94
+ options.setup(loader)
95
+
96
+ env = Environment.new()
97
+ loader.load(env: env)
98
+
99
+ stdout.print JSON.generate(env.declarations)
100
+ stdout.flush
101
+ end
102
+
103
+ def run_list(args, options)
104
+ list = []
105
+
106
+ OptionParser.new do |opts|
107
+ opts.on("--class") { list << :class }
108
+ opts.on("--module") { list << :module }
109
+ opts.on("--interface") { list << :interface }
110
+ end.order!(args)
111
+
112
+ list.push(:class, :module, :interface) if list.empty?
113
+
114
+ loader = EnvironmentLoader.new()
115
+
116
+ options.setup(loader)
117
+
118
+ env = Environment.new()
119
+ loader.load(env: env)
120
+
121
+ env.each_decl.sort_by {|name,| name.to_s }.each do |type_name, decl|
122
+ case decl
123
+ when AST::Declarations::Class
124
+ if list.include?(:class)
125
+ stdout.puts "#{type_name} (class)"
126
+ end
127
+ when AST::Declarations::Module
128
+ if list.include?(:module)
129
+ stdout.puts "#{type_name} (module)"
130
+ end
131
+ when AST::Declarations::Interface
132
+ if list.include?(:interface)
133
+ stdout.puts "#{type_name} (interface)"
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ def run_ancestors(args, options)
140
+ kind = :instance
141
+
142
+ OptionParser.new do |opts|
143
+ opts.on("--instance") { kind = :instance }
144
+ opts.on("--singleton") { kind = :singleton }
145
+ end.order!(args)
146
+
147
+ loader = EnvironmentLoader.new()
148
+
149
+ options.setup(loader)
150
+
151
+ env = Environment.new()
152
+ loader.load(env: env)
153
+
154
+ builder = DefinitionBuilder.new(env: env)
155
+ type_name = parse_type_name(args[0]).absolute!
156
+
157
+ if env.class?(type_name)
158
+ ancestor = case kind
159
+ when :instance
160
+ decl = env.find_class(type_name)
161
+ Definition::Ancestor::Instance.new(name: type_name,
162
+ args: Types::Variable.build(decl.type_params.each.map(&:name)))
163
+ when :singleton
164
+ Definition::Ancestor::Singleton.new(name: type_name)
165
+ end
166
+
167
+ ancestors = builder.build_ancestors(ancestor)
168
+
169
+ ancestors.each do |ancestor|
170
+ case ancestor
171
+ when Definition::Ancestor::Singleton
172
+ stdout.puts "singleton(#{ancestor.name})"
173
+ when Definition::Ancestor::ExtensionSingleton
174
+ stdout.puts "singleton(#{ancestor.name} (#{ancestor.extension_name}))"
175
+ when Definition::Ancestor::Instance
176
+ if ancestor.args.empty?
177
+ stdout.puts ancestor.name.to_s
178
+ else
179
+ stdout.puts "#{ancestor.name}[#{ancestor.args.join(", ")}]"
180
+ end
181
+ when Definition::Ancestor::ExtensionInstance
182
+ if ancestor.args.empty?
183
+ stdout.puts "#{ancestor.name} (#{ancestor.extension_name})"
184
+ else
185
+ stdout.puts "#{ancestor.name}[#{ancestor.args.join(", ")}] (#{ancestor.extension_name})"
186
+ end
187
+ end
188
+ end
189
+ else
190
+ stdout.puts "Cannot find class: #{type_name}"
191
+ end
192
+ end
193
+
194
+ def run_methods(args, options)
195
+ kind = :instance
196
+ inherit = true
197
+
198
+ OptionParser.new do |opts|
199
+ opts.on("--instance") { kind = :instance }
200
+ opts.on("--singleton") { kind = :singleton }
201
+ opts.on("--inherit") { inherit = true }
202
+ opts.on("--no-inherit") { inherit = false }
203
+ end.order!(args)
204
+
205
+ unless args.size == 1
206
+ stdout.puts "Expected one argument."
207
+ return
208
+ end
209
+
210
+ loader = EnvironmentLoader.new()
211
+
212
+ options.setup(loader)
213
+
214
+ env = Environment.new()
215
+ loader.load(env: env)
216
+
217
+ builder = DefinitionBuilder.new(env: env)
218
+ type_name = parse_type_name(args[0]).absolute!
219
+
220
+ if env.class?(type_name)
221
+ definition = case kind
222
+ when :instance
223
+ builder.build_instance(type_name)
224
+ when :singleton
225
+ builder.build_singleton(type_name)
226
+ end
227
+
228
+ definition.methods.keys.sort.each do |name|
229
+ method = definition.methods[name]
230
+ if inherit || method.implemented_in == definition.declaration
231
+ stdout.puts "#{name} (#{method.accessibility})"
232
+ end
233
+ end
234
+ else
235
+ stdout.puts "Cannot find class: #{type_name}"
236
+ end
237
+ end
238
+
239
+ def run_method(args, options)
240
+ kind = :instance
241
+
242
+ OptionParser.new do |opts|
243
+ opts.on("--instance") { kind = :instance }
244
+ opts.on("--singleton") { kind = :singleton }
245
+ end.order!(args)
246
+
247
+ unless args.size == 2
248
+ stdout.puts "Expected two arguments, but given #{args.size}."
249
+ return
250
+ end
251
+
252
+ loader = EnvironmentLoader.new()
253
+
254
+ options.setup(loader)
255
+
256
+ env = Environment.new()
257
+ loader.load(env: env)
258
+
259
+ builder = DefinitionBuilder.new(env: env)
260
+ type_name = parse_type_name(args[0]).absolute!
261
+ method_name = args[1].to_sym
262
+
263
+ unless env.class?(type_name)
264
+ stdout.puts "Cannot find class: #{type_name}"
265
+ return
266
+ end
267
+
268
+ definition = case kind
269
+ when :instance
270
+ builder.build_instance(type_name)
271
+ when :singleton
272
+ builder.build_singleton(type_name)
273
+ end
274
+
275
+ method = definition.methods[method_name]
276
+
277
+ unless method
278
+ stdout.puts "Cannot find method: #{method_name}"
279
+ return
280
+ end
281
+
282
+ stdout.puts "#{type_name}#{kind == :instance ? "#" : "."}#{method_name}"
283
+ stdout.puts " defined_in: #{method.defined_in&.name&.absolute!}"
284
+ stdout.puts " implementation: #{method.implemented_in.name.absolute!}"
285
+ stdout.puts " accessibility: #{method.accessibility}"
286
+ stdout.puts " types:"
287
+ separator = " "
288
+ for type in method.method_types
289
+ stdout.puts " #{separator} #{type}"
290
+ separator = "|"
291
+ end
292
+ end
293
+
294
+ def run_validate(args, options)
295
+ loader = EnvironmentLoader.new()
296
+
297
+ options.setup(loader)
298
+
299
+ env = Environment.new()
300
+ loader.load(env: env)
301
+
302
+ builder = DefinitionBuilder.new(env: env)
303
+
304
+ env.each_decl do |name, decl|
305
+ case decl
306
+ when AST::Declarations::Class, AST::Declarations::Module
307
+ stdout.puts "#{Location.to_string decl.location}:\tValidating class/module definition: `#{name}`..."
308
+ builder.build_instance(decl.name.absolute!).each_type do |type|
309
+ env.validate type, namespace: Namespace.root
310
+ end
311
+ builder.build_singleton(decl.name.absolute!).each_type do |type|
312
+ env.validate type, namespace: Namespace.root
313
+ end
314
+ when AST::Declarations::Interface
315
+ stdout.puts "#{Location.to_string decl.location}:\tValidating interface: `#{name}`..."
316
+ builder.build_interface(decl.name.absolute!, decl).each_type do |type|
317
+ env.validate type, namespace: Namespace.root
318
+ end
319
+ end
320
+ end
321
+
322
+ env.each_constant do |name, const|
323
+ stdout.puts "#{Location.to_string const.location}:\tValidating constant: `#{name}`..."
324
+ env.validate const.type, namespace: name.namespace
325
+ end
326
+
327
+ env.each_global do |name, global|
328
+ stdout.puts "#{Location.to_string global.location}:\tValidating global: `#{name}`..."
329
+ env.validate global.type, namespace: Namespace.root
330
+ end
331
+
332
+ env.each_alias do |name, decl|
333
+ stdout.puts "#{Location.to_string decl.location}:\tValidating alias: `#{name}`..."
334
+ env.validate decl.type, namespace: name.namespace
335
+ end
336
+ end
337
+
338
+ def run_constant(args, options)
339
+ context = nil
340
+
341
+ OptionParser.new do |opts|
342
+ opts.on("--context CONTEXT") {|c| context = c }
343
+ end.order!(args)
344
+
345
+ unless args.size == 1
346
+ stdout.puts "Expected one argument."
347
+ return
348
+ end
349
+
350
+ loader = EnvironmentLoader.new()
351
+
352
+ options.setup(loader)
353
+
354
+ env = Environment.new()
355
+ loader.load(env: env)
356
+
357
+ builder = DefinitionBuilder.new(env: env)
358
+ table = ConstantTable.new(builder: builder)
359
+
360
+ namespace = context ? Namespace.parse(context).absolute! : Namespace.root
361
+ stdout.puts "Context: #{namespace}"
362
+ name = Namespace.parse(args[0]).to_type_name
363
+ stdout.puts "Constant name: #{name}"
364
+
365
+ constant = table.resolve_constant_reference(name, context: namespace)
366
+
367
+ if constant
368
+ stdout.puts " => #{constant.name}: #{constant.type}"
369
+ else
370
+ stdout.puts " => [no constant]"
371
+ end
372
+ end
373
+
374
+ def run_version(args, options)
375
+ stdout.puts "ruby-signature #{VERSION}"
376
+ end
377
+
378
+ def run_paths(args, options)
379
+ loader = EnvironmentLoader.new()
380
+
381
+ options.setup(loader)
382
+
383
+ kind_of = -> (path) {
384
+ case
385
+ when path.file?
386
+ "file"
387
+ when path.directory?
388
+ "dir"
389
+ when !path.exist?
390
+ "absent"
391
+ else
392
+ "unknown"
393
+ end
394
+ }
395
+
396
+ if loader.stdlib_root
397
+ path = loader.stdlib_root
398
+ stdout.puts "#{path}/builtin (#{kind_of[path]}, stdlib)"
399
+ end
400
+
401
+ loader.paths.each do |path|
402
+ case path
403
+ when Pathname
404
+ stdout.puts "#{path} (#{kind_of[path]})"
405
+ when EnvironmentLoader::GemPath
406
+ stdout.puts "#{path.path} (#{kind_of[path.path]}, gem, name=#{path.name}, version=#{path.version})"
407
+ when EnvironmentLoader::LibraryPath
408
+ stdout.puts "#{path.path} (#{kind_of[path.path]}, library, name=#{path.name})"
409
+ end
410
+ end
411
+ end
412
+
413
+ def run_prototype(args, options)
414
+ format = args.shift
415
+
416
+ case format
417
+ when "rbi", "rb"
418
+ decls = run_prototype_file(format, args)
419
+ when "runtime"
420
+ require_libs = []
421
+ relative_libs = []
422
+ merge = false
423
+ owners_included = []
424
+
425
+ OptionParser.new do |opts|
426
+ opts.on("--require LIB") do |lib|
427
+ require_libs << lib
428
+ end
429
+ opts.on("--require-relative LIB") do |lib|
430
+ relative_libs << lib
431
+ end
432
+ opts.on("--merge") do
433
+ merge = true
434
+ end
435
+ opts.on("--method-owner CLASS") do |klass|
436
+ owners_included << klass
437
+ end
438
+ end.parse!(args)
439
+
440
+ loader = EnvironmentLoader.new()
441
+
442
+ options.setup(loader)
443
+
444
+ env = Environment.new()
445
+ loader.load(env: env)
446
+
447
+ require_libs.each do |lib|
448
+ require(lib)
449
+ end
450
+
451
+ relative_libs.each do |lib|
452
+ require(lib)
453
+ end
454
+
455
+ decls = Prototype::Runtime.new(patterns: args, env: env, merge: merge, owners_included: owners_included).decls
456
+ else
457
+ stdout.puts "Supported formats: rbi, rb, runtime"
458
+ exit 1
459
+ end
460
+
461
+ writer = Writer.new(out: stdout)
462
+ writer.write decls
463
+ end
464
+
465
+ def run_prototype_file(format, args)
466
+ parser = case format
467
+ when "rbi"
468
+ Prototype::RBI.new()
469
+ when "rb"
470
+ Prototype::RB.new()
471
+ end
472
+
473
+ args.each do |file|
474
+ parser.parse Pathname(file).read
475
+ end
476
+
477
+ parser.decls
478
+ end
479
+
480
+ def run_vendor(args, options)
481
+ clean = false
482
+ vendor_stdlib = false
483
+ vendor_dir = Pathname("vendor/sigs")
484
+
485
+ OptionParser.new do |opts|
486
+ opts.banner = <<~EOB
487
+ Usage: rbs vendor [options] GEMS...
488
+ Vendor signatures in the project directory.
489
+ EOB
490
+
491
+ opts.on("--[no-]clean", "Clean vendor directory (default: no)") do |v|
492
+ clean = v
493
+ end
494
+
495
+ opts.on("--[no-]stdlib", "Vendor stdlib signatures or not (default: no)") do |v|
496
+ vendor_stdlib = v
497
+ end
498
+
499
+ opts.on("--vendor-dir [DIR]", "Specify the directory for vendored signatures (default: vendor/sigs)") do |path|
500
+ vendor_dir = Pathname(path)
501
+ end
502
+ end.parse!(args)
503
+
504
+ stdout.puts "Vendoring signatures to #{vendor_dir}..."
505
+
506
+ vendorer = Vendorer.new(vendor_dir: vendor_dir)
507
+
508
+ if clean
509
+ stdout.puts " Deleting #{vendor_dir}..."
510
+ vendorer.clean!
511
+ end
512
+
513
+ if vendor_stdlib
514
+ stdout.puts " Vendoring standard libraries..."
515
+ vendorer.stdlib!
516
+ end
517
+
518
+ args.each do |gem|
519
+ name, version = EnvironmentLoader.parse_library(gem)
520
+
521
+ unless EnvironmentLoader.gem_sig_path(name, version)
522
+ stdout.puts " ⚠️ Cannot find rubygem: name=#{name}, version=#{version} 🚨"
523
+ else
524
+ stdout.puts " Vendoring gem: name=#{name}, version=#{version}..."
525
+ vendorer.gem!(name, version)
526
+ end
527
+ end
528
+ end
529
+
530
+ def run_parse(args, options)
531
+ loader = EnvironmentLoader.new()
532
+
533
+ syntax_error = false
534
+ args.each do |path|
535
+ path = Pathname(path)
536
+ loader.each_signature(path) do |sig_path|
537
+ Parser.parse_signature(sig_path.read)
538
+ rescue RBS::Parser::SyntaxError => ex
539
+ loc = ex.error_value.location
540
+ stdout.puts "#{sig_path}:#{loc.start_line}:#{loc.start_column}: parse error on value: (#{ex.token_str})"
541
+ syntax_error = true
542
+ rescue RBS::Parser::SemanticsError => ex
543
+ loc = ex.location
544
+ stdout.puts "#{sig_path}:#{loc.start_line}:#{loc.start_column}: #{ex.original_message}"
545
+ syntax_error = true
546
+ end
547
+ end
548
+ exit 1 if syntax_error
549
+ end
550
+
551
+ def parse_type_name(string)
552
+ Namespace.parse(string).yield_self do |namespace|
553
+ last = namespace.path.last
554
+ TypeName.new(name: last, namespace: namespace.parent)
555
+ end
556
+ end
557
+ end
558
+ end
@@ -0,0 +1,26 @@
1
+ module RBS
2
+ class Constant
3
+ attr_reader :name
4
+ attr_reader :type
5
+ attr_reader :declaration
6
+
7
+ def initialize(name:, type:, declaration:)
8
+ @name = name
9
+ @type = type
10
+ @declaration = declaration
11
+ end
12
+
13
+ def ==(other)
14
+ other.is_a?(Constant) &&
15
+ other.name == name &&
16
+ other.type == type &&
17
+ other.declaration == declaration
18
+ end
19
+
20
+ alias eql? ==
21
+
22
+ def hash
23
+ self.class.hash ^ name.hash ^ type.hash ^ declaration.hash
24
+ end
25
+ end
26
+ end