tapioca 0.9.4 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +21 -0
  3. data/README.md +48 -22
  4. data/lib/tapioca/cli.rb +17 -23
  5. data/lib/tapioca/commands/annotations.rb +2 -2
  6. data/lib/tapioca/commands/dsl.rb +43 -65
  7. data/lib/tapioca/commands/gem.rb +18 -50
  8. data/lib/tapioca/commands/todo.rb +1 -2
  9. data/lib/tapioca/dsl/compiler.rb +34 -37
  10. data/lib/tapioca/dsl/compilers/aasm.rb +7 -3
  11. data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +7 -3
  12. data/lib/tapioca/dsl/compilers/action_mailer.rb +7 -3
  13. data/lib/tapioca/dsl/compilers/active_job.rb +7 -3
  14. data/lib/tapioca/dsl/compilers/active_model_attributes.rb +9 -5
  15. data/lib/tapioca/dsl/compilers/active_model_secure_password.rb +11 -7
  16. data/lib/tapioca/dsl/compilers/active_record_associations.rb +7 -3
  17. data/lib/tapioca/dsl/compilers/active_record_columns.rb +7 -3
  18. data/lib/tapioca/dsl/compilers/active_record_enum.rb +7 -3
  19. data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +8 -4
  20. data/lib/tapioca/dsl/compilers/active_record_relations.rb +7 -3
  21. data/lib/tapioca/dsl/compilers/active_record_scope.rb +5 -3
  22. data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +8 -4
  23. data/lib/tapioca/dsl/compilers/active_resource.rb +7 -3
  24. data/lib/tapioca/dsl/compilers/active_storage.rb +9 -5
  25. data/lib/tapioca/dsl/compilers/active_support_concern.rb +21 -18
  26. data/lib/tapioca/dsl/compilers/active_support_current_attributes.rb +7 -3
  27. data/lib/tapioca/dsl/compilers/config.rb +12 -8
  28. data/lib/tapioca/dsl/compilers/frozen_record.rb +7 -3
  29. data/lib/tapioca/dsl/compilers/graphql_input_object.rb +71 -0
  30. data/lib/tapioca/dsl/compilers/graphql_mutation.rb +81 -0
  31. data/lib/tapioca/dsl/compilers/identity_cache.rb +8 -4
  32. data/lib/tapioca/dsl/compilers/mixed_in_class_attributes.rb +9 -5
  33. data/lib/tapioca/dsl/compilers/protobuf.rb +69 -25
  34. data/lib/tapioca/dsl/compilers/rails_generators.rb +12 -8
  35. data/lib/tapioca/dsl/compilers/sidekiq_worker.rb +7 -3
  36. data/lib/tapioca/dsl/compilers/smart_properties.rb +10 -6
  37. data/lib/tapioca/dsl/compilers/state_machines.rb +7 -3
  38. data/lib/tapioca/dsl/compilers/url_helpers.rb +29 -26
  39. data/lib/tapioca/dsl/compilers.rb +0 -5
  40. data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +1 -9
  41. data/lib/tapioca/dsl/helpers/graphql_type_helper.rb +62 -0
  42. data/lib/tapioca/dsl/pipeline.rb +19 -11
  43. data/lib/tapioca/gem/listeners/source_location.rb +16 -9
  44. data/lib/tapioca/gemfile.rb +30 -0
  45. data/lib/tapioca/helpers/config_helper.rb +2 -2
  46. data/lib/tapioca/helpers/rbi_helper.rb +43 -30
  47. data/lib/tapioca/helpers/source_uri.rb +77 -0
  48. data/lib/tapioca/helpers/test/dsl_compiler.rb +1 -1
  49. data/lib/tapioca/helpers/test/isolation.rb +7 -3
  50. data/lib/tapioca/internal.rb +5 -1
  51. data/lib/tapioca/loaders/dsl.rb +84 -0
  52. data/lib/tapioca/loaders/gem.rb +85 -0
  53. data/lib/tapioca/{runtime → loaders}/loader.rb +39 -31
  54. data/lib/tapioca/repo_index.rb +12 -8
  55. data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +2 -2
  56. data/lib/tapioca/runtime/trackers/constant_definition.rb +15 -13
  57. data/lib/tapioca/runtime/trackers/mixin.rb +35 -31
  58. data/lib/tapioca/runtime/trackers/required_ancestor.rb +21 -19
  59. data/lib/tapioca/static/requires_compiler.rb +2 -3
  60. data/lib/tapioca/static/symbol_table_parser.rb +19 -17
  61. data/lib/tapioca/version.rb +1 -1
  62. data/lib/tapioca.rb +24 -20
  63. metadata +10 -5
  64. data/Gemfile +0 -53
  65. data/Rakefile +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 212af3a2ba5204b2aa479e52acddf879f32755faaee95691ce51e5c26b306481
4
- data.tar.gz: e8f957c96874e08fed7cce1580ac110c41bef0853c6f52f2e46c90bb6435bfe8
3
+ metadata.gz: 9c7d5aa34969c7dc1bcd885ac0438e4a76d945ca23e7a5942d88d1aa679d4b75
4
+ data.tar.gz: 0d6fd32d3388e33804bbdbb6cddcd904f724cc3071864219b6fcb88377cb5816
5
5
  SHA512:
6
- metadata.gz: fe339f96a20827fd80cb4134ccfcb258319ea43017f8b0f98170792e8732e464e468efeed7f7c0092fb095fff1e62e2f79f51113bbc6cff78e45b9cf288febc3
7
- data.tar.gz: dafe9aeaa6118b98c1c4a5e40064a55aacf7bc883d9ffb406bca0edd8bfecacb52b7f1f0c898bb8b09fa2c3101c9a88e3ba812fbbd3f71c15837fb110b241e69
6
+ metadata.gz: fdda19a3d7e5033fb96a3703c6b2f35030fc72ec5299072c8d41db071df61bbe4fcd28c5e68637199c793b52713f0177ffc55086fce58fb7b443194a8de5d2a4
7
+ data.tar.gz: 7ad308fc2d306370e5a246c9ef548b0199d597027e6c4561f93b7aff4a31ac98f26d2cdc4e5cb836704c1351d634505a71f9a87cfef899899fea0f07ab8d0795
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019-present, Shopify Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -30,6 +30,31 @@ Tapioca makes it easy to work with [Sorbet](https://sorbet.org) in your codebase
30
30
  * Find useless definitions in shim RBI files from Sorbet's embedded RBI for core and stdlib
31
31
  * Synchronization validation for your CI
32
32
 
33
+ ## Table of Contents <!-- no_toc -->
34
+ <!-- START_TOC -->
35
+ * [Installation](#installation)
36
+ * [Getting started](#getting-started)
37
+ * [Usage](#usage)
38
+ * [Generating RBI files for gems](#generating-rbi-files-for-gems)
39
+ * [Manually requiring parts of a gem](#manually-requiring-parts-of-a-gem)
40
+ * [Excluding a gem from RBI generation](#excluding-a-gem-from-rbi-generation)
41
+ * [Changing the strictness level of the RBI for a gem](#changing-the-strictness-level-of-the-rbi-for-a-gem)
42
+ * [Keeping RBI files for gems up-to-date](#keeping-rbi-files-for-gems-up-to-date)
43
+ * [Pulling RBI annotations from remote sources](#pulling-rbi-annotations-from-remote-sources)
44
+ * [Basic authentication](#basic-authentication)
45
+ * [Using a .netrc file](#using-a-netrc-file)
46
+ * [Changing the typed strictness of annotations files](#changing-the-typed-strictness-of-annotations-files)
47
+ * [Generating RBI files for Rails and other DSLs](#generating-rbi-files-for-rails-and-other-dsls)
48
+ * [Keeping RBI files for DSLs up-to-date](#keeping-rbi-files-for-dsls-up-to-date)
49
+ * [Writing custom DSL compilers](#writing-custom-dsl-compilers)
50
+ * [RBI files for missing constants and methods](#rbi-files-for-missing-constants-and-methods)
51
+ * [Generating the RBI file for missing constants](#generating-the-rbi-file-for-missing-constants)
52
+ * [Manually writing RBI definitions (shims)](#manually-writing-rbi-definitions-shims)
53
+ * [Configuration](#configuration)
54
+ * [Contributing](#contributing)
55
+ * [License](#license)
56
+ <!-- END_TOC -->
57
+
33
58
  ## Installation
34
59
 
35
60
  Add this line to your application's `Gemfile`:
@@ -156,8 +181,7 @@ Options:
156
181
  # Default: true
157
182
  [--exported-gem-rbis], [--no-exported-gem-rbis] # Include RBIs found in the `rbi/` directory of the gem
158
183
  # Default: true
159
- -w, [--workers=N] # EXPERIMENTAL: Number of parallel workers to use when generating RBIs
160
- # Default: 1
184
+ -w, [--workers=N] # Number of parallel workers to use when generating RBIs (default: auto)
161
185
  [--auto-strictness], [--no-auto-strictness] # Autocorrect strictness in gem RBIs in case of conflict with the DSL RBIs
162
186
  # Default: true
163
187
  --dsl-dir, [--dsl-dir=directory] # The DSL directory used to correct gems strictnesses
@@ -434,23 +458,23 @@ Usage:
434
458
  tapioca dsl [constant...]
435
459
 
436
460
  Options:
437
- --out, -o, [--outdir=directory] # The output directory for generated DSL RBI files
438
- # Default: sorbet/rbi/dsl
439
- [--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
440
- # Default: true
441
- [--only=compiler [compiler ...]] # Only run supplied DSL compiler(s)
442
- [--exclude=compiler [compiler ...]] # Exclude supplied DSL compiler(s)
443
- [--verify], [--no-verify] # Verifies RBIs are up-to-date
444
- -q, [--quiet], [--no-quiet] # Suppresses file creation output
445
- -w, [--workers=N] # EXPERIMENTAL: Number of parallel workers to use when generating RBIs
446
- # Default: 1
447
- [--rbi-max-line-length=N] # Set the max line length of generated RBIs. Signatures longer than the max line length will be wrapped
448
- # Default: 120
449
- -e, [--environment=ENVIRONMENT] # The Rack/Rails environment to use when generating RBIs
450
- # Default: development
451
- -c, [--config=<config file path>] # Path to the Tapioca configuration file
452
- # Default: sorbet/tapioca/config.yml
453
- -V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
461
+ --out, -o, [--outdir=directory] # The output directory for generated DSL RBI files
462
+ # Default: sorbet/rbi/dsl
463
+ [--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
464
+ # Default: true
465
+ [--only=compiler [compiler ...]] # Only run supplied DSL compiler(s)
466
+ [--exclude=compiler [compiler ...]] # Exclude supplied DSL compiler(s)
467
+ [--verify], [--no-verify] # Verifies RBIs are up-to-date
468
+ -q, [--quiet], [--no-quiet] # Suppresses file creation output
469
+ -w, [--workers=N] # Number of parallel workers to use when generating RBIs (default: auto)
470
+ [--rbi-max-line-length=N] # Set the max line length of generated RBIs. Signatures longer than the max line length will be wrapped
471
+ # Default: 120
472
+ -e, [--environment=ENVIRONMENT] # The Rack/Rails environment to use when generating RBIs
473
+ # Default: development
474
+ -l, [--list-compilers], [--no-list-compilers] # List all loaded compilers
475
+ -c, [--config=<config file path>] # Path to the Tapioca configuration file
476
+ # Default: sorbet/tapioca/config.yml
477
+ -V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
454
478
 
455
479
  generate RBIs for dynamic methods
456
480
  ```
@@ -568,7 +592,7 @@ Errors: 5
568
592
 
569
593
  To solve this you will have to create your own DSL compiler able that understands the `Encryptable` DSL and can generate the RBI definitions representing the actual shape of `CreditCard` at runtime.
570
594
 
571
- To do so, create the new DSL compiler inside the `sorbet/tapioca/compilers` directory of your application with the following contents:
595
+ To do so, you need to create a new DSL compiler similar to the following:
572
596
 
573
597
  ```rb
574
598
  module Tapioca
@@ -603,6 +627,8 @@ module Tapioca
603
627
  end
604
628
  ```
605
629
 
630
+ In order for this DSL compiler to be discovered by Tapioca, it either needs to be placed inside the `sorbet/tapioca/compilers` directory of your application or be inside a `tapioca/dsl/compilers` folder on the load path. For example, if `Encryptable` was being exposed by a gem, all the gem needs to do is to place the DSL compiler inside the `lib/tapioca/dsl/compilers` folder and it will be automatically discovered and loaded by Tapioca.
631
+
606
632
  There are two main parts to the DSL compiler API: `gather_constants` and `decorate`:
607
633
 
608
634
  * The `gather_constants` class method collects all classes (or modules) that should be processed by this specific DSL compiler.
@@ -742,8 +768,7 @@ Options:
742
768
  # Default: sorbet/rbi/todo.rbi
743
769
  [--payload], [--no-payload] # Check shims against Sorbet's payload
744
770
  # Default: true
745
- -w, [--workers=N] # EXPERIMENTAL: Number of parallel workers
746
- # Default: 1
771
+ -w, [--workers=N] # Number of parallel workers (default: auto)
747
772
  -c, [--config=<config file path>] # Path to the Tapioca configuration file
748
773
  # Default: sorbet/tapioca/config.yml
749
774
  -V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
@@ -795,6 +820,7 @@ dsl:
795
820
  workers: 1
796
821
  rbi_max_line_length: 120
797
822
  environment: development
823
+ list_compilers: false
798
824
  gem:
799
825
  outdir: sorbet/rbi/gems
800
826
  file_header: true
data/lib/tapioca/cli.rb CHANGED
@@ -105,8 +105,7 @@ module Tapioca
105
105
  option :workers,
106
106
  aliases: ["-w"],
107
107
  type: :numeric,
108
- desc: "EXPERIMENTAL: Number of parallel workers to use when generating RBIs",
109
- default: 1
108
+ desc: "Number of parallel workers to use when generating RBIs (default: auto)"
110
109
  option :rbi_max_line_length,
111
110
  type: :numeric,
112
111
  desc: "Set the max line length of generated RBIs. Signatures longer than the max line length will be wrapped",
@@ -116,6 +115,11 @@ module Tapioca
116
115
  type: :string,
117
116
  desc: "The Rack/Rails environment to use when generating RBIs",
118
117
  default: DEFAULT_ENVIRONMENT
118
+ option :list_compilers,
119
+ aliases: ["-l"],
120
+ type: :boolean,
121
+ desc: "List all loaded compilers",
122
+ default: false
119
123
  def dsl(*constants)
120
124
  set_environment(options)
121
125
 
@@ -125,7 +129,6 @@ module Tapioca
125
129
  only: options[:only],
126
130
  exclude: options[:exclude],
127
131
  file_header: options[:file_header],
128
- compiler_path: Tapioca::Dsl::Compilers::DIRECTORY,
129
132
  tapioca_path: TAPIOCA_DIR,
130
133
  should_verify: options[:verify],
131
134
  quiet: options[:quiet],
@@ -134,15 +137,12 @@ module Tapioca
134
137
  rbi_formatter: rbi_formatter(options)
135
138
  )
136
139
 
137
- if options[:workers] != 1
138
- say(
139
- "Using more than one worker is experimental and might produce results that are not deterministic",
140
- :red
141
- )
142
- end
143
-
144
140
  Tapioca.silence_warnings do
145
- command.execute
141
+ if options[:list_compilers]
142
+ command.list_compilers
143
+ else
144
+ command.execute
145
+ end
146
146
  end
147
147
  end
148
148
 
@@ -201,8 +201,7 @@ module Tapioca
201
201
  option :workers,
202
202
  aliases: ["-w"],
203
203
  type: :numeric,
204
- desc: "EXPERIMENTAL: Number of parallel workers to use when generating RBIs",
205
- default: 1
204
+ desc: "Number of parallel workers to use when generating RBIs (default: auto)"
206
205
  option :auto_strictness,
207
206
  type: :boolean,
208
207
  desc: "Autocorrect strictness in gem RBIs in case of conflict with the DSL RBIs",
@@ -252,13 +251,6 @@ module Tapioca
252
251
  raise MalformattedArgumentError, "Option '--verify' must be provided without any other arguments" if verify
253
252
  end
254
253
 
255
- if options[:workers] != 1
256
- say(
257
- "Using more than one worker is experimental and might produce results that are not deterministic",
258
- :red
259
- )
260
- end
261
-
262
254
  if gems.empty? && !all
263
255
  command.sync(should_verify: verify, exclude: options[:exclude])
264
256
  else
@@ -275,7 +267,7 @@ module Tapioca
275
267
  option :annotations_rbi_dir, type: :string, desc: "Path to annotations RBIs", default: DEFAULT_ANNOTATIONS_DIR
276
268
  option :todo_rbi_file, type: :string, desc: "Path to the generated todo RBI file", default: DEFAULT_TODO_FILE
277
269
  option :payload, type: :boolean, desc: "Check shims against Sorbet's payload", default: true
278
- option :workers, aliases: ["-w"], type: :numeric, desc: "EXPERIMENTAL: Number of parallel workers", default: 1
270
+ option :workers, aliases: ["-w"], type: :numeric, desc: "Number of parallel workers (default: auto)"
279
271
  def check_shims
280
272
  Tapioca.disable_traces
281
273
 
@@ -325,8 +317,10 @@ module Tapioca
325
317
  end
326
318
 
327
319
  no_commands do
328
- def self.exit_on_failure?
329
- true
320
+ class << self
321
+ def exit_on_failure?
322
+ true
323
+ end
330
324
  end
331
325
  end
332
326
 
@@ -247,13 +247,13 @@ module Tapioca
247
247
  sig { returns(T::Hash[String, T.nilable(String)]) }
248
248
  def repo_tokens
249
249
  @netrc_info = Netrc.read(@netrc_file) if @netrc_file
250
- @central_repo_root_uris.map do |uri|
250
+ @central_repo_root_uris.filter_map do |uri|
251
251
  if @auth
252
252
  [uri, @auth]
253
253
  else
254
254
  [uri, token_for(uri)]
255
255
  end
256
- end.compact.to_h
256
+ end.to_h
257
257
  end
258
258
 
259
259
  sig { params(repo_uri: String).returns(T.nilable(String)) }
@@ -14,7 +14,6 @@ module Tapioca
14
14
  only: T::Array[String],
15
15
  exclude: T::Array[String],
16
16
  file_header: T::Boolean,
17
- compiler_path: String,
18
17
  tapioca_path: String,
19
18
  should_verify: T::Boolean,
20
19
  quiet: T::Boolean,
@@ -31,7 +30,6 @@ module Tapioca
31
30
  only:,
32
31
  exclude:,
33
32
  file_header:,
34
- compiler_path:,
35
33
  tapioca_path:,
36
34
  should_verify: false,
37
35
  quiet: false,
@@ -46,7 +44,6 @@ module Tapioca
46
44
  @only = only
47
45
  @exclude = exclude
48
46
  @file_header = file_header
49
- @compiler_path = compiler_path
50
47
  @tapioca_path = tapioca_path
51
48
  @should_verify = should_verify
52
49
  @quiet = quiet
@@ -57,16 +54,40 @@ module Tapioca
57
54
  @rbi_formatter = rbi_formatter
58
55
 
59
56
  super()
57
+ end
58
+
59
+ sig { void }
60
+ def list_compilers
61
+ Loaders::Dsl.load_application(
62
+ tapioca_path: @tapioca_path,
63
+ eager_load: @requested_constants.empty?
64
+ )
65
+
66
+ pipeline = create_pipeline
67
+
68
+ say("")
69
+ say("Loaded DSL compiler classes:")
70
+ say("")
71
+
72
+ table = pipeline.compilers.map do |compiler|
73
+ status = if pipeline.active_compilers.include?(compiler)
74
+ set_color("enabled", :green)
75
+ else
76
+ set_color("disabled", :red)
77
+ end
78
+
79
+ [compiler.name, status]
80
+ end
60
81
 
61
- @loader = T.let(nil, T.nilable(Runtime::Loader))
82
+ print_table(table, { indent: 2 })
62
83
  end
63
84
 
64
85
  sig { override.void }
65
86
  def execute
66
- load_dsl_extensions
67
- load_application(eager_load: @requested_constants.empty?)
68
- abort_if_pending_migrations!
69
- load_dsl_compilers
87
+ Loaders::Dsl.load_application(
88
+ tapioca_path: @tapioca_path,
89
+ eager_load: @requested_constants.empty?
90
+ )
70
91
 
71
92
  if @should_verify
72
93
  say("Checking for out-of-date RBIs...")
@@ -78,15 +99,7 @@ module Tapioca
78
99
  outpath = @should_verify ? Pathname.new(Dir.mktmpdir) : @outpath
79
100
  rbi_files_to_purge = existing_rbi_filenames(@requested_constants)
80
101
 
81
- pipeline = Tapioca::Dsl::Pipeline.new(
82
- requested_constants: constantize(@requested_constants),
83
- requested_compilers: constantize_compilers(@only),
84
- excluded_compilers: constantize_compilers(@exclude),
85
- error_handler: ->(error) {
86
- say_error(error, :bold, :red)
87
- },
88
- number_of_workers: @number_of_workers
89
- )
102
+ pipeline = create_pipeline
90
103
 
91
104
  processed_files = pipeline.run do |constant, contents|
92
105
  constant_name = T.must(Tapioca::Runtime::Reflection.name_of(constant))
@@ -120,7 +133,7 @@ module Tapioca
120
133
  gem_dir: @gem_dir,
121
134
  dsl_dir: @outpath.to_s,
122
135
  auto_strictness: @auto_strictness,
123
- compilers: pipeline.compilers
136
+ compilers: pipeline.active_compilers
124
137
  )
125
138
  end
126
139
 
@@ -131,42 +144,17 @@ module Tapioca
131
144
 
132
145
  private
133
146
 
134
- sig { params(eager_load: T::Boolean).void }
135
- def load_application(eager_load:)
136
- say("Loading Rails application... ")
137
-
138
- loader.load_rails_application(
139
- environment_load: true,
140
- eager_load: eager_load
147
+ sig { returns(Tapioca::Dsl::Pipeline) }
148
+ def create_pipeline
149
+ Tapioca::Dsl::Pipeline.new(
150
+ requested_constants: constantize(@requested_constants),
151
+ requested_compilers: constantize_compilers(@only),
152
+ excluded_compilers: constantize_compilers(@exclude),
153
+ error_handler: ->(error) {
154
+ say_error(error, :bold, :red)
155
+ },
156
+ number_of_workers: @number_of_workers
141
157
  )
142
-
143
- say("Done", :green)
144
- end
145
-
146
- sig { void }
147
- def abort_if_pending_migrations!
148
- return unless File.exist?("config/application.rb")
149
- return unless defined?(::Rake)
150
-
151
- Rails.application.load_tasks
152
- if Rake::Task.task_defined?("db:abort_if_pending_migrations")
153
- Rake::Task["db:abort_if_pending_migrations"].invoke
154
- end
155
- end
156
-
157
- sig { void }
158
- def load_dsl_compilers
159
- say("Loading DSL compiler classes... ")
160
-
161
- Dir.glob([
162
- "#{@compiler_path}/*.rb",
163
- "#{@tapioca_path}/generators/**/*.rb", # TODO: Here for backcompat, remove later
164
- "#{@tapioca_path}/compilers/**/*.rb",
165
- ]).each do |compiler|
166
- require File.expand_path(compiler)
167
- end
168
-
169
- say("Done", :green)
170
158
  end
171
159
 
172
160
  sig { params(requested_constants: T::Array[String], path: Pathname).returns(T::Set[Pathname]) }
@@ -309,9 +297,9 @@ module Tapioca
309
297
 
310
298
  common_files = (existing_rbis & new_rbis)
311
299
 
312
- changed_files = common_files.map do |filename|
300
+ changed_files = common_files.filter_map do |filename|
313
301
  filename unless FileUtils.identical?(@outpath / filename, tmp_dir / filename)
314
- end.compact
302
+ end
315
303
 
316
304
  changed_files.each do |file|
317
305
  diff[file] = :changed
@@ -356,11 +344,6 @@ module Tapioca
356
344
  end.sort
357
345
  end
358
346
 
359
- sig { returns(Runtime::Loader) }
360
- def loader
361
- @loader ||= Runtime::Loader.new
362
- end
363
-
364
347
  sig { params(class_name: String).returns(String) }
365
348
  def underscore(class_name)
366
349
  return class_name unless /[A-Z-]|::/.match?(class_name)
@@ -382,11 +365,6 @@ module Tapioca
382
365
  def generate_command_for(constant)
383
366
  default_command(:dsl, constant)
384
367
  end
385
-
386
- sig { void }
387
- def load_dsl_extensions
388
- Dir["#{__dir__}/../dsl/extensions/*.rb"].sort.each { |f| require(f) }
389
- end
390
368
  end
391
369
  end
392
370
  end
@@ -55,8 +55,7 @@ module Tapioca
55
55
 
56
56
  super()
57
57
 
58
- @loader = T.let(nil, T.nilable(Runtime::Loader))
59
- @bundle = T.let(nil, T.nilable(Gemfile))
58
+ @bundle = T.let(Gemfile.new(exclude), Gemfile)
60
59
  @existing_rbis = T.let(nil, T.nilable(T::Hash[String, String]))
61
60
  @expected_rbis = T.let(nil, T.nilable(T::Hash[String, String]))
62
61
  @include_doc = T.let(include_doc, T::Boolean)
@@ -66,7 +65,12 @@ module Tapioca
66
65
 
67
66
  sig { override.void }
68
67
  def execute
69
- require_gem_file
68
+ Loaders::Gem.load_application(
69
+ bundle: @bundle,
70
+ prerequire: @prerequire,
71
+ postrequire: @postrequire,
72
+ default_command: default_command(:require),
73
+ )
70
74
 
71
75
  gem_queue = gems_to_generate(@gem_names).reject { |gem| @exclude.include?(gem.name) }
72
76
  anything_done = [
@@ -87,7 +91,7 @@ module Tapioca
87
91
  gem_dir: @outpath.to_s,
88
92
  dsl_dir: @dsl_dir,
89
93
  auto_strictness: @auto_strictness,
90
- gems: bundle.dependencies
94
+ gems: @bundle.dependencies
91
95
  )
92
96
 
93
97
  say("All operations performed in working directory.", [:green, :bold])
@@ -117,7 +121,7 @@ module Tapioca
117
121
  gem_dir: @outpath.to_s,
118
122
  dsl_dir: @dsl_dir,
119
123
  auto_strictness: @auto_strictness,
120
- gems: bundle.dependencies
124
+ gems: @bundle.dependencies
121
125
  )
122
126
 
123
127
  say("All operations performed in working directory.", [:green, :bold])
@@ -131,39 +135,9 @@ module Tapioca
131
135
 
132
136
  private
133
137
 
134
- sig { returns(Runtime::Loader) }
135
- def loader
136
- @loader ||= Runtime::Loader.new
137
- end
138
-
139
- sig { returns(Gemfile) }
140
- def bundle
141
- @bundle ||= Gemfile.new(@exclude)
142
- end
143
-
144
- sig { void }
145
- def require_gem_file
146
- say("Requiring all gems to prepare for compiling... ")
147
- begin
148
- loader.load_bundle(bundle, @prerequire, @postrequire)
149
- rescue LoadError => e
150
- explain_failed_require(@postrequire, e)
151
- exit(1)
152
- end
153
-
154
- Runtime::Trackers::Autoload.eager_load_all!
155
-
156
- say(" Done", :green)
157
- unless bundle.missing_specs.empty?
158
- say(" completed with missing specs: ")
159
- say(bundle.missing_specs.join(", "), :yellow)
160
- end
161
- puts
162
- end
163
-
164
138
  sig { params(gem_names: T::Array[String]).returns(T::Array[Gemfile::GemSpec]) }
165
139
  def gems_to_generate(gem_names)
166
- return bundle.dependencies if gem_names.empty?
140
+ return @bundle.dependencies if gem_names.empty?
167
141
 
168
142
  gem_names.map do |gem_name|
169
143
  gem = @bundle.gem(gem_name)
@@ -264,7 +238,12 @@ module Tapioca
264
238
  if gems.empty?
265
239
  say("Nothing to do.")
266
240
  else
267
- require_gem_file
241
+ Loaders::Gem.load_application(
242
+ bundle: @bundle,
243
+ prerequire: @prerequire,
244
+ postrequire: @postrequire,
245
+ default_command: default_command(:require),
246
+ )
268
247
 
269
248
  Executor.new(gems, number_of_workers: @number_of_workers).run_in_parallel do |gem_name|
270
249
  filename = expected_rbi(gem_name)
@@ -274,7 +253,7 @@ module Tapioca
274
253
  move(old_filename, filename) unless old_filename == filename
275
254
  end
276
255
 
277
- gem = T.must(bundle.gem(gem_name))
256
+ gem = T.must(@bundle.gem(gem_name))
278
257
  compile_gem_rbi(gem)
279
258
  puts
280
259
  end
@@ -288,17 +267,6 @@ module Tapioca
288
267
  anything_done
289
268
  end
290
269
 
291
- sig { params(file: String, error: LoadError).void }
292
- def explain_failed_require(file, error)
293
- say_error("\n\nLoadError: #{error}", :bold, :red)
294
- say_error("\nTapioca could not load all the gems required by your application.", :yellow)
295
- say_error("If you populated ", :yellow)
296
- say_error("#{file} ", :bold, :blue)
297
- say_error("with ", :yellow)
298
- say_error("`#{default_command(:require)}`", :bold, :blue)
299
- say_error("you should probably review it and remove the faulty line.", :yellow)
300
- end
301
-
302
270
  sig { returns(T::Array[String]) }
303
271
  def removed_rbis
304
272
  (existing_rbis.keys - expected_rbis.keys).sort
@@ -360,7 +328,7 @@ module Tapioca
360
328
 
361
329
  sig { returns(T::Hash[String, String]) }
362
330
  def expected_rbis
363
- @expected_rbis ||= bundle.dependencies
331
+ @expected_rbis ||= @bundle.dependencies
364
332
  .reject { |gem| @exclude.include?(gem.name) }
365
333
  .to_h { |gem| [gem.name, gem.version.to_s] }
366
334
  end
@@ -72,13 +72,12 @@ module Tapioca
72
72
  .out
73
73
  .strip
74
74
  .each_line
75
- .map do |line|
75
+ .filter_map do |line|
76
76
  next if line.include?("<")
77
77
 
78
78
  line.strip
79
79
  .gsub(/T\.class_of\(([:\w]+)\)/, '\1') # Turn T.class_of(Foo)::Bar into Foo::Bar
80
80
  end
81
- .compact
82
81
  .sort
83
82
  end
84
83
  end