tapioca 0.6.4 → 0.7.2
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 +4 -4
- data/Gemfile +8 -2
- data/README.md +27 -15
- data/Rakefile +10 -14
- data/lib/tapioca/cli.rb +65 -80
- data/lib/tapioca/{generators/base.rb → commands/command.rb} +16 -9
- data/lib/tapioca/{generators → commands}/dsl.rb +59 -45
- data/lib/tapioca/{generators → commands}/gem.rb +93 -30
- data/lib/tapioca/{generators → commands}/init.rb +9 -13
- data/lib/tapioca/{generators → commands}/require.rb +8 -10
- data/lib/tapioca/commands/todo.rb +86 -0
- data/lib/tapioca/commands.rb +13 -0
- data/lib/tapioca/dsl/compiler.rb +185 -0
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/aasm.rb +12 -9
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/action_controller_helpers.rb +13 -20
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/action_mailer.rb +10 -8
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_job.rb +11 -9
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_model_attributes.rb +13 -11
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_model_secure_password.rb +10 -12
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_associations.rb +28 -34
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_columns.rb +18 -16
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_enum.rb +14 -12
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_fixtures.rb +12 -8
- data/lib/tapioca/dsl/compilers/active_record_relations.rb +712 -0
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_scope.rb +21 -20
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_typed_store.rb +11 -16
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_resource.rb +10 -8
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_storage.rb +14 -10
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_support_concern.rb +19 -14
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_support_current_attributes.rb +16 -21
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/config.rb +11 -9
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/frozen_record.rb +13 -11
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/identity_cache.rb +23 -22
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/mixed_in_class_attributes.rb +12 -10
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/protobuf.rb +22 -10
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/rails_generators.rb +12 -13
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/sidekiq_worker.rb +14 -13
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/smart_properties.rb +11 -9
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/state_machines.rb +12 -10
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/url_helpers.rb +20 -15
- data/lib/tapioca/dsl/compilers.rb +31 -0
- data/lib/tapioca/{compilers/dsl → dsl}/extensions/frozen_record.rb +2 -2
- data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +114 -0
- data/lib/tapioca/dsl/helpers/active_record_constants_helper.rb +29 -0
- data/lib/tapioca/{compilers/dsl → dsl/helpers}/param_helper.rb +6 -3
- data/lib/tapioca/dsl/pipeline.rb +169 -0
- data/lib/tapioca/gem/events.rb +120 -0
- data/lib/tapioca/gem/listeners/base.rb +48 -0
- data/lib/tapioca/gem/listeners/dynamic_mixins.rb +32 -0
- data/lib/tapioca/gem/listeners/methods.rb +183 -0
- data/lib/tapioca/gem/listeners/mixins.rb +101 -0
- data/lib/tapioca/gem/listeners/remove_empty_payload_scopes.rb +21 -0
- data/lib/tapioca/gem/listeners/sorbet_enums.rb +26 -0
- data/lib/tapioca/gem/listeners/sorbet_helpers.rb +29 -0
- data/lib/tapioca/gem/listeners/sorbet_props.rb +33 -0
- data/lib/tapioca/gem/listeners/sorbet_required_ancestors.rb +23 -0
- data/lib/tapioca/gem/listeners/sorbet_signatures.rb +79 -0
- data/lib/tapioca/gem/listeners/sorbet_type_variables.rb +51 -0
- data/lib/tapioca/gem/listeners/subconstants.rb +37 -0
- data/lib/tapioca/gem/listeners/yard_doc.rb +96 -0
- data/lib/tapioca/gem/listeners.rb +16 -0
- data/lib/tapioca/gem/pipeline.rb +365 -0
- data/lib/tapioca/helpers/cli_helper.rb +7 -0
- data/lib/tapioca/helpers/config_helper.rb +5 -8
- data/lib/tapioca/helpers/shims_helper.rb +87 -0
- data/lib/tapioca/helpers/signatures_helper.rb +17 -0
- data/lib/tapioca/helpers/sorbet_helper.rb +57 -0
- data/lib/tapioca/helpers/test/dsl_compiler.rb +118 -0
- data/lib/tapioca/helpers/test/isolation.rb +1 -1
- data/lib/tapioca/helpers/test/template.rb +13 -2
- data/lib/tapioca/helpers/type_variable_helper.rb +43 -0
- data/lib/tapioca/internal.rb +18 -10
- data/lib/tapioca/rbi_ext/model.rb +14 -50
- data/lib/tapioca/rbi_formatter.rb +37 -0
- data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +227 -0
- data/lib/tapioca/runtime/generic_type_registry.rb +168 -0
- data/lib/tapioca/runtime/loader.rb +123 -0
- data/lib/tapioca/runtime/reflection.rb +157 -0
- data/lib/tapioca/runtime/trackers/autoload.rb +72 -0
- data/lib/tapioca/runtime/trackers/constant_definition.rb +44 -0
- data/lib/tapioca/runtime/trackers/mixin.rb +80 -0
- data/lib/tapioca/runtime/trackers/required_ancestor.rb +50 -0
- data/lib/tapioca/{trackers.rb → runtime/trackers.rb} +4 -3
- data/lib/tapioca/sorbet_ext/generic_name_patch.rb +69 -34
- data/lib/tapioca/sorbet_ext/name_patch.rb +7 -1
- data/lib/tapioca/{compilers → static}/requires_compiler.rb +2 -2
- data/lib/tapioca/static/symbol_loader.rb +83 -0
- data/lib/tapioca/static/symbol_table_parser.rb +63 -0
- data/lib/tapioca/version.rb +1 -1
- data/lib/tapioca.rb +2 -7
- metadata +83 -62
- data/lib/tapioca/compilers/dsl/active_record_relations.rb +0 -720
- data/lib/tapioca/compilers/dsl/base.rb +0 -195
- data/lib/tapioca/compilers/dsl/helper/active_record_constants.rb +0 -27
- data/lib/tapioca/compilers/dsl_compiler.rb +0 -134
- data/lib/tapioca/compilers/dynamic_mixin_compiler.rb +0 -223
- data/lib/tapioca/compilers/sorbet.rb +0 -59
- data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +0 -780
- data/lib/tapioca/compilers/symbol_table/symbol_loader.rb +0 -90
- data/lib/tapioca/compilers/symbol_table_compiler.rb +0 -17
- data/lib/tapioca/compilers/todos_compiler.rb +0 -32
- data/lib/tapioca/generators/todo.rb +0 -76
- data/lib/tapioca/generators.rb +0 -9
- data/lib/tapioca/generic_type_registry.rb +0 -164
- data/lib/tapioca/helpers/active_record_column_type_helper.rb +0 -108
- data/lib/tapioca/loader.rb +0 -119
- data/lib/tapioca/reflection.rb +0 -151
- data/lib/tapioca/trackers/autoload.rb +0 -70
- data/lib/tapioca/trackers/constant_definition.rb +0 -42
- data/lib/tapioca/trackers/mixin.rb +0 -78
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module Tapioca
|
|
5
|
-
module
|
|
6
|
-
class Dsl <
|
|
5
|
+
module Commands
|
|
6
|
+
class Dsl < Command
|
|
7
7
|
sig do
|
|
8
8
|
params(
|
|
9
9
|
requested_constants: T::Array[String],
|
|
@@ -13,12 +13,11 @@ module Tapioca
|
|
|
13
13
|
file_header: T::Boolean,
|
|
14
14
|
compiler_path: String,
|
|
15
15
|
tapioca_path: String,
|
|
16
|
-
default_command: String,
|
|
17
|
-
file_writer: Thor::Actions,
|
|
18
16
|
should_verify: T::Boolean,
|
|
19
17
|
quiet: T::Boolean,
|
|
20
18
|
verbose: T::Boolean,
|
|
21
19
|
number_of_workers: T.nilable(Integer),
|
|
20
|
+
rbi_formatter: RBIFormatter
|
|
22
21
|
).void
|
|
23
22
|
end
|
|
24
23
|
def initialize(
|
|
@@ -29,12 +28,11 @@ module Tapioca
|
|
|
29
28
|
file_header:,
|
|
30
29
|
compiler_path:,
|
|
31
30
|
tapioca_path:,
|
|
32
|
-
default_command:,
|
|
33
|
-
file_writer: FileWriter.new,
|
|
34
31
|
should_verify: false,
|
|
35
32
|
quiet: false,
|
|
36
33
|
verbose: false,
|
|
37
|
-
number_of_workers: nil
|
|
34
|
+
number_of_workers: nil,
|
|
35
|
+
rbi_formatter: DEFAULT_RBI_FORMATTER
|
|
38
36
|
)
|
|
39
37
|
@requested_constants = requested_constants
|
|
40
38
|
@outpath = outpath
|
|
@@ -47,18 +45,19 @@ module Tapioca
|
|
|
47
45
|
@quiet = quiet
|
|
48
46
|
@verbose = verbose
|
|
49
47
|
@number_of_workers = number_of_workers
|
|
48
|
+
@rbi_formatter = rbi_formatter
|
|
50
49
|
|
|
51
|
-
super(
|
|
50
|
+
super()
|
|
52
51
|
|
|
53
|
-
@loader = T.let(nil, T.nilable(Loader))
|
|
52
|
+
@loader = T.let(nil, T.nilable(Runtime::Loader))
|
|
54
53
|
end
|
|
55
54
|
|
|
56
55
|
sig { override.void }
|
|
57
|
-
def
|
|
56
|
+
def execute
|
|
58
57
|
load_dsl_extensions
|
|
59
58
|
load_application(eager_load: @requested_constants.empty?)
|
|
60
59
|
abort_if_pending_migrations!
|
|
61
|
-
|
|
60
|
+
load_dsl_compilers
|
|
62
61
|
|
|
63
62
|
if @should_verify
|
|
64
63
|
say("Checking for out-of-date RBIs...")
|
|
@@ -70,18 +69,18 @@ module Tapioca
|
|
|
70
69
|
outpath = @should_verify ? Pathname.new(Dir.mktmpdir) : @outpath
|
|
71
70
|
rbi_files_to_purge = existing_rbi_filenames(@requested_constants)
|
|
72
71
|
|
|
73
|
-
|
|
72
|
+
pipeline = Tapioca::Dsl::Pipeline.new(
|
|
74
73
|
requested_constants: constantize(@requested_constants),
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
requested_compilers: constantize_compilers(@only),
|
|
75
|
+
excluded_compilers: constantize_compilers(@exclude),
|
|
77
76
|
error_handler: ->(error) {
|
|
78
77
|
say_error(error, :bold, :red)
|
|
79
78
|
},
|
|
80
79
|
number_of_workers: @number_of_workers
|
|
81
80
|
)
|
|
82
81
|
|
|
83
|
-
processed_files =
|
|
84
|
-
constant_name = T.must(Reflection.name_of(constant))
|
|
82
|
+
processed_files = pipeline.run do |constant, contents|
|
|
83
|
+
constant_name = T.must(Tapioca::Runtime::Reflection.name_of(constant))
|
|
85
84
|
|
|
86
85
|
if @verbose && !@quiet
|
|
87
86
|
say_status(:processing, constant_name, :yellow)
|
|
@@ -91,7 +90,7 @@ module Tapioca
|
|
|
91
90
|
constant_name,
|
|
92
91
|
contents,
|
|
93
92
|
outpath: outpath,
|
|
94
|
-
quiet: @should_verify || @quiet && !@verbose
|
|
93
|
+
quiet: @should_verify || (@quiet && !@verbose)
|
|
95
94
|
)
|
|
96
95
|
end
|
|
97
96
|
|
|
@@ -137,14 +136,15 @@ module Tapioca
|
|
|
137
136
|
end
|
|
138
137
|
|
|
139
138
|
sig { void }
|
|
140
|
-
def
|
|
141
|
-
say("Loading DSL
|
|
139
|
+
def load_dsl_compilers
|
|
140
|
+
say("Loading DSL compiler classes... ")
|
|
142
141
|
|
|
143
142
|
Dir.glob([
|
|
144
143
|
"#{@compiler_path}/*.rb",
|
|
145
|
-
"#{@tapioca_path}/generators/**/*.rb",
|
|
146
|
-
|
|
147
|
-
|
|
144
|
+
"#{@tapioca_path}/generators/**/*.rb", # TODO: Here for backcompat, remove later
|
|
145
|
+
"#{@tapioca_path}/compilers/**/*.rb",
|
|
146
|
+
]).each do |compiler|
|
|
147
|
+
require File.expand_path(compiler)
|
|
148
148
|
end
|
|
149
149
|
|
|
150
150
|
say("Done", :green)
|
|
@@ -165,11 +165,11 @@ module Tapioca
|
|
|
165
165
|
|
|
166
166
|
sig { params(constant_names: T::Array[String]).returns(T::Array[Module]) }
|
|
167
167
|
def constantize(constant_names)
|
|
168
|
-
constant_map = constant_names.
|
|
168
|
+
constant_map = constant_names.to_h do |name|
|
|
169
169
|
[name, Object.const_get(name)]
|
|
170
170
|
rescue NameError
|
|
171
171
|
[name, nil]
|
|
172
|
-
end
|
|
172
|
+
end
|
|
173
173
|
|
|
174
174
|
unprocessable_constants = constant_map.select { |_, v| v.nil? }
|
|
175
175
|
unless unprocessable_constants.empty?
|
|
@@ -185,22 +185,35 @@ module Tapioca
|
|
|
185
185
|
constant_map.values
|
|
186
186
|
end
|
|
187
187
|
|
|
188
|
-
sig { params(
|
|
189
|
-
def
|
|
190
|
-
|
|
191
|
-
[name,
|
|
188
|
+
sig { params(compiler_names: T::Array[String]).returns(T::Array[T.class_of(Tapioca::Dsl::Compiler)]) }
|
|
189
|
+
def constantize_compilers(compiler_names)
|
|
190
|
+
compiler_map = compiler_names.to_h do |name|
|
|
191
|
+
[name, resolve(name)]
|
|
192
192
|
end
|
|
193
193
|
|
|
194
|
-
|
|
195
|
-
unless
|
|
196
|
-
|
|
197
|
-
say("Error: Cannot find
|
|
194
|
+
unprocessable_compilers = compiler_map.select { |_, v| v.nil? }
|
|
195
|
+
unless unprocessable_compilers.empty?
|
|
196
|
+
unprocessable_compilers.each do |name, _|
|
|
197
|
+
say("Error: Cannot find compiler '#{name}'", :red)
|
|
198
198
|
end
|
|
199
199
|
|
|
200
200
|
exit(1)
|
|
201
201
|
end
|
|
202
202
|
|
|
203
|
-
T.cast(
|
|
203
|
+
T.cast(compiler_map.values, T::Array[T.class_of(Tapioca::Dsl::Compiler)])
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
sig { params(name: String).returns(T.nilable(T.class_of(Tapioca::Dsl::Compiler))) }
|
|
207
|
+
def resolve(name)
|
|
208
|
+
# Try to find built-in tapioca compiler first, then globally defined compiler.
|
|
209
|
+
potentials = Tapioca::Dsl::Compilers::NAMESPACES.map do |namespace|
|
|
210
|
+
Object.const_get(namespace + name)
|
|
211
|
+
rescue NameError
|
|
212
|
+
# Skip if we can't find compiler by the potential name
|
|
213
|
+
nil
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
potentials.compact.first
|
|
204
217
|
end
|
|
205
218
|
|
|
206
219
|
sig do
|
|
@@ -216,13 +229,14 @@ module Tapioca
|
|
|
216
229
|
|
|
217
230
|
filename = outpath / rbi_filename_for(constant_name)
|
|
218
231
|
|
|
219
|
-
|
|
232
|
+
@rbi_formatter.write_header!(
|
|
233
|
+
rbi,
|
|
220
234
|
generate_command_for(constant_name),
|
|
221
|
-
reason: "dynamic methods in `#{constant_name}`"
|
|
222
|
-
|
|
223
|
-
)
|
|
235
|
+
reason: "dynamic methods in `#{constant_name}`"
|
|
236
|
+
) if @file_header
|
|
224
237
|
|
|
225
|
-
|
|
238
|
+
rbi_string = @rbi_formatter.print_file(rbi)
|
|
239
|
+
create_file(filename, rbi_string, verbose: !quiet)
|
|
226
240
|
|
|
227
241
|
filename
|
|
228
242
|
end
|
|
@@ -231,7 +245,7 @@ module Tapioca
|
|
|
231
245
|
def perform_dsl_verification(dir)
|
|
232
246
|
diff = verify_dsl_rbi(tmp_dir: dir)
|
|
233
247
|
|
|
234
|
-
report_diff_and_exit_if_out_of_date(diff,
|
|
248
|
+
report_diff_and_exit_if_out_of_date(diff, :dsl)
|
|
235
249
|
ensure
|
|
236
250
|
FileUtils.remove_entry(dir)
|
|
237
251
|
end
|
|
@@ -294,13 +308,13 @@ module Tapioca
|
|
|
294
308
|
" File(s) #{cause}:\n - #{filenames}"
|
|
295
309
|
end
|
|
296
310
|
|
|
297
|
-
sig { params(diff: T::Hash[String, Symbol], command:
|
|
311
|
+
sig { params(diff: T::Hash[String, Symbol], command: Symbol).void }
|
|
298
312
|
def report_diff_and_exit_if_out_of_date(diff, command)
|
|
299
313
|
if diff.empty?
|
|
300
314
|
say("Nothing to do, all RBIs are up-to-date.")
|
|
301
315
|
else
|
|
302
316
|
say("RBI files are out-of-date. In your development environment, please run:", :green)
|
|
303
|
-
say(" `#{
|
|
317
|
+
say(" `#{default_command(command)}`", [:green, :bold])
|
|
304
318
|
say("Once it is complete, be sure to commit and push any changes", :green)
|
|
305
319
|
|
|
306
320
|
say("")
|
|
@@ -321,9 +335,9 @@ module Tapioca
|
|
|
321
335
|
end.sort
|
|
322
336
|
end
|
|
323
337
|
|
|
324
|
-
sig { returns(Loader) }
|
|
338
|
+
sig { returns(Runtime::Loader) }
|
|
325
339
|
def loader
|
|
326
|
-
@loader ||= Loader.new
|
|
340
|
+
@loader ||= Runtime::Loader.new
|
|
327
341
|
end
|
|
328
342
|
|
|
329
343
|
sig { params(class_name: String).returns(String) }
|
|
@@ -345,12 +359,12 @@ module Tapioca
|
|
|
345
359
|
|
|
346
360
|
sig { params(constant: String).returns(String) }
|
|
347
361
|
def generate_command_for(constant)
|
|
348
|
-
|
|
362
|
+
default_command(:dsl, constant)
|
|
349
363
|
end
|
|
350
364
|
|
|
351
365
|
sig { void }
|
|
352
366
|
def load_dsl_extensions
|
|
353
|
-
Dir["#{__dir__}/../
|
|
367
|
+
Dir["#{__dir__}/../dsl/extensions/*.rb"].sort.each { |f| require(f) }
|
|
354
368
|
end
|
|
355
369
|
end
|
|
356
370
|
end
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module Tapioca
|
|
5
|
-
module
|
|
6
|
-
class Gem <
|
|
5
|
+
module Commands
|
|
6
|
+
class Gem < Command
|
|
7
|
+
include SorbetHelper
|
|
8
|
+
|
|
7
9
|
sig do
|
|
8
10
|
params(
|
|
9
11
|
gem_names: T::Array[String],
|
|
@@ -11,13 +13,14 @@ module Tapioca
|
|
|
11
13
|
prerequire: T.nilable(String),
|
|
12
14
|
postrequire: String,
|
|
13
15
|
typed_overrides: T::Hash[String, String],
|
|
14
|
-
default_command: String,
|
|
15
16
|
outpath: Pathname,
|
|
16
17
|
file_header: T::Boolean,
|
|
17
18
|
doc: T::Boolean,
|
|
18
19
|
include_exported_rbis: T::Boolean,
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
number_of_workers: T.nilable(Integer),
|
|
21
|
+
auto_strictness: T::Boolean,
|
|
22
|
+
dsl_dir: String,
|
|
23
|
+
rbi_formatter: RBIFormatter
|
|
21
24
|
).void
|
|
22
25
|
end
|
|
23
26
|
def initialize(
|
|
@@ -26,13 +29,14 @@ module Tapioca
|
|
|
26
29
|
prerequire:,
|
|
27
30
|
postrequire:,
|
|
28
31
|
typed_overrides:,
|
|
29
|
-
default_command:,
|
|
30
32
|
outpath:,
|
|
31
33
|
file_header:,
|
|
32
34
|
doc:,
|
|
33
35
|
include_exported_rbis:,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
number_of_workers: nil,
|
|
37
|
+
auto_strictness: true,
|
|
38
|
+
dsl_dir: DEFAULT_DSL_DIR,
|
|
39
|
+
rbi_formatter: DEFAULT_RBI_FORMATTER
|
|
36
40
|
)
|
|
37
41
|
@gem_names = gem_names
|
|
38
42
|
@exclude = exclude
|
|
@@ -42,10 +46,13 @@ module Tapioca
|
|
|
42
46
|
@outpath = outpath
|
|
43
47
|
@file_header = file_header
|
|
44
48
|
@number_of_workers = number_of_workers
|
|
49
|
+
@auto_strictness = auto_strictness
|
|
50
|
+
@dsl_dir = dsl_dir
|
|
51
|
+
@rbi_formatter = rbi_formatter
|
|
45
52
|
|
|
46
|
-
super(
|
|
53
|
+
super()
|
|
47
54
|
|
|
48
|
-
@loader = T.let(nil, T.nilable(Loader))
|
|
55
|
+
@loader = T.let(nil, T.nilable(Runtime::Loader))
|
|
49
56
|
@bundle = T.let(nil, T.nilable(Gemfile))
|
|
50
57
|
@existing_rbis = T.let(nil, T.nilable(T::Hash[String, String]))
|
|
51
58
|
@expected_rbis = T.let(nil, T.nilable(T::Hash[String, String]))
|
|
@@ -54,7 +61,7 @@ module Tapioca
|
|
|
54
61
|
end
|
|
55
62
|
|
|
56
63
|
sig { override.void }
|
|
57
|
-
def
|
|
64
|
+
def execute
|
|
58
65
|
require_gem_file
|
|
59
66
|
|
|
60
67
|
gem_queue = gems_to_generate(@gem_names).reject { |gem| @exclude.include?(gem.name) }
|
|
@@ -71,6 +78,8 @@ module Tapioca
|
|
|
71
78
|
end
|
|
72
79
|
|
|
73
80
|
if anything_done
|
|
81
|
+
update_strictnesses(gem_queue.map(&:name), gem_dir: @outpath.to_s, dsl_dir: @dsl_dir) if @auto_strictness
|
|
82
|
+
|
|
74
83
|
say("All operations performed in working directory.", [:green, :bold])
|
|
75
84
|
say("Please review changes and commit them.", [:green, :bold])
|
|
76
85
|
else
|
|
@@ -93,6 +102,8 @@ module Tapioca
|
|
|
93
102
|
].any?
|
|
94
103
|
|
|
95
104
|
if anything_done
|
|
105
|
+
update_strictnesses([], gem_dir: @outpath.to_s, dsl_dir: @dsl_dir) if @auto_strictness
|
|
106
|
+
|
|
96
107
|
say("All operations performed in working directory.", [:green, :bold])
|
|
97
108
|
say("Please review changes and commit them.", [:green, :bold])
|
|
98
109
|
else
|
|
@@ -104,9 +115,9 @@ module Tapioca
|
|
|
104
115
|
|
|
105
116
|
private
|
|
106
117
|
|
|
107
|
-
sig { returns(Loader) }
|
|
118
|
+
sig { returns(Runtime::Loader) }
|
|
108
119
|
def loader
|
|
109
|
-
@loader ||= Loader.new
|
|
120
|
+
@loader ||= Runtime::Loader.new
|
|
110
121
|
end
|
|
111
122
|
|
|
112
123
|
sig { returns(Gemfile) }
|
|
@@ -124,7 +135,7 @@ module Tapioca
|
|
|
124
135
|
exit(1)
|
|
125
136
|
end
|
|
126
137
|
|
|
127
|
-
|
|
138
|
+
Runtime::Trackers::Autoload.eager_load_all!
|
|
128
139
|
|
|
129
140
|
say(" Done", :green)
|
|
130
141
|
unless bundle.missing_specs.empty?
|
|
@@ -153,24 +164,24 @@ module Tapioca
|
|
|
153
164
|
gem_name = set_color(gem.name, :yellow, :bold)
|
|
154
165
|
|
|
155
166
|
rbi = RBI::File.new(strictness: @typed_overrides[gem.name] || "true")
|
|
156
|
-
rbi.set_file_header(
|
|
157
|
-
"#{@default_command} gem #{gem.name}",
|
|
158
|
-
reason: "types exported from the `#{gem.name}` gem",
|
|
159
|
-
display_heading: @file_header
|
|
160
|
-
)
|
|
161
167
|
|
|
162
|
-
|
|
168
|
+
@rbi_formatter.write_header!(rbi,
|
|
169
|
+
default_command(:gem, gem.name),
|
|
170
|
+
reason: "types exported from the `#{gem.name}` gem",) if @file_header
|
|
171
|
+
|
|
172
|
+
rbi.root = Tapioca::Gem::Pipeline.new(gem, include_doc: @doc).compile
|
|
163
173
|
|
|
164
174
|
merge_with_exported_rbi(gem, rbi) if @include_exported_rbis
|
|
165
175
|
|
|
166
176
|
if rbi.empty?
|
|
167
|
-
rbi
|
|
177
|
+
@rbi_formatter.write_empty_body_comment!(rbi)
|
|
168
178
|
say("Compiled #{gem_name} (empty output)", :yellow)
|
|
169
179
|
else
|
|
170
180
|
say("Compiled #{gem_name}", :green)
|
|
171
181
|
end
|
|
172
182
|
|
|
173
|
-
|
|
183
|
+
rbi_string = @rbi_formatter.print_file(rbi)
|
|
184
|
+
create_file(@outpath / gem.rbi_file_name, rbi_string)
|
|
174
185
|
|
|
175
186
|
T.unsafe(Pathname).glob((@outpath / "#{gem.name}@*.rbi").to_s) do |file|
|
|
176
187
|
remove_file(file) unless file.basename.to_s == gem.rbi_file_name
|
|
@@ -191,7 +202,7 @@ module Tapioca
|
|
|
191
202
|
diff[filename] = gem_rbi_exists?(gem_name) ? :changed : :added
|
|
192
203
|
end
|
|
193
204
|
|
|
194
|
-
report_diff_and_exit_if_out_of_date(diff,
|
|
205
|
+
report_diff_and_exit_if_out_of_date(diff, :gem)
|
|
195
206
|
end
|
|
196
207
|
|
|
197
208
|
sig { void }
|
|
@@ -265,7 +276,7 @@ module Tapioca
|
|
|
265
276
|
say_error("If you populated ", :yellow)
|
|
266
277
|
say_error("#{file} ", :bold, :blue)
|
|
267
278
|
say_error("with ", :yellow)
|
|
268
|
-
say_error("`#{
|
|
279
|
+
say_error("`#{default_command(:require)}`", :bold, :blue)
|
|
269
280
|
say_error("you should probably review it and remove the faulty line.", :yellow)
|
|
270
281
|
end
|
|
271
282
|
|
|
@@ -296,13 +307,13 @@ module Tapioca
|
|
|
296
307
|
existing_rbis.key?(gem_name)
|
|
297
308
|
end
|
|
298
309
|
|
|
299
|
-
sig { params(diff: T::Hash[String, Symbol], command:
|
|
310
|
+
sig { params(diff: T::Hash[String, Symbol], command: Symbol).void }
|
|
300
311
|
def report_diff_and_exit_if_out_of_date(diff, command)
|
|
301
312
|
if diff.empty?
|
|
302
313
|
say("Nothing to do, all RBIs are up-to-date.")
|
|
303
314
|
else
|
|
304
315
|
say("RBI files are out-of-date. In your development environment, please run:", :green)
|
|
305
|
-
say(" `#{
|
|
316
|
+
say(" `#{default_command(command)}`", [:green, :bold])
|
|
306
317
|
say("Once it is complete, be sure to commit and push any changes", :green)
|
|
307
318
|
|
|
308
319
|
say("")
|
|
@@ -325,16 +336,14 @@ module Tapioca
|
|
|
325
336
|
sig { returns(T::Hash[String, String]) }
|
|
326
337
|
def existing_rbis
|
|
327
338
|
@existing_rbis ||= Pathname.glob((@outpath / "*@*.rbi").to_s)
|
|
328
|
-
.
|
|
329
|
-
.to_h
|
|
339
|
+
.to_h { |f| T.cast(f.basename(".*").to_s.split("@", 2), [String, String]) }
|
|
330
340
|
end
|
|
331
341
|
|
|
332
342
|
sig { returns(T::Hash[String, String]) }
|
|
333
343
|
def expected_rbis
|
|
334
344
|
@expected_rbis ||= bundle.dependencies
|
|
335
345
|
.reject { |gem| @exclude.include?(gem.name) }
|
|
336
|
-
.
|
|
337
|
-
.to_h
|
|
346
|
+
.to_h { |gem| [gem.name, gem.version.to_s] }
|
|
338
347
|
end
|
|
339
348
|
|
|
340
349
|
sig { params(gem_name: String, version: String).returns(Pathname) }
|
|
@@ -370,6 +379,60 @@ module Tapioca
|
|
|
370
379
|
say_error("\n\n RBIs exported by `#{gem.name}` contain errors and can't be used:", :yellow)
|
|
371
380
|
say_error("Cause: #{e.message} (#{e.location})")
|
|
372
381
|
end
|
|
382
|
+
|
|
383
|
+
sig { params(gem_names: T::Array[String], gem_dir: String, dsl_dir: String).void }
|
|
384
|
+
def update_strictnesses(gem_names, gem_dir: DEFAULT_GEM_DIR, dsl_dir: DEFAULT_DSL_DIR)
|
|
385
|
+
return unless File.directory?(dsl_dir)
|
|
386
|
+
|
|
387
|
+
error_url_base = Spoom::Sorbet::Errors::DEFAULT_ERROR_URL_BASE
|
|
388
|
+
|
|
389
|
+
say("Typechecking RBI files... ")
|
|
390
|
+
res = sorbet(
|
|
391
|
+
"--no-config",
|
|
392
|
+
"--error-url-base=#{error_url_base}",
|
|
393
|
+
"--isolate-error-code 4010",
|
|
394
|
+
dsl_dir,
|
|
395
|
+
gem_dir
|
|
396
|
+
)
|
|
397
|
+
say(" Done", :green)
|
|
398
|
+
|
|
399
|
+
errors = Spoom::Sorbet::Errors::Parser.parse_string(res.err)
|
|
400
|
+
|
|
401
|
+
if errors.empty?
|
|
402
|
+
say("No error found", [:green, :bold])
|
|
403
|
+
return
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
files = []
|
|
407
|
+
|
|
408
|
+
errors.each do |error|
|
|
409
|
+
# Collect the file with error
|
|
410
|
+
files << error.file
|
|
411
|
+
error.more.each do |line|
|
|
412
|
+
# Also collect the conflicting definition file paths
|
|
413
|
+
next unless line.include?("Previous definition")
|
|
414
|
+
files << line.split(":").first&.strip
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
files
|
|
419
|
+
.uniq
|
|
420
|
+
.sort
|
|
421
|
+
.select do |file|
|
|
422
|
+
name = gem_name_from_rbi_path(file)
|
|
423
|
+
file.start_with?(gem_dir) && (gem_names.empty? || gem_names.include?(name))
|
|
424
|
+
end.each do |file|
|
|
425
|
+
Spoom::Sorbet::Sigils.change_sigil_in_file(file, "false")
|
|
426
|
+
say("\n Changed strictness of #{file} to `typed: false` (conflicting with DSL files)", [:yellow, :bold])
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
say("\n")
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
sig { params(path: String).returns(String) }
|
|
433
|
+
def gem_name_from_rbi_path(path)
|
|
434
|
+
T.must(File.basename(path, ".rbi").split("@").first)
|
|
435
|
+
end
|
|
373
436
|
end
|
|
374
437
|
end
|
|
375
438
|
end
|
|
@@ -2,36 +2,32 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module Tapioca
|
|
5
|
-
module
|
|
6
|
-
class Init <
|
|
5
|
+
module Commands
|
|
6
|
+
class Init < Command
|
|
7
7
|
sig do
|
|
8
8
|
params(
|
|
9
9
|
sorbet_config: String,
|
|
10
10
|
tapioca_config: String,
|
|
11
|
-
default_postrequire: String
|
|
12
|
-
default_command: String,
|
|
13
|
-
file_writer: Thor::Actions
|
|
11
|
+
default_postrequire: String
|
|
14
12
|
).void
|
|
15
13
|
end
|
|
16
14
|
def initialize(
|
|
17
15
|
sorbet_config:,
|
|
18
16
|
tapioca_config:,
|
|
19
|
-
default_postrequire
|
|
20
|
-
default_command:,
|
|
21
|
-
file_writer: FileWriter.new
|
|
17
|
+
default_postrequire:
|
|
22
18
|
)
|
|
23
19
|
@sorbet_config = sorbet_config
|
|
24
20
|
@tapioca_config = tapioca_config
|
|
25
21
|
@default_postrequire = default_postrequire
|
|
26
22
|
|
|
27
|
-
super(
|
|
23
|
+
super()
|
|
28
24
|
|
|
29
25
|
@installer = T.let(nil, T.nilable(Bundler::Installer))
|
|
30
26
|
@spec = T.let(nil, T.nilable(Bundler::StubSpecification))
|
|
31
27
|
end
|
|
32
28
|
|
|
33
29
|
sig { override.void }
|
|
34
|
-
def
|
|
30
|
+
def execute
|
|
35
31
|
create_sorbet_config
|
|
36
32
|
create_tapioca_config
|
|
37
33
|
create_post_require
|
|
@@ -73,19 +69,19 @@ module Tapioca
|
|
|
73
69
|
# typed: true
|
|
74
70
|
# frozen_string_literal: true
|
|
75
71
|
|
|
76
|
-
# Add your extra requires here (`#{
|
|
72
|
+
# Add your extra requires here (`#{default_command(:require)}` can be used to boostrap this list)
|
|
77
73
|
CONTENT
|
|
78
74
|
end
|
|
79
75
|
|
|
80
76
|
sig { void }
|
|
81
77
|
def create_binstub
|
|
82
|
-
force = File.exist?(
|
|
78
|
+
force = File.exist?(Tapioca::BINARY_FILE)
|
|
83
79
|
|
|
84
80
|
installer.generate_bundler_executable_stubs(spec, { force: force })
|
|
85
81
|
|
|
86
82
|
say_status(
|
|
87
83
|
force ? :force : :create,
|
|
88
|
-
|
|
84
|
+
Tapioca::BINARY_FILE,
|
|
89
85
|
force ? :yellow : :green
|
|
90
86
|
)
|
|
91
87
|
end
|
|
@@ -2,26 +2,24 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module Tapioca
|
|
5
|
-
module
|
|
6
|
-
class Require <
|
|
5
|
+
module Commands
|
|
6
|
+
class Require < Command
|
|
7
7
|
sig do
|
|
8
8
|
params(
|
|
9
9
|
requires_path: String,
|
|
10
|
-
sorbet_config_path: String
|
|
11
|
-
default_command: String,
|
|
12
|
-
file_writer: Thor::Actions
|
|
10
|
+
sorbet_config_path: String
|
|
13
11
|
).void
|
|
14
12
|
end
|
|
15
|
-
def initialize(requires_path:, sorbet_config_path
|
|
13
|
+
def initialize(requires_path:, sorbet_config_path:)
|
|
16
14
|
@requires_path = requires_path
|
|
17
15
|
@sorbet_config_path = sorbet_config_path
|
|
18
16
|
|
|
19
|
-
super(
|
|
17
|
+
super()
|
|
20
18
|
end
|
|
21
19
|
|
|
22
20
|
sig { override.void }
|
|
23
|
-
def
|
|
24
|
-
compiler =
|
|
21
|
+
def execute
|
|
22
|
+
compiler = Static::RequiresCompiler.new(@sorbet_config_path)
|
|
25
23
|
name = set_color(@requires_path, :yellow, :bold)
|
|
26
24
|
say("Compiling #{name}, this may take a few seconds... ")
|
|
27
25
|
|
|
@@ -44,7 +42,7 @@ module Tapioca
|
|
|
44
42
|
say("Done", :green)
|
|
45
43
|
|
|
46
44
|
say("All requires from this application have been written to #{name}.", [:green, :bold])
|
|
47
|
-
cmd = set_color(
|
|
45
|
+
cmd = set_color(default_command(:gem), :yellow, :bold)
|
|
48
46
|
say("Please review changes and commit them, then run `#{cmd}`.", [:green, :bold])
|
|
49
47
|
end
|
|
50
48
|
end
|