tapioca 0.4.27 → 0.5.3

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +15 -15
  3. data/README.md +2 -2
  4. data/Rakefile +5 -7
  5. data/exe/tapioca +2 -2
  6. data/lib/tapioca/cli.rb +172 -2
  7. data/lib/tapioca/compilers/dsl/aasm.rb +122 -0
  8. data/lib/tapioca/compilers/dsl/action_controller_helpers.rb +52 -12
  9. data/lib/tapioca/compilers/dsl/action_mailer.rb +6 -9
  10. data/lib/tapioca/compilers/dsl/active_job.rb +8 -12
  11. data/lib/tapioca/compilers/dsl/active_model_attributes.rb +131 -0
  12. data/lib/tapioca/compilers/dsl/active_model_secure_password.rb +101 -0
  13. data/lib/tapioca/compilers/dsl/active_record_associations.rb +33 -54
  14. data/lib/tapioca/compilers/dsl/active_record_columns.rb +10 -105
  15. data/lib/tapioca/compilers/dsl/active_record_enum.rb +8 -10
  16. data/lib/tapioca/compilers/dsl/active_record_fixtures.rb +86 -0
  17. data/lib/tapioca/compilers/dsl/active_record_scope.rb +7 -10
  18. data/lib/tapioca/compilers/dsl/active_record_typed_store.rb +5 -8
  19. data/lib/tapioca/compilers/dsl/active_resource.rb +9 -37
  20. data/lib/tapioca/compilers/dsl/active_storage.rb +98 -0
  21. data/lib/tapioca/compilers/dsl/active_support_concern.rb +106 -0
  22. data/lib/tapioca/compilers/dsl/active_support_current_attributes.rb +13 -8
  23. data/lib/tapioca/compilers/dsl/base.rb +108 -82
  24. data/lib/tapioca/compilers/dsl/config.rb +111 -0
  25. data/lib/tapioca/compilers/dsl/frozen_record.rb +5 -7
  26. data/lib/tapioca/compilers/dsl/identity_cache.rb +66 -29
  27. data/lib/tapioca/compilers/dsl/mixed_in_class_attributes.rb +74 -0
  28. data/lib/tapioca/compilers/dsl/protobuf.rb +19 -69
  29. data/lib/tapioca/compilers/dsl/sidekiq_worker.rb +25 -12
  30. data/lib/tapioca/compilers/dsl/smart_properties.rb +21 -33
  31. data/lib/tapioca/compilers/dsl/state_machines.rb +56 -78
  32. data/lib/tapioca/compilers/dsl/url_helpers.rb +7 -10
  33. data/lib/tapioca/compilers/dsl_compiler.rb +25 -40
  34. data/lib/tapioca/compilers/dynamic_mixin_compiler.rb +198 -0
  35. data/lib/tapioca/compilers/requires_compiler.rb +2 -2
  36. data/lib/tapioca/compilers/sorbet.rb +25 -5
  37. data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +122 -206
  38. data/lib/tapioca/compilers/symbol_table/symbol_loader.rb +4 -4
  39. data/lib/tapioca/compilers/symbol_table_compiler.rb +5 -11
  40. data/lib/tapioca/compilers/todos_compiler.rb +1 -1
  41. data/lib/tapioca/config.rb +3 -0
  42. data/lib/tapioca/config_builder.rb +5 -2
  43. data/lib/tapioca/constant_locator.rb +6 -8
  44. data/lib/tapioca/gemfile.rb +14 -11
  45. data/lib/tapioca/generators/base.rb +61 -0
  46. data/lib/tapioca/generators/dsl.rb +362 -0
  47. data/lib/tapioca/generators/gem.rb +345 -0
  48. data/lib/tapioca/generators/init.rb +79 -0
  49. data/lib/tapioca/generators/require.rb +52 -0
  50. data/lib/tapioca/generators/todo.rb +76 -0
  51. data/lib/tapioca/generators.rb +9 -0
  52. data/lib/tapioca/generic_type_registry.rb +25 -98
  53. data/lib/tapioca/helpers/active_record_column_type_helper.rb +98 -0
  54. data/lib/tapioca/internal.rb +2 -10
  55. data/lib/tapioca/loader.rb +11 -31
  56. data/lib/tapioca/rbi_ext/model.rb +166 -0
  57. data/lib/tapioca/reflection.rb +138 -0
  58. data/lib/tapioca/sorbet_ext/fixed_hash_patch.rb +1 -1
  59. data/lib/tapioca/sorbet_ext/generic_name_patch.rb +72 -4
  60. data/lib/tapioca/sorbet_ext/name_patch.rb +1 -1
  61. data/lib/tapioca/version.rb +1 -1
  62. data/lib/tapioca.rb +3 -0
  63. metadata +45 -23
  64. data/lib/tapioca/cli/main.rb +0 -146
  65. data/lib/tapioca/core_ext/class.rb +0 -28
  66. data/lib/tapioca/core_ext/string.rb +0 -18
  67. data/lib/tapioca/generator.rb +0 -633
  68. data/lib/tapioca/rbi/model.rb +0 -405
  69. data/lib/tapioca/rbi/printer.rb +0 -410
  70. data/lib/tapioca/rbi/rewriters/group_nodes.rb +0 -106
  71. data/lib/tapioca/rbi/rewriters/nest_non_public_methods.rb +0 -65
  72. data/lib/tapioca/rbi/rewriters/nest_singleton_methods.rb +0 -42
  73. data/lib/tapioca/rbi/rewriters/sort_nodes.rb +0 -86
  74. data/lib/tapioca/rbi/visitor.rb +0 -21
@@ -1,633 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require 'pathname'
5
- require 'thor'
6
- require "tapioca/core_ext/string"
7
-
8
- module Tapioca
9
- class Generator < ::Thor::Shell::Color
10
- extend(T::Sig)
11
-
12
- sig { returns(Config) }
13
- attr_reader :config
14
-
15
- sig do
16
- params(
17
- config: Config
18
- ).void
19
- end
20
- def initialize(config)
21
- @config = config
22
- @bundle = T.let(nil, T.nilable(Gemfile))
23
- @loader = T.let(nil, T.nilable(Loader))
24
- @compiler = T.let(nil, T.nilable(Compilers::SymbolTableCompiler))
25
- @existing_rbis = T.let(nil, T.nilable(T::Hash[String, String]))
26
- @expected_rbis = T.let(nil, T.nilable(T::Hash[String, String]))
27
- super()
28
- end
29
-
30
- sig { params(gem_names: T::Array[String]).void }
31
- def build_gem_rbis(gem_names)
32
- require_gem_file
33
-
34
- gems_to_generate(gem_names)
35
- .reject { |gem| config.exclude.include?(gem.name) }
36
- .each do |gem|
37
- say("Processing '#{gem.name}' gem:", :green)
38
- indent do
39
- compile_gem_rbi(gem)
40
- puts
41
- end
42
- end
43
-
44
- say("All operations performed in working directory.", [:green, :bold])
45
- say("Please review changes and commit them.", [:green, :bold])
46
- end
47
-
48
- sig { void }
49
- def build_requires
50
- requires_path = Config::DEFAULT_POSTREQUIRE
51
- compiler = Compilers::RequiresCompiler.new(Config::SORBET_CONFIG)
52
- name = set_color(requires_path, :yellow, :bold)
53
- say("Compiling #{name}, this may take a few seconds... ")
54
-
55
- rb_string = compiler.compile
56
- if rb_string.empty?
57
- say("Nothing to do", :green)
58
- return
59
- end
60
-
61
- # Clean all existing requires before regenerating the list so we update
62
- # it with the new one found in the client code and remove the old ones.
63
- File.delete(requires_path) if File.exist?(requires_path)
64
-
65
- content = String.new
66
- content << rbi_header(
67
- "#{Config::DEFAULT_COMMAND} require",
68
- reason: "explicit gem requires",
69
- strictness: "false"
70
- )
71
- content << rb_string
72
-
73
- outdir = File.dirname(requires_path)
74
- FileUtils.mkdir_p(outdir)
75
- File.write(requires_path, content)
76
-
77
- say("Done", :green)
78
-
79
- say("All requires from this application have been written to #{name}.", [:green, :bold])
80
- cmd = set_color("#{Config::DEFAULT_COMMAND} sync", :yellow, :bold)
81
- say("Please review changes and commit them, then run `#{cmd}`.", [:green, :bold])
82
- end
83
-
84
- sig { void }
85
- def build_todos
86
- todos_path = config.todos_path
87
- compiler = Compilers::TodosCompiler.new
88
- name = set_color(todos_path, :yellow, :bold)
89
- say("Compiling #{name}, this may take a few seconds... ")
90
-
91
- # Clean all existing unresolved constants before regenerating the list
92
- # so Sorbet won't grab them as already resolved.
93
- File.delete(todos_path) if File.exist?(todos_path)
94
-
95
- rbi_string = compiler.compile
96
- if rbi_string.empty?
97
- say("Nothing to do", :green)
98
- return
99
- end
100
-
101
- content = String.new
102
- content << rbi_header(
103
- "#{Config::DEFAULT_COMMAND} todo",
104
- reason: "unresolved constants",
105
- strictness: "false"
106
- )
107
- content << rbi_string
108
- content << "\n"
109
-
110
- outdir = File.dirname(todos_path)
111
- FileUtils.mkdir_p(outdir)
112
- File.write(todos_path, content)
113
-
114
- say("Done", :green)
115
-
116
- say("All unresolved constants have been written to #{name}.", [:green, :bold])
117
- say("Please review changes and commit them.", [:green, :bold])
118
- end
119
-
120
- sig do
121
- params(
122
- requested_constants: T::Array[String],
123
- should_verify: T::Boolean,
124
- quiet: T::Boolean
125
- ).void
126
- end
127
- def build_dsl(requested_constants, should_verify: false, quiet: false)
128
- load_application(eager_load: requested_constants.empty?)
129
- load_dsl_generators
130
-
131
- if should_verify
132
- say("Checking for out-of-date RBIs...")
133
- else
134
- say("Compiling DSL RBI files...")
135
- end
136
- say("")
137
-
138
- outpath = should_verify ? Pathname.new(Dir.mktmpdir) : config.outpath
139
- rbi_files_to_purge = existing_rbi_filenames(requested_constants)
140
-
141
- compiler = Compilers::DslCompiler.new(
142
- requested_constants: constantize(requested_constants),
143
- requested_generators: config.generators,
144
- error_handler: ->(error) {
145
- say_error(error, :bold, :red)
146
- }
147
- )
148
-
149
- compiler.run do |constant, contents|
150
- constant_name = Module.instance_method(:name).bind(constant).call
151
-
152
- filename = compile_dsl_rbi(
153
- constant_name,
154
- contents,
155
- outpath: outpath,
156
- quiet: should_verify || quiet
157
- )
158
-
159
- if filename
160
- rbi_files_to_purge.delete(filename)
161
- end
162
- end
163
- say("")
164
-
165
- if should_verify
166
- perform_dsl_verification(outpath)
167
- else
168
- purge_stale_dsl_rbi_files(rbi_files_to_purge)
169
-
170
- say("Done", :green)
171
-
172
- say("All operations performed in working directory.", [:green, :bold])
173
- say("Please review changes and commit them.", [:green, :bold])
174
- end
175
- end
176
-
177
- sig { void }
178
- def sync_rbis_with_gemfile
179
- anything_done = [
180
- perform_removals,
181
- perform_additions,
182
- ].any?
183
-
184
- if anything_done
185
- say("All operations performed in working directory.", [:green, :bold])
186
- say("Please review changes and commit them.", [:green, :bold])
187
- else
188
- say("No operations performed, all RBIs are up-to-date.", [:green, :bold])
189
- end
190
-
191
- puts
192
- end
193
-
194
- private
195
-
196
- EMPTY_RBI_COMMENT = <<~CONTENT
197
- # THIS IS AN EMPTY RBI FILE.
198
- # see https://github.com/Shopify/tapioca/blob/master/README.md#manual-gem-requires
199
- CONTENT
200
-
201
- sig { returns(Gemfile) }
202
- def bundle
203
- @bundle ||= Gemfile.new
204
- end
205
-
206
- sig { returns(Loader) }
207
- def loader
208
- @loader ||= Loader.new(bundle)
209
- end
210
-
211
- sig { returns(Compilers::SymbolTableCompiler) }
212
- def compiler
213
- @compiler ||= Compilers::SymbolTableCompiler.new
214
- end
215
-
216
- sig { void }
217
- def require_gem_file
218
- say("Requiring all gems to prepare for compiling... ")
219
- begin
220
- loader.load_bundle(config.prerequire, config.postrequire)
221
- rescue LoadError => e
222
- explain_failed_require(config.postrequire, e)
223
- exit(1)
224
- end
225
- say(" Done", :green)
226
- unless bundle.missing_specs.empty?
227
- say(" completed with missing specs: ")
228
- say(bundle.missing_specs.join(', '), :yellow)
229
- end
230
- puts
231
- end
232
-
233
- sig { params(file: String, error: LoadError).void }
234
- def explain_failed_require(file, error)
235
- say_error("\n\nLoadError: #{error}", :bold, :red)
236
- say_error("\nTapioca could not load all the gems required by your application.", :yellow)
237
- say_error("If you populated ", :yellow)
238
- say_error("#{file} ", :bold, :blue)
239
- say_error("with ", :yellow)
240
- say_error("`#{Config::DEFAULT_COMMAND} require`", :bold, :blue)
241
- say_error("you should probably review it and remove the faulty line.", :yellow)
242
- end
243
-
244
- sig do
245
- params(
246
- message: String,
247
- color: T.any(Symbol, T::Array[Symbol]),
248
- ).void
249
- end
250
- def say_error(message = "", *color)
251
- force_new_line = (message.to_s !~ /( |\t)\Z/)
252
- buffer = prepare_message(*T.unsafe([message, *T.unsafe(color)]))
253
- buffer << "\n" if force_new_line && !message.to_s.end_with?("\n")
254
-
255
- stderr.print(buffer)
256
- stderr.flush
257
- end
258
-
259
- sig { params(eager_load: T::Boolean).void }
260
- def load_application(eager_load:)
261
- say("Loading Rails application... ")
262
-
263
- loader.load_rails_application(
264
- environment_load: true,
265
- eager_load: eager_load
266
- )
267
-
268
- say("Done", :green)
269
- end
270
-
271
- sig { void }
272
- def load_dsl_generators
273
- say("Loading DSL generator classes... ")
274
-
275
- Dir.glob([
276
- "#{__dir__}/compilers/dsl/*.rb",
277
- "#{Config::TAPIOCA_PATH}/generators/**/*.rb",
278
- ]).each do |generator|
279
- require File.expand_path(generator)
280
- end
281
-
282
- say("Done", :green)
283
- end
284
-
285
- sig { params(constant_names: T::Array[String]).returns(T::Array[Module]) }
286
- def constantize(constant_names)
287
- constant_map = constant_names.map do |name|
288
- begin
289
- [name, Object.const_get(name)]
290
- rescue NameError
291
- [name, nil]
292
- end
293
- end.to_h
294
-
295
- unprocessable_constants = constant_map.select { |_, v| v.nil? }
296
- unless unprocessable_constants.empty?
297
- unprocessable_constants.each do |name, _|
298
- say("Error: Cannot find constant '#{name}'", :red)
299
- remove(dsl_rbi_filename(name))
300
- end
301
-
302
- exit(1)
303
- end
304
-
305
- constant_map.values
306
- end
307
-
308
- sig { params(requested_constants: T::Array[String], path: Pathname).returns(T::Set[Pathname]) }
309
- def existing_rbi_filenames(requested_constants, path: config.outpath)
310
- filenames = if requested_constants.empty?
311
- Pathname.glob(path / "**/*.rbi")
312
- else
313
- requested_constants.map do |constant_name|
314
- dsl_rbi_filename(constant_name)
315
- end
316
- end
317
-
318
- filenames.to_set
319
- end
320
-
321
- sig { returns(T::Hash[String, String]) }
322
- def existing_rbis
323
- @existing_rbis ||= Pathname.glob((config.outpath / "*@*.rbi").to_s)
324
- .map { |f| T.cast(f.basename(".*").to_s.split('@', 2), [String, String]) }
325
- .to_h
326
- end
327
-
328
- sig { returns(T::Hash[String, String]) }
329
- def expected_rbis
330
- @expected_rbis ||= bundle.dependencies
331
- .reject { |gem| config.exclude.include?(gem.name) }
332
- .map { |gem| [gem.name, gem.version.to_s] }
333
- .to_h
334
- end
335
-
336
- sig { params(constant_name: String).returns(Pathname) }
337
- def dsl_rbi_filename(constant_name)
338
- config.outpath / "#{constant_name.underscore}.rbi"
339
- end
340
-
341
- sig { params(gem_name: String, version: String).returns(Pathname) }
342
- def gem_rbi_filename(gem_name, version)
343
- config.outpath / "#{gem_name}@#{version}.rbi"
344
- end
345
-
346
- sig { params(gem_name: String).returns(Pathname) }
347
- def existing_rbi(gem_name)
348
- gem_rbi_filename(gem_name, T.must(existing_rbis[gem_name]))
349
- end
350
-
351
- sig { params(gem_name: String).returns(Pathname) }
352
- def expected_rbi(gem_name)
353
- gem_rbi_filename(gem_name, T.must(expected_rbis[gem_name]))
354
- end
355
-
356
- sig { params(gem_name: String).returns(T::Boolean) }
357
- def gem_rbi_exists?(gem_name)
358
- existing_rbis.key?(gem_name)
359
- end
360
-
361
- sig { returns(T::Array[String]) }
362
- def removed_rbis
363
- (existing_rbis.keys - expected_rbis.keys).sort
364
- end
365
-
366
- sig { returns(T::Array[String]) }
367
- def added_rbis
368
- expected_rbis.select do |name, value|
369
- existing_rbis[name] != value
370
- end.keys.sort
371
- end
372
-
373
- sig { params(filename: Pathname).void }
374
- def add(filename)
375
- say("++ Adding: #{filename}")
376
- end
377
-
378
- sig { params(filename: Pathname).void }
379
- def remove(filename)
380
- return unless filename.exist?
381
- say("-- Removing: #{filename}")
382
- filename.unlink
383
- end
384
-
385
- sig { params(old_filename: Pathname, new_filename: Pathname).void }
386
- def move(old_filename, new_filename)
387
- say("-> Moving: #{old_filename} to #{new_filename}")
388
- old_filename.rename(new_filename.to_s)
389
- end
390
-
391
- sig { void }
392
- def perform_removals
393
- say("Removing RBI files of gems that have been removed:", [:blue, :bold])
394
- puts
395
-
396
- anything_done = T.let(false, T::Boolean)
397
-
398
- gems = removed_rbis
399
-
400
- indent do
401
- if gems.empty?
402
- say("Nothing to do.")
403
- else
404
- gems.each do |removed|
405
- filename = existing_rbi(removed)
406
- remove(filename)
407
- end
408
-
409
- anything_done = true
410
- end
411
- end
412
-
413
- puts
414
-
415
- anything_done
416
- end
417
-
418
- sig { void }
419
- def perform_additions
420
- say("Generating RBI files of gems that are added or updated:", [:blue, :bold])
421
- puts
422
-
423
- anything_done = T.let(false, T::Boolean)
424
-
425
- gems = added_rbis
426
-
427
- indent do
428
- if gems.empty?
429
- say("Nothing to do.")
430
- else
431
- require_gem_file
432
-
433
- gems.each do |gem_name|
434
- filename = expected_rbi(gem_name)
435
-
436
- if gem_rbi_exists?(gem_name)
437
- old_filename = existing_rbi(gem_name)
438
- move(old_filename, filename) unless old_filename == filename
439
- end
440
-
441
- gem = T.must(bundle.gem(gem_name))
442
- compile_gem_rbi(gem)
443
- add(filename)
444
-
445
- puts
446
- end
447
- end
448
-
449
- anything_done = true
450
- end
451
-
452
- puts
453
-
454
- anything_done
455
- end
456
-
457
- sig do
458
- params(gem_names: T::Array[String])
459
- .returns(T::Array[Gemfile::GemSpec])
460
- end
461
- def gems_to_generate(gem_names)
462
- return bundle.dependencies if gem_names.empty?
463
-
464
- gem_names.map do |gem_name|
465
- gem = bundle.gem(gem_name)
466
- if gem.nil?
467
- say("Error: Cannot find gem '#{gem_name}'", :red)
468
- exit(1)
469
- end
470
- gem
471
- end
472
- end
473
-
474
- sig { params(command: String, reason: T.nilable(String), strictness: T.nilable(String)).returns(String) }
475
- def rbi_header(command, reason: nil, strictness: nil)
476
- statement = <<~HEAD
477
- # DO NOT EDIT MANUALLY
478
- # This is an autogenerated file for #{reason}.
479
- # Please instead update this file by running `#{command}`.
480
- HEAD
481
-
482
- sigil = <<~SIGIL if strictness
483
- # typed: #{strictness}
484
- SIGIL
485
-
486
- [statement, sigil].compact.join("\n").strip.concat("\n\n")
487
- end
488
-
489
- sig { params(gem: Gemfile::GemSpec).void }
490
- def compile_gem_rbi(gem)
491
- compiler = Compilers::SymbolTableCompiler.new
492
- gem_name = set_color(gem.name, :yellow, :bold)
493
- say("Compiling #{gem_name}, this may take a few seconds... ")
494
-
495
- strictness = config.typed_overrides[gem.name] || "true"
496
- rbi_body_content = compiler.compile(gem)
497
- content = String.new
498
- content << rbi_header(
499
- "#{Config::DEFAULT_COMMAND} sync",
500
- reason: "types exported from the `#{gem.name}` gem",
501
- strictness: strictness
502
- )
503
-
504
- FileUtils.mkdir_p(config.outdir)
505
- filename = config.outpath / gem.rbi_file_name
506
-
507
- if rbi_body_content.strip.empty?
508
- content << EMPTY_RBI_COMMENT
509
- say("Done (empty output)", :yellow)
510
- else
511
- content << rbi_body_content
512
- say("Done", :green)
513
- end
514
- File.write(filename.to_s, content)
515
-
516
- T.unsafe(Pathname).glob((config.outpath / "#{gem.name}@*.rbi").to_s) do |file|
517
- remove(file) unless file.basename.to_s == gem.rbi_file_name
518
- end
519
- end
520
-
521
- sig do
522
- params(constant_name: String, contents: String, outpath: Pathname, quiet: T::Boolean)
523
- .returns(T.nilable(Pathname))
524
- end
525
- def compile_dsl_rbi(constant_name, contents, outpath: config.outpath, quiet: false)
526
- return if contents.nil?
527
-
528
- rbi_name = constant_name.underscore + ".rbi"
529
- filename = outpath / rbi_name
530
-
531
- out = String.new
532
- out << rbi_header(
533
- "#{Config::DEFAULT_COMMAND} dsl #{constant_name}",
534
- reason: "dynamic methods in `#{constant_name}`"
535
- )
536
- out << contents
537
-
538
- FileUtils.mkdir_p(File.dirname(filename))
539
- File.write(filename, out)
540
-
541
- unless quiet
542
- say("Wrote: ", [:green])
543
- say(filename)
544
- end
545
-
546
- filename
547
- end
548
-
549
- sig { params(tmp_dir: Pathname).returns(T::Hash[String, Symbol]) }
550
- def verify_dsl_rbi(tmp_dir:)
551
- diff = {}
552
-
553
- existing_rbis = rbi_files_in(config.outpath)
554
- new_rbis = rbi_files_in(tmp_dir)
555
-
556
- added_files = (new_rbis - existing_rbis)
557
-
558
- added_files.each do |file|
559
- diff[file] = :added
560
- end
561
-
562
- removed_files = (existing_rbis - new_rbis)
563
-
564
- removed_files.each do |file|
565
- diff[file] = :removed
566
- end
567
-
568
- common_files = (existing_rbis & new_rbis)
569
-
570
- changed_files = common_files.map do |filename|
571
- filename unless FileUtils.identical?(config.outpath / filename, tmp_dir / filename)
572
- end.compact
573
-
574
- changed_files.each do |file|
575
- diff[file] = :changed
576
- end
577
-
578
- diff
579
- end
580
-
581
- sig { params(cause: Symbol, files: T::Array[String]).returns(String) }
582
- def build_error_for_files(cause, files)
583
- filenames = files.map do |file|
584
- config.outpath / file
585
- end.join("\n - ")
586
-
587
- " File(s) #{cause}:\n - #{filenames}"
588
- end
589
-
590
- sig { params(path: Pathname).returns(T::Array[Pathname]) }
591
- def rbi_files_in(path)
592
- Pathname.glob(path / "**/*.rbi").map do |file|
593
- file.relative_path_from(path)
594
- end.sort
595
- end
596
-
597
- sig { params(dir: Pathname).void }
598
- def perform_dsl_verification(dir)
599
- diff = verify_dsl_rbi(tmp_dir: dir)
600
-
601
- if diff.empty?
602
- say("Nothing to do, all RBIs are up-to-date.")
603
- else
604
- say("RBI files are out-of-date. In your development environment, please run:", :green)
605
- say(" `#{Config::DEFAULT_COMMAND} dsl`", [:green, :bold])
606
- say("Once it is complete, be sure to commit and push any changes", :green)
607
-
608
- say("")
609
-
610
- say("Reason:", [:red])
611
- diff.group_by(&:last).sort.each do |cause, diff_for_cause|
612
- say(build_error_for_files(cause, diff_for_cause.map(&:first)))
613
- end
614
-
615
- exit(1)
616
- end
617
- ensure
618
- FileUtils.remove_entry(dir)
619
- end
620
-
621
- sig { params(files: T::Set[Pathname]).void }
622
- def purge_stale_dsl_rbi_files(files)
623
- if files.any?
624
- say("Removing stale RBI files...")
625
-
626
- files.sort.each do |filename|
627
- remove(filename)
628
- end
629
- say("")
630
- end
631
- end
632
- end
633
- end