Skip to content

Commit d762b73

Browse files
authored
Merge pull request #1072 from Shopify/new-loader
Extract gem and dsl loaders in a new API
2 parents edbc6f7 + 22a4324 commit d762b73

File tree

7 files changed

+227
-140
lines changed

7 files changed

+227
-140
lines changed

lib/tapioca/cli.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ def dsl(*constants)
124124
only: options[:only],
125125
exclude: options[:exclude],
126126
file_header: options[:file_header],
127-
compiler_path: Tapioca::Dsl::Compilers::DIRECTORY,
127+
compilers_path: Tapioca::Dsl::Compilers::DIRECTORY,
128128
tapioca_path: TAPIOCA_DIR,
129129
should_verify: options[:verify],
130130
quiet: options[:quiet],

lib/tapioca/commands/dsl.rb

Lines changed: 8 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class Dsl < Command
1414
only: T::Array[String],
1515
exclude: T::Array[String],
1616
file_header: T::Boolean,
17-
compiler_path: String,
17+
compilers_path: String,
1818
tapioca_path: String,
1919
should_verify: T::Boolean,
2020
quiet: T::Boolean,
@@ -31,7 +31,7 @@ def initialize(
3131
only:,
3232
exclude:,
3333
file_header:,
34-
compiler_path:,
34+
compilers_path:,
3535
tapioca_path:,
3636
should_verify: false,
3737
quiet: false,
@@ -46,7 +46,7 @@ def initialize(
4646
@only = only
4747
@exclude = exclude
4848
@file_header = file_header
49-
@compiler_path = compiler_path
49+
@compilers_path = compilers_path
5050
@tapioca_path = tapioca_path
5151
@should_verify = should_verify
5252
@quiet = quiet
@@ -57,16 +57,15 @@ def initialize(
5757
@rbi_formatter = rbi_formatter
5858

5959
super()
60-
61-
@loader = T.let(nil, T.nilable(Runtime::Loader))
6260
end
6361

6462
sig { override.void }
6563
def execute
66-
load_dsl_extensions
67-
load_application(eager_load: @requested_constants.empty?)
68-
abort_if_pending_migrations!
69-
load_dsl_compilers
64+
Loaders::Dsl.load_application(
65+
tapioca_path: @tapioca_path,
66+
compilers_path: @compilers_path,
67+
eager_load: @requested_constants.empty?
68+
)
7069

7170
if @should_verify
7271
say("Checking for out-of-date RBIs...")
@@ -131,44 +130,6 @@ def execute
131130

132131
private
133132

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
141-
)
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-
end
171-
172133
sig { params(requested_constants: T::Array[String], path: Pathname).returns(T::Set[Pathname]) }
173134
def existing_rbi_filenames(requested_constants, path: @outpath)
174135
filenames = if requested_constants.empty?
@@ -354,11 +315,6 @@ def rbi_files_in(path)
354315
end.sort
355316
end
356317

357-
sig { returns(Runtime::Loader) }
358-
def loader
359-
@loader ||= Runtime::Loader.new
360-
end
361-
362318
sig { params(class_name: String).returns(String) }
363319
def underscore(class_name)
364320
return class_name unless /[A-Z-]|::/.match?(class_name)
@@ -380,11 +336,6 @@ def rbi_filename_for(constant)
380336
def generate_command_for(constant)
381337
default_command(:dsl, constant)
382338
end
383-
384-
sig { void }
385-
def load_dsl_extensions
386-
Dir["#{__dir__}/../dsl/extensions/*.rb"].sort.each { |f| require(f) }
387-
end
388339
end
389340
end
390341
end

lib/tapioca/commands/gem.rb

Lines changed: 19 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ def initialize(
5555

5656
super()
5757

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)
6059
@existing_rbis = T.let(nil, T.nilable(T::Hash[String, String]))
6160
@expected_rbis = T.let(nil, T.nilable(T::Hash[String, String]))
6261
@include_doc = T.let(include_doc, T::Boolean)
@@ -66,7 +65,12 @@ def initialize(
6665

6766
sig { override.void }
6867
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+
)
7074

7175
gem_queue = gems_to_generate(@gem_names).reject { |gem| @exclude.include?(gem.name) }
7276
anything_done = [
@@ -87,7 +91,7 @@ def execute
8791
gem_dir: @outpath.to_s,
8892
dsl_dir: @dsl_dir,
8993
auto_strictness: @auto_strictness,
90-
gems: bundle.dependencies
94+
gems: @bundle.dependencies
9195
)
9296

9397
say("All operations performed in working directory.", [:green, :bold])
@@ -117,7 +121,7 @@ def sync(should_verify: false, exclude: [])
117121
gem_dir: @outpath.to_s,
118122
dsl_dir: @dsl_dir,
119123
auto_strictness: @auto_strictness,
120-
gems: bundle.dependencies
124+
gems: @bundle.dependencies
121125
)
122126

123127
say("All operations performed in working directory.", [:green, :bold])
@@ -131,42 +135,12 @@ def sync(should_verify: false, exclude: [])
131135

132136
private
133137

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-
164138
sig { params(gem_names: T::Array[String]).returns(T::Array[Gemfile::GemSpec]) }
165139
def gems_to_generate(gem_names)
166-
return bundle.dependencies if gem_names.empty?
140+
return @bundle.dependencies if gem_names.empty?
167141

168142
gem_names.map do |gem_name|
169-
gem = bundle.gem(gem_name)
143+
gem = @bundle.gem(gem_name)
170144
if gem.nil?
171145
say("Error: Cannot find gem '#{gem_name}'", :red)
172146
exit(1)
@@ -263,7 +237,12 @@ def perform_additions
263237
if gems.empty?
264238
say("Nothing to do.")
265239
else
266-
require_gem_file
240+
Loaders::Gem.load_application(
241+
bundle: @bundle,
242+
prerequire: @prerequire,
243+
postrequire: @postrequire,
244+
default_command: default_command(:require),
245+
)
267246

268247
Executor.new(gems, number_of_workers: @number_of_workers).run_in_parallel do |gem_name|
269248
filename = expected_rbi(gem_name)
@@ -273,7 +252,7 @@ def perform_additions
273252
move(old_filename, filename) unless old_filename == filename
274253
end
275254

276-
gem = T.must(bundle.gem(gem_name))
255+
gem = T.must(@bundle.gem(gem_name))
277256
compile_gem_rbi(gem)
278257
puts
279258
end
@@ -287,17 +266,6 @@ def perform_additions
287266
anything_done
288267
end
289268

290-
sig { params(file: String, error: LoadError).void }
291-
def explain_failed_require(file, error)
292-
say_error("\n\nLoadError: #{error}", :bold, :red)
293-
say_error("\nTapioca could not load all the gems required by your application.", :yellow)
294-
say_error("If you populated ", :yellow)
295-
say_error("#{file} ", :bold, :blue)
296-
say_error("with ", :yellow)
297-
say_error("`#{default_command(:require)}`", :bold, :blue)
298-
say_error("you should probably review it and remove the faulty line.", :yellow)
299-
end
300-
301269
sig { returns(T::Array[String]) }
302270
def removed_rbis
303271
(existing_rbis.keys - expected_rbis.keys).sort
@@ -359,7 +327,7 @@ def existing_rbis
359327

360328
sig { returns(T::Hash[String, String]) }
361329
def expected_rbis
362-
@expected_rbis ||= bundle.dependencies
330+
@expected_rbis ||= @bundle.dependencies
363331
.reject { |gem| @exclude.include?(gem.name) }
364332
.to_h { |gem| [gem.name, gem.version.to_s] }
365333
end

lib/tapioca/internal.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727

2828
require "tapioca/runtime/dynamic_mixin_compiler"
2929
require "tapioca/helpers/gem_helper"
30-
require "tapioca/runtime/loader"
3130

3231
require "tapioca/helpers/sorbet_helper"
3332
require "tapioca/helpers/rbi_helper"
@@ -50,6 +49,10 @@
5049
require "tapioca/static/symbol_loader"
5150
require "tapioca/static/requires_compiler"
5251

52+
require "tapioca/loaders/loader"
53+
require "tapioca/loaders/gem"
54+
require "tapioca/loaders/dsl"
55+
5356
require "tapioca/gem"
5457
require "tapioca/dsl"
5558
require "tapioca/commands"

lib/tapioca/loaders/dsl.rb

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# typed: strict
2+
# frozen_string_literal: true
3+
4+
module Tapioca
5+
module Loaders
6+
class Dsl < Loader
7+
extend T::Sig
8+
9+
sig { params(tapioca_path: String, compilers_path: String, eager_load: T::Boolean).void }
10+
def self.load_application(tapioca_path:, compilers_path:, eager_load: true)
11+
loader = new(tapioca_path: tapioca_path, compilers_path: compilers_path)
12+
loader.load
13+
end
14+
15+
sig { override.void }
16+
def load
17+
load_dsl_extensions
18+
load_application
19+
abort_if_pending_migrations!
20+
load_dsl_compilers
21+
end
22+
23+
protected
24+
25+
sig { params(tapioca_path: String, compilers_path: String, eager_load: T::Boolean).void }
26+
def initialize(tapioca_path:, compilers_path:, eager_load: true)
27+
super()
28+
29+
@tapioca_path = tapioca_path
30+
@compilers_path = compilers_path
31+
@eager_load = eager_load
32+
end
33+
34+
sig { void }
35+
def load_dsl_extensions
36+
Dir["#{__dir__}/../dsl/extensions/*.rb"].sort.each { |f| require(f) }
37+
end
38+
39+
sig { void }
40+
def load_dsl_compilers
41+
say("Loading DSL compiler classes... ")
42+
43+
Dir.glob([
44+
"#{@compilers_path}/*.rb",
45+
"#{@tapioca_path}/generators/**/*.rb", # TODO: Here for backcompat, remove later
46+
"#{@tapioca_path}/compilers/**/*.rb",
47+
]).each do |compiler|
48+
require File.expand_path(compiler)
49+
end
50+
51+
say("Done", :green)
52+
end
53+
54+
sig { void }
55+
def load_application
56+
say("Loading Rails application... ")
57+
58+
load_rails_application(
59+
environment_load: true,
60+
eager_load: @eager_load
61+
)
62+
63+
say("Done", :green)
64+
end
65+
66+
sig { void }
67+
def abort_if_pending_migrations!
68+
return unless File.exist?("config/application.rb")
69+
return unless defined?(::Rake)
70+
71+
Rails.application.load_tasks
72+
if Rake::Task.task_defined?("db:abort_if_pending_migrations")
73+
Rake::Task["db:abort_if_pending_migrations"].invoke
74+
end
75+
end
76+
end
77+
end
78+
end

0 commit comments

Comments
 (0)