tapioca 0.9.4 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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