rbs 0.2.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.
- checksums.yaml +7 -0
- data/.github/workflows/ruby.yml +28 -0
- data/.gitignore +12 -0
- data/.rubocop.yml +15 -0
- data/BSDL +22 -0
- data/CHANGELOG.md +9 -0
- data/COPYING +56 -0
- data/Gemfile +6 -0
- data/README.md +93 -0
- data/Rakefile +142 -0
- data/bin/annotate-with-rdoc +157 -0
- data/bin/console +14 -0
- data/bin/query-rdoc +103 -0
- data/bin/setup +10 -0
- data/bin/sort +89 -0
- data/bin/test_runner.rb +16 -0
- data/docs/CONTRIBUTING.md +97 -0
- data/docs/sigs.md +148 -0
- data/docs/stdlib.md +152 -0
- data/docs/syntax.md +528 -0
- data/exe/rbs +7 -0
- data/lib/rbs.rb +64 -0
- data/lib/rbs/ast/annotation.rb +27 -0
- data/lib/rbs/ast/comment.rb +27 -0
- data/lib/rbs/ast/declarations.rb +395 -0
- data/lib/rbs/ast/members.rb +362 -0
- data/lib/rbs/buffer.rb +50 -0
- data/lib/rbs/builtin_names.rb +55 -0
- data/lib/rbs/cli.rb +558 -0
- data/lib/rbs/constant.rb +26 -0
- data/lib/rbs/constant_table.rb +150 -0
- data/lib/rbs/definition.rb +170 -0
- data/lib/rbs/definition_builder.rb +919 -0
- data/lib/rbs/environment.rb +281 -0
- data/lib/rbs/environment_loader.rb +136 -0
- data/lib/rbs/environment_walker.rb +124 -0
- data/lib/rbs/errors.rb +187 -0
- data/lib/rbs/location.rb +102 -0
- data/lib/rbs/method_type.rb +123 -0
- data/lib/rbs/namespace.rb +91 -0
- data/lib/rbs/parser.y +1344 -0
- data/lib/rbs/prototype/rb.rb +553 -0
- data/lib/rbs/prototype/rbi.rb +587 -0
- data/lib/rbs/prototype/runtime.rb +381 -0
- data/lib/rbs/substitution.rb +46 -0
- data/lib/rbs/test.rb +26 -0
- data/lib/rbs/test/errors.rb +61 -0
- data/lib/rbs/test/hook.rb +294 -0
- data/lib/rbs/test/setup.rb +58 -0
- data/lib/rbs/test/spy.rb +325 -0
- data/lib/rbs/test/test_helper.rb +183 -0
- data/lib/rbs/test/type_check.rb +254 -0
- data/lib/rbs/type_name.rb +70 -0
- data/lib/rbs/types.rb +936 -0
- data/lib/rbs/variance_calculator.rb +138 -0
- data/lib/rbs/vendorer.rb +47 -0
- data/lib/rbs/version.rb +3 -0
- data/lib/rbs/writer.rb +269 -0
- data/lib/ruby/signature.rb +7 -0
- data/rbs.gemspec +46 -0
- data/stdlib/abbrev/abbrev.rbs +60 -0
- data/stdlib/base64/base64.rbs +71 -0
- data/stdlib/benchmark/benchmark.rbs +372 -0
- data/stdlib/builtin/array.rbs +1997 -0
- data/stdlib/builtin/basic_object.rbs +280 -0
- data/stdlib/builtin/binding.rbs +177 -0
- data/stdlib/builtin/builtin.rbs +45 -0
- data/stdlib/builtin/class.rbs +145 -0
- data/stdlib/builtin/comparable.rbs +116 -0
- data/stdlib/builtin/complex.rbs +400 -0
- data/stdlib/builtin/constants.rbs +37 -0
- data/stdlib/builtin/data.rbs +5 -0
- data/stdlib/builtin/deprecated.rbs +2 -0
- data/stdlib/builtin/dir.rbs +413 -0
- data/stdlib/builtin/encoding.rbs +607 -0
- data/stdlib/builtin/enumerable.rbs +404 -0
- data/stdlib/builtin/enumerator.rbs +260 -0
- data/stdlib/builtin/errno.rbs +781 -0
- data/stdlib/builtin/errors.rbs +582 -0
- data/stdlib/builtin/exception.rbs +194 -0
- data/stdlib/builtin/false_class.rbs +40 -0
- data/stdlib/builtin/fiber.rbs +68 -0
- data/stdlib/builtin/fiber_error.rbs +12 -0
- data/stdlib/builtin/file.rbs +1076 -0
- data/stdlib/builtin/file_test.rbs +59 -0
- data/stdlib/builtin/float.rbs +696 -0
- data/stdlib/builtin/gc.rbs +243 -0
- data/stdlib/builtin/hash.rbs +1029 -0
- data/stdlib/builtin/integer.rbs +707 -0
- data/stdlib/builtin/io.rbs +683 -0
- data/stdlib/builtin/kernel.rbs +576 -0
- data/stdlib/builtin/marshal.rbs +161 -0
- data/stdlib/builtin/match_data.rbs +271 -0
- data/stdlib/builtin/math.rbs +369 -0
- data/stdlib/builtin/method.rbs +185 -0
- data/stdlib/builtin/module.rbs +1104 -0
- data/stdlib/builtin/nil_class.rbs +82 -0
- data/stdlib/builtin/numeric.rbs +409 -0
- data/stdlib/builtin/object.rbs +824 -0
- data/stdlib/builtin/proc.rbs +429 -0
- data/stdlib/builtin/process.rbs +1227 -0
- data/stdlib/builtin/random.rbs +267 -0
- data/stdlib/builtin/range.rbs +226 -0
- data/stdlib/builtin/rational.rbs +424 -0
- data/stdlib/builtin/rb_config.rbs +57 -0
- data/stdlib/builtin/regexp.rbs +1083 -0
- data/stdlib/builtin/ruby_vm.rbs +14 -0
- data/stdlib/builtin/signal.rbs +55 -0
- data/stdlib/builtin/string.rbs +1901 -0
- data/stdlib/builtin/string_io.rbs +284 -0
- data/stdlib/builtin/struct.rbs +40 -0
- data/stdlib/builtin/symbol.rbs +228 -0
- data/stdlib/builtin/thread.rbs +1108 -0
- data/stdlib/builtin/thread_group.rbs +23 -0
- data/stdlib/builtin/time.rbs +1047 -0
- data/stdlib/builtin/trace_point.rbs +290 -0
- data/stdlib/builtin/true_class.rbs +46 -0
- data/stdlib/builtin/unbound_method.rbs +153 -0
- data/stdlib/builtin/warning.rbs +17 -0
- data/stdlib/coverage/coverage.rbs +62 -0
- data/stdlib/csv/csv.rbs +773 -0
- data/stdlib/erb/erb.rbs +392 -0
- data/stdlib/find/find.rbs +40 -0
- data/stdlib/ipaddr/ipaddr.rbs +247 -0
- data/stdlib/json/json.rbs +335 -0
- data/stdlib/pathname/pathname.rbs +1093 -0
- data/stdlib/prime/integer-extension.rbs +23 -0
- data/stdlib/prime/prime.rbs +188 -0
- data/stdlib/securerandom/securerandom.rbs +9 -0
- data/stdlib/set/set.rbs +301 -0
- data/stdlib/tmpdir/tmpdir.rbs +53 -0
- metadata +292 -0
data/lib/rbs/cli.rb
ADDED
@@ -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
|