tapioca 0.16.9 → 0.17.7
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/README.md +21 -0
- data/exe/tapioca +6 -1
- data/lib/ruby_lsp/tapioca/addon.rb +73 -43
- data/lib/ruby_lsp/tapioca/run_gem_rbi_check.rb +43 -43
- data/lib/ruby_lsp/tapioca/server_addon.rb +13 -10
- data/lib/tapioca/bundler_ext/auto_require_hook.rb +6 -14
- data/lib/tapioca/cli.rb +16 -8
- data/lib/tapioca/commands/abstract_dsl.rb +39 -66
- data/lib/tapioca/commands/abstract_gem.rb +25 -46
- data/lib/tapioca/commands/annotations.rb +28 -34
- data/lib/tapioca/commands/check_shims.rb +6 -15
- data/lib/tapioca/commands/command.rb +12 -26
- data/lib/tapioca/commands/command_without_tracker.rb +2 -5
- data/lib/tapioca/commands/configure.rb +11 -16
- data/lib/tapioca/commands/dsl_compiler_list.rb +2 -1
- data/lib/tapioca/commands/dsl_generate.rb +2 -1
- data/lib/tapioca/commands/dsl_verify.rb +2 -1
- data/lib/tapioca/commands/gem_generate.rb +5 -9
- data/lib/tapioca/commands/gem_sync.rb +2 -1
- data/lib/tapioca/commands/gem_verify.rb +3 -2
- data/lib/tapioca/commands/require.rb +3 -7
- data/lib/tapioca/commands/todo.rb +6 -10
- data/lib/tapioca/dsl/compiler.rb +36 -63
- data/lib/tapioca/dsl/compilers/aasm.rb +33 -44
- data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +8 -7
- data/lib/tapioca/dsl/compilers/action_mailer.rb +6 -5
- data/lib/tapioca/dsl/compilers/action_text.rb +6 -5
- data/lib/tapioca/dsl/compilers/active_job.rb +6 -10
- data/lib/tapioca/dsl/compilers/active_model_attributes.rb +10 -11
- data/lib/tapioca/dsl/compilers/active_model_secure_password.rb +5 -6
- data/lib/tapioca/dsl/compilers/active_model_validations_confirmation.rb +5 -12
- data/lib/tapioca/dsl/compilers/active_record_associations.rb +17 -44
- data/lib/tapioca/dsl/compilers/active_record_columns.rb +20 -26
- data/lib/tapioca/dsl/compilers/active_record_delegated_types.rb +9 -8
- data/lib/tapioca/dsl/compilers/active_record_enum.rb +7 -6
- data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +54 -62
- data/lib/tapioca/dsl/compilers/active_record_relations.rb +148 -209
- data/lib/tapioca/dsl/compilers/active_record_scope.rb +8 -13
- data/lib/tapioca/dsl/compilers/active_record_secure_token.rb +5 -4
- data/lib/tapioca/dsl/compilers/active_record_store.rb +5 -4
- data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +19 -28
- data/lib/tapioca/dsl/compilers/active_resource.rb +19 -21
- data/lib/tapioca/dsl/compilers/active_storage.rb +6 -14
- data/lib/tapioca/dsl/compilers/active_support_concern.rb +9 -8
- data/lib/tapioca/dsl/compilers/active_support_current_attributes.rb +8 -7
- data/lib/tapioca/dsl/compilers/active_support_time_ext.rb +5 -4
- data/lib/tapioca/dsl/compilers/config.rb +5 -4
- data/lib/tapioca/dsl/compilers/frozen_record.rb +7 -11
- data/lib/tapioca/dsl/compilers/graphql_input_object.rb +9 -10
- data/lib/tapioca/dsl/compilers/graphql_mutation.rb +6 -10
- data/lib/tapioca/dsl/compilers/identity_cache.rb +11 -39
- data/lib/tapioca/dsl/compilers/json_api_client_resource.rb +9 -18
- data/lib/tapioca/dsl/compilers/kredis.rb +7 -8
- data/lib/tapioca/dsl/compilers/mixed_in_class_attributes.rb +5 -4
- data/lib/tapioca/dsl/compilers/protobuf.rb +13 -26
- data/lib/tapioca/dsl/compilers/rails_generators.rb +9 -11
- data/lib/tapioca/dsl/compilers/sidekiq_worker.rb +23 -13
- data/lib/tapioca/dsl/compilers/smart_properties.rb +32 -38
- data/lib/tapioca/dsl/compilers/state_machines.rb +15 -26
- data/lib/tapioca/dsl/compilers/url_helpers.rb +10 -9
- data/lib/tapioca/dsl/compilers.rb +4 -7
- data/lib/tapioca/dsl/helpers/active_model_type_helper.rb +13 -16
- data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +13 -28
- data/lib/tapioca/dsl/helpers/active_record_constants_helper.rb +19 -15
- data/lib/tapioca/dsl/helpers/graphql_type_helper.rb +5 -24
- data/lib/tapioca/dsl/pipeline.rb +30 -58
- data/lib/tapioca/executor.rb +6 -12
- data/lib/tapioca/gem/events.rb +24 -34
- data/lib/tapioca/gem/listeners/base.rb +7 -10
- data/lib/tapioca/gem/listeners/dynamic_mixins.rb +4 -2
- data/lib/tapioca/gem/listeners/foreign_constants.rb +5 -7
- data/lib/tapioca/gem/listeners/methods.rb +36 -47
- data/lib/tapioca/gem/listeners/mixins.rb +6 -18
- data/lib/tapioca/gem/listeners/remove_empty_payload_scopes.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_enums.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_helpers.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_props.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_required_ancestors.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_signatures.rb +7 -5
- data/lib/tapioca/gem/listeners/sorbet_type_variables.rb +6 -4
- data/lib/tapioca/gem/listeners/source_location.rb +15 -8
- data/lib/tapioca/gem/listeners/subconstants.rb +5 -4
- data/lib/tapioca/gem/listeners/yard_doc.rb +30 -23
- data/lib/tapioca/gem/pipeline.rb +107 -91
- data/lib/tapioca/gem_info.rb +1 -1
- data/lib/tapioca/gemfile.rb +64 -73
- data/lib/tapioca/helpers/cli_helper.rb +4 -7
- data/lib/tapioca/helpers/config_helper.rb +17 -29
- data/lib/tapioca/helpers/env_helper.rb +2 -5
- data/lib/tapioca/helpers/gem_helper.rb +5 -5
- data/lib/tapioca/helpers/git_attributes.rb +3 -3
- data/lib/tapioca/helpers/rbi_files_helper.rb +76 -73
- data/lib/tapioca/helpers/rbi_helper.rb +14 -22
- data/lib/tapioca/helpers/sorbet_helper.rb +9 -18
- data/lib/tapioca/helpers/source_uri.rb +15 -25
- data/lib/tapioca/helpers/test/content.rb +7 -10
- data/lib/tapioca/helpers/test/dsl_compiler.rb +20 -33
- data/lib/tapioca/helpers/test/isolation.rb +10 -14
- data/lib/tapioca/helpers/test/template.rb +6 -11
- data/lib/tapioca/internal.rb +18 -8
- data/lib/tapioca/loaders/dsl.rb +11 -19
- data/lib/tapioca/loaders/gem.rb +6 -21
- data/lib/tapioca/loaders/loader.rb +21 -39
- data/lib/tapioca/rbi_ext/model.rb +12 -37
- data/lib/tapioca/rbi_formatter.rb +10 -19
- data/lib/tapioca/rbs/rewriter.rb +55 -0
- data/lib/tapioca/repo_index.rb +7 -9
- data/lib/tapioca/runtime/attached_class_of_32.rb +1 -1
- data/lib/tapioca/runtime/attached_class_of_legacy.rb +2 -5
- data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +23 -23
- data/lib/tapioca/runtime/generic_type_registry.rb +13 -23
- data/lib/tapioca/runtime/reflection.rb +81 -60
- data/lib/tapioca/runtime/source_location.rb +44 -0
- data/lib/tapioca/runtime/trackers/autoload.rb +7 -9
- data/lib/tapioca/runtime/trackers/constant_definition.rb +18 -14
- data/lib/tapioca/runtime/trackers/method_definition.rb +65 -0
- data/lib/tapioca/runtime/trackers/mixin.rb +8 -11
- data/lib/tapioca/runtime/trackers/required_ancestor.rb +3 -3
- data/lib/tapioca/runtime/trackers/tracker.rb +3 -6
- data/lib/tapioca/runtime/trackers.rb +5 -8
- data/lib/tapioca/sorbet_ext/generic_name_patch.rb +9 -15
- data/lib/tapioca/sorbet_ext/name_patch.rb +2 -2
- data/lib/tapioca/sorbet_ext/proc_bind_patch.rb +1 -1
- data/lib/tapioca/static/requires_compiler.rb +6 -6
- data/lib/tapioca/static/symbol_loader.rb +14 -16
- data/lib/tapioca/static/symbol_table_parser.rb +8 -8
- data/lib/tapioca/version.rb +1 -1
- data/lib/tapioca.rb +22 -29
- metadata +27 -10
|
@@ -3,34 +3,12 @@
|
|
|
3
3
|
|
|
4
4
|
module Tapioca
|
|
5
5
|
module Commands
|
|
6
|
+
# @abstract
|
|
6
7
|
class AbstractDsl < CommandWithoutTracker
|
|
7
8
|
include SorbetHelper
|
|
8
9
|
include RBIFilesHelper
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
sig do
|
|
13
|
-
params(
|
|
14
|
-
requested_constants: T::Array[String],
|
|
15
|
-
requested_paths: T::Array[Pathname],
|
|
16
|
-
outpath: Pathname,
|
|
17
|
-
only: T::Array[String],
|
|
18
|
-
exclude: T::Array[String],
|
|
19
|
-
file_header: T::Boolean,
|
|
20
|
-
tapioca_path: String,
|
|
21
|
-
skip_constant: T::Array[String],
|
|
22
|
-
quiet: T::Boolean,
|
|
23
|
-
verbose: T::Boolean,
|
|
24
|
-
number_of_workers: T.nilable(Integer),
|
|
25
|
-
auto_strictness: T::Boolean,
|
|
26
|
-
gem_dir: String,
|
|
27
|
-
rbi_formatter: RBIFormatter,
|
|
28
|
-
app_root: String,
|
|
29
|
-
halt_upon_load_error: T::Boolean,
|
|
30
|
-
compiler_options: T::Hash[String, T.untyped],
|
|
31
|
-
lsp_addon: T::Boolean,
|
|
32
|
-
).void
|
|
33
|
-
end
|
|
11
|
+
#: (requested_constants: Array[String], requested_paths: Array[Pathname], outpath: Pathname, only: Array[String], exclude: Array[String], file_header: bool, tapioca_path: String, ?skip_constant: Array[String], ?quiet: bool, ?verbose: bool, ?number_of_workers: Integer?, ?auto_strictness: bool, ?gem_dir: String, ?rbi_formatter: RBIFormatter, ?app_root: String, ?halt_upon_load_error: bool, ?compiler_options: Hash[String, untyped], ?lsp_addon: bool) -> void
|
|
34
12
|
def initialize(
|
|
35
13
|
requested_constants:,
|
|
36
14
|
requested_paths:,
|
|
@@ -75,7 +53,7 @@ module Tapioca
|
|
|
75
53
|
|
|
76
54
|
private
|
|
77
55
|
|
|
78
|
-
|
|
56
|
+
#: (Pathname outpath, quiet: bool) -> Set[Pathname]
|
|
79
57
|
def generate_dsl_rbi_files(outpath, quiet:)
|
|
80
58
|
if @lsp_addon
|
|
81
59
|
pipeline.active_compilers.each(&:reset_state)
|
|
@@ -103,20 +81,17 @@ module Tapioca
|
|
|
103
81
|
files_to_purge
|
|
104
82
|
end
|
|
105
83
|
|
|
106
|
-
|
|
84
|
+
#: -> Array[String]
|
|
107
85
|
def all_requested_constants
|
|
108
|
-
@all_requested_constants ||=
|
|
109
|
-
@requested_constants + constants_from_requested_paths,
|
|
110
|
-
T.nilable(T::Array[String]),
|
|
111
|
-
)
|
|
86
|
+
@all_requested_constants ||= @requested_constants + constants_from_requested_paths #: Array[String]?
|
|
112
87
|
end
|
|
113
88
|
|
|
114
|
-
|
|
89
|
+
#: -> Tapioca::Dsl::Pipeline
|
|
115
90
|
def pipeline
|
|
116
|
-
@pipeline ||=
|
|
91
|
+
@pipeline ||= create_pipeline #: Tapioca::Dsl::Pipeline?
|
|
117
92
|
end
|
|
118
93
|
|
|
119
|
-
|
|
94
|
+
#: -> void
|
|
120
95
|
def load_application
|
|
121
96
|
# Loaded ahead of time when using the add-on to avoid reloading multiple times
|
|
122
97
|
return if @lsp_addon
|
|
@@ -129,17 +104,24 @@ module Tapioca
|
|
|
129
104
|
)
|
|
130
105
|
end
|
|
131
106
|
|
|
132
|
-
|
|
107
|
+
#: -> Tapioca::Dsl::Pipeline
|
|
133
108
|
def create_pipeline
|
|
109
|
+
error_handler = if @lsp_addon
|
|
110
|
+
->(error) {
|
|
111
|
+
say(error)
|
|
112
|
+
}
|
|
113
|
+
else
|
|
114
|
+
->(error) {
|
|
115
|
+
say_error(error, :bold, :red)
|
|
116
|
+
}
|
|
117
|
+
end
|
|
134
118
|
Tapioca::Dsl::Pipeline.new(
|
|
135
119
|
requested_constants:
|
|
136
120
|
constantize(@requested_constants) + constantize(constants_from_requested_paths, ignore_missing: true),
|
|
137
121
|
requested_paths: @requested_paths,
|
|
138
122
|
requested_compilers: constantize_compilers(@only),
|
|
139
123
|
excluded_compilers: constantize_compilers(@exclude),
|
|
140
|
-
error_handler:
|
|
141
|
-
say_error(error, :bold, :red)
|
|
142
|
-
},
|
|
124
|
+
error_handler: error_handler,
|
|
143
125
|
skipped_constants: constantize(@skip_constant, ignore_missing: true),
|
|
144
126
|
number_of_workers: @number_of_workers,
|
|
145
127
|
compiler_options: @compiler_options,
|
|
@@ -147,7 +129,7 @@ module Tapioca
|
|
|
147
129
|
)
|
|
148
130
|
end
|
|
149
131
|
|
|
150
|
-
|
|
132
|
+
#: (Array[String] requested_constants, ?path: Pathname) -> Set[Pathname]
|
|
151
133
|
def existing_rbi_filenames(requested_constants, path: @outpath)
|
|
152
134
|
filenames = if requested_constants.empty?
|
|
153
135
|
Pathname.glob(path / "**/*.rbi")
|
|
@@ -161,7 +143,7 @@ module Tapioca
|
|
|
161
143
|
filenames.to_set
|
|
162
144
|
end
|
|
163
145
|
|
|
164
|
-
|
|
146
|
+
#: (Array[String] constant_names, ?ignore_missing: bool) -> Array[Module]
|
|
165
147
|
def constantize(constant_names, ignore_missing: false)
|
|
166
148
|
constant_map = constant_names.to_h do |name|
|
|
167
149
|
[name, Object.const_get(name)]
|
|
@@ -178,7 +160,7 @@ module Tapioca
|
|
|
178
160
|
remove_file(filename) if File.file?(filename)
|
|
179
161
|
end
|
|
180
162
|
|
|
181
|
-
raise
|
|
163
|
+
raise Tapioca::Error, ""
|
|
182
164
|
end
|
|
183
165
|
|
|
184
166
|
processable_constants
|
|
@@ -186,7 +168,7 @@ module Tapioca
|
|
|
186
168
|
.grep(Module)
|
|
187
169
|
end
|
|
188
170
|
|
|
189
|
-
|
|
171
|
+
#: (Array[String] compiler_names) -> Array[singleton(Tapioca::Dsl::Compiler)]
|
|
190
172
|
def constantize_compilers(compiler_names)
|
|
191
173
|
compiler_map = compiler_names.to_h do |name|
|
|
192
174
|
[name, resolve(name)]
|
|
@@ -206,7 +188,7 @@ module Tapioca
|
|
|
206
188
|
T.cast(compiler_map.values, T::Array[T.class_of(Tapioca::Dsl::Compiler)])
|
|
207
189
|
end
|
|
208
190
|
|
|
209
|
-
|
|
191
|
+
#: (String name) -> singleton(Tapioca::Dsl::Compiler)?
|
|
210
192
|
def resolve(name)
|
|
211
193
|
# Try to find built-in tapioca compiler first, then globally defined compiler.
|
|
212
194
|
potentials = Tapioca::Dsl::Compilers::NAMESPACES.map do |namespace|
|
|
@@ -219,14 +201,7 @@ module Tapioca
|
|
|
219
201
|
potentials.compact.first
|
|
220
202
|
end
|
|
221
203
|
|
|
222
|
-
|
|
223
|
-
params(
|
|
224
|
-
constant_name: String,
|
|
225
|
-
rbi: RBI::File,
|
|
226
|
-
outpath: Pathname,
|
|
227
|
-
quiet: T::Boolean,
|
|
228
|
-
).returns(T.nilable(Pathname))
|
|
229
|
-
end
|
|
204
|
+
#: (String constant_name, RBI::File rbi, ?outpath: Pathname, ?quiet: bool) -> Pathname?
|
|
230
205
|
def compile_dsl_rbi(constant_name, rbi, outpath: @outpath, quiet: false)
|
|
231
206
|
return if rbi.empty?
|
|
232
207
|
|
|
@@ -244,7 +219,7 @@ module Tapioca
|
|
|
244
219
|
filename
|
|
245
220
|
end
|
|
246
221
|
|
|
247
|
-
|
|
222
|
+
#: (Pathname dir) -> void
|
|
248
223
|
def perform_dsl_verification(dir)
|
|
249
224
|
diff = verify_dsl_rbi(tmp_dir: dir)
|
|
250
225
|
|
|
@@ -253,7 +228,7 @@ module Tapioca
|
|
|
253
228
|
FileUtils.remove_entry(dir)
|
|
254
229
|
end
|
|
255
230
|
|
|
256
|
-
|
|
231
|
+
#: (Set[Pathname] files) -> void
|
|
257
232
|
def purge_stale_dsl_rbi_files(files)
|
|
258
233
|
if files.any?
|
|
259
234
|
say("Removing stale RBI files...")
|
|
@@ -265,12 +240,12 @@ module Tapioca
|
|
|
265
240
|
end
|
|
266
241
|
end
|
|
267
242
|
|
|
268
|
-
|
|
243
|
+
#: (String constant_name) -> Pathname
|
|
269
244
|
def dsl_rbi_filename(constant_name)
|
|
270
245
|
@outpath / "#{underscore(constant_name)}.rbi"
|
|
271
246
|
end
|
|
272
247
|
|
|
273
|
-
|
|
248
|
+
#: (tmp_dir: Pathname) -> Hash[String, Symbol]
|
|
274
249
|
def verify_dsl_rbi(tmp_dir:)
|
|
275
250
|
diff = {}
|
|
276
251
|
|
|
@@ -302,7 +277,7 @@ module Tapioca
|
|
|
302
277
|
diff
|
|
303
278
|
end
|
|
304
279
|
|
|
305
|
-
|
|
280
|
+
#: (Symbol cause, Array[String] files) -> String
|
|
306
281
|
def build_error_for_files(cause, files)
|
|
307
282
|
filenames = files.map do |file|
|
|
308
283
|
@outpath / file
|
|
@@ -311,7 +286,7 @@ module Tapioca
|
|
|
311
286
|
" File(s) #{cause}:\n - #{filenames}"
|
|
312
287
|
end
|
|
313
288
|
|
|
314
|
-
|
|
289
|
+
#: (Hash[String, Symbol] diff, Symbol command) -> void
|
|
315
290
|
def report_diff_and_exit_if_out_of_date(diff, command)
|
|
316
291
|
if diff.empty?
|
|
317
292
|
say("Nothing to do, all RBIs are up-to-date.")
|
|
@@ -320,7 +295,7 @@ module Tapioca
|
|
|
320
295
|
build_error_for_files(cause, diff_for_cause.map(&:first))
|
|
321
296
|
end.join("\n")
|
|
322
297
|
|
|
323
|
-
raise
|
|
298
|
+
raise Tapioca::Error, <<~ERROR
|
|
324
299
|
#{set_color("RBI files are out-of-date. In your development environment, please run:", :green)}
|
|
325
300
|
#{set_color("`#{default_command(command)}`", :green, :bold)}
|
|
326
301
|
#{set_color("Once it is complete, be sure to commit and push any changes", :green)}
|
|
@@ -333,14 +308,14 @@ module Tapioca
|
|
|
333
308
|
end
|
|
334
309
|
end
|
|
335
310
|
|
|
336
|
-
|
|
311
|
+
#: (Pathname path) -> Array[Pathname]
|
|
337
312
|
def rbi_files_in(path)
|
|
338
313
|
Pathname.glob(path / "**/*.rbi").map do |file|
|
|
339
314
|
file.relative_path_from(path)
|
|
340
315
|
end.sort
|
|
341
316
|
end
|
|
342
317
|
|
|
343
|
-
|
|
318
|
+
#: (String class_name) -> String
|
|
344
319
|
def underscore(class_name)
|
|
345
320
|
return class_name unless /[A-Z-]|::/.match?(class_name)
|
|
346
321
|
|
|
@@ -352,22 +327,20 @@ module Tapioca
|
|
|
352
327
|
word
|
|
353
328
|
end
|
|
354
329
|
|
|
355
|
-
|
|
330
|
+
#: (String constant) -> String
|
|
356
331
|
def rbi_filename_for(constant)
|
|
357
332
|
underscore(constant) + ".rbi"
|
|
358
333
|
end
|
|
359
334
|
|
|
360
|
-
|
|
335
|
+
#: (String constant) -> String
|
|
361
336
|
def generate_command_for(constant)
|
|
362
337
|
default_command(:dsl, constant)
|
|
363
338
|
end
|
|
364
339
|
|
|
365
|
-
|
|
340
|
+
#: -> Array[String]
|
|
366
341
|
def constants_from_requested_paths
|
|
367
|
-
@constants_from_requested_paths ||=
|
|
368
|
-
Static::SymbolLoader.symbols_from_paths(@requested_paths).to_a
|
|
369
|
-
T.nilable(T::Array[String]),
|
|
370
|
-
)
|
|
342
|
+
@constants_from_requested_paths ||=
|
|
343
|
+
Static::SymbolLoader.symbols_from_paths(@requested_paths).to_a #: Array[String]?
|
|
371
344
|
end
|
|
372
345
|
end
|
|
373
346
|
end
|
|
@@ -3,33 +3,12 @@
|
|
|
3
3
|
|
|
4
4
|
module Tapioca
|
|
5
5
|
module Commands
|
|
6
|
+
# @abstract
|
|
6
7
|
class AbstractGem < Command
|
|
7
8
|
include SorbetHelper
|
|
8
9
|
include RBIFilesHelper
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
sig do
|
|
13
|
-
params(
|
|
14
|
-
gem_names: T::Array[String],
|
|
15
|
-
exclude: T::Array[String],
|
|
16
|
-
include_dependencies: T::Boolean,
|
|
17
|
-
prerequire: T.nilable(String),
|
|
18
|
-
postrequire: String,
|
|
19
|
-
typed_overrides: T::Hash[String, String],
|
|
20
|
-
outpath: Pathname,
|
|
21
|
-
file_header: T::Boolean,
|
|
22
|
-
include_doc: T::Boolean,
|
|
23
|
-
include_loc: T::Boolean,
|
|
24
|
-
include_exported_rbis: T::Boolean,
|
|
25
|
-
number_of_workers: T.nilable(Integer),
|
|
26
|
-
auto_strictness: T::Boolean,
|
|
27
|
-
dsl_dir: String,
|
|
28
|
-
rbi_formatter: RBIFormatter,
|
|
29
|
-
halt_upon_load_error: T::Boolean,
|
|
30
|
-
lsp_addon: T.nilable(T::Boolean),
|
|
31
|
-
).void
|
|
32
|
-
end
|
|
11
|
+
#: (gem_names: Array[String], exclude: Array[String], include_dependencies: bool, prerequire: String?, postrequire: String, typed_overrides: Hash[String, String], outpath: Pathname, file_header: bool, include_doc: bool, include_loc: bool, include_exported_rbis: bool, ?number_of_workers: Integer?, ?auto_strictness: bool, ?dsl_dir: String, ?rbi_formatter: RBIFormatter, ?halt_upon_load_error: bool, ?lsp_addon: bool?) -> void
|
|
33
12
|
def initialize(
|
|
34
13
|
gem_names:,
|
|
35
14
|
exclude:,
|
|
@@ -65,18 +44,18 @@ module Tapioca
|
|
|
65
44
|
|
|
66
45
|
super()
|
|
67
46
|
|
|
68
|
-
@bundle =
|
|
69
|
-
@existing_rbis =
|
|
70
|
-
@expected_rbis =
|
|
71
|
-
@include_doc =
|
|
72
|
-
@include_loc =
|
|
47
|
+
@bundle = Gemfile.new(exclude) #: Gemfile
|
|
48
|
+
@existing_rbis = nil #: Hash[String, String]?
|
|
49
|
+
@expected_rbis = nil #: Hash[String, String]?
|
|
50
|
+
@include_doc = include_doc #: bool
|
|
51
|
+
@include_loc = include_loc #: bool
|
|
73
52
|
@include_exported_rbis = include_exported_rbis
|
|
74
53
|
@halt_upon_load_error = halt_upon_load_error
|
|
75
54
|
end
|
|
76
55
|
|
|
77
56
|
private
|
|
78
57
|
|
|
79
|
-
|
|
58
|
+
#: (Gemfile::GemSpec gem) -> void
|
|
80
59
|
def compile_gem_rbi(gem)
|
|
81
60
|
gem_name = set_color(gem.name, :yellow, :bold)
|
|
82
61
|
|
|
@@ -116,12 +95,12 @@ module Tapioca
|
|
|
116
95
|
end
|
|
117
96
|
end
|
|
118
97
|
|
|
119
|
-
|
|
98
|
+
#: -> void
|
|
120
99
|
def perform_removals
|
|
121
100
|
say("Removing RBI files of gems that have been removed:", [:blue, :bold])
|
|
122
101
|
puts
|
|
123
102
|
|
|
124
|
-
anything_done =
|
|
103
|
+
anything_done = false #: bool
|
|
125
104
|
|
|
126
105
|
gems = removed_rbis
|
|
127
106
|
|
|
@@ -143,12 +122,12 @@ module Tapioca
|
|
|
143
122
|
anything_done
|
|
144
123
|
end
|
|
145
124
|
|
|
146
|
-
|
|
125
|
+
#: -> void
|
|
147
126
|
def perform_additions
|
|
148
127
|
say("Generating RBI files of gems that are added or updated:", [:blue, :bold])
|
|
149
128
|
puts
|
|
150
129
|
|
|
151
|
-
anything_done =
|
|
130
|
+
anything_done = false #: bool
|
|
152
131
|
|
|
153
132
|
gems = added_rbis
|
|
154
133
|
|
|
@@ -186,34 +165,34 @@ module Tapioca
|
|
|
186
165
|
anything_done
|
|
187
166
|
end
|
|
188
167
|
|
|
189
|
-
|
|
168
|
+
#: -> Array[String]
|
|
190
169
|
def removed_rbis
|
|
191
170
|
(existing_rbis.keys - expected_rbis.keys).sort
|
|
192
171
|
end
|
|
193
172
|
|
|
194
|
-
|
|
173
|
+
#: (String gem_name) -> Pathname
|
|
195
174
|
def existing_rbi(gem_name)
|
|
196
175
|
gem_rbi_filename(gem_name, T.must(existing_rbis[gem_name]))
|
|
197
176
|
end
|
|
198
177
|
|
|
199
|
-
|
|
178
|
+
#: -> Array[String]
|
|
200
179
|
def added_rbis
|
|
201
180
|
expected_rbis.select do |name, value|
|
|
202
181
|
existing_rbis[name] != value
|
|
203
182
|
end.keys.sort
|
|
204
183
|
end
|
|
205
184
|
|
|
206
|
-
|
|
185
|
+
#: (String gem_name) -> Pathname
|
|
207
186
|
def expected_rbi(gem_name)
|
|
208
187
|
gem_rbi_filename(gem_name, T.must(expected_rbis[gem_name]))
|
|
209
188
|
end
|
|
210
189
|
|
|
211
|
-
|
|
190
|
+
#: (String gem_name) -> bool
|
|
212
191
|
def gem_rbi_exists?(gem_name)
|
|
213
192
|
existing_rbis.key?(gem_name)
|
|
214
193
|
end
|
|
215
194
|
|
|
216
|
-
|
|
195
|
+
#: (Hash[String, Symbol] diff, Symbol command) -> void
|
|
217
196
|
def report_diff_and_exit_if_out_of_date(diff, command)
|
|
218
197
|
if diff.empty?
|
|
219
198
|
say("Nothing to do, all RBIs are up-to-date.")
|
|
@@ -222,7 +201,7 @@ module Tapioca
|
|
|
222
201
|
build_error_for_files(cause, diff_for_cause.map(&:first))
|
|
223
202
|
end.join("\n")
|
|
224
203
|
|
|
225
|
-
raise
|
|
204
|
+
raise Tapioca::Error, <<~ERROR
|
|
226
205
|
#{set_color("RBI files are out-of-date. In your development environment, please run:", :green)}
|
|
227
206
|
#{set_color("`#{default_command(command)}`", :green, :bold)}
|
|
228
207
|
#{set_color("Once it is complete, be sure to commit and push any changes", :green)}
|
|
@@ -233,36 +212,36 @@ module Tapioca
|
|
|
233
212
|
end
|
|
234
213
|
end
|
|
235
214
|
|
|
236
|
-
|
|
215
|
+
#: (Pathname old_filename, Pathname new_filename) -> void
|
|
237
216
|
def move(old_filename, new_filename)
|
|
238
217
|
say("-> Moving: #{old_filename} to #{new_filename}")
|
|
239
218
|
old_filename.rename(new_filename.to_s)
|
|
240
219
|
end
|
|
241
220
|
|
|
242
|
-
|
|
221
|
+
#: -> Hash[String, String]
|
|
243
222
|
def existing_rbis
|
|
244
223
|
@existing_rbis ||= Pathname.glob((@outpath / "*@*.rbi").to_s)
|
|
245
224
|
.to_h { |f| T.cast(f.basename(".*").to_s.split("@", 2), [String, String]) }
|
|
246
225
|
end
|
|
247
226
|
|
|
248
|
-
|
|
227
|
+
#: -> Hash[String, String]
|
|
249
228
|
def expected_rbis
|
|
250
229
|
@expected_rbis ||= @bundle.dependencies
|
|
251
230
|
.reject { |gem| @exclude.include?(gem.name) }
|
|
252
231
|
.to_h { |gem| [gem.name, gem.version.to_s] }
|
|
253
232
|
end
|
|
254
233
|
|
|
255
|
-
|
|
234
|
+
#: (String gem_name, String version) -> Pathname
|
|
256
235
|
def gem_rbi_filename(gem_name, version)
|
|
257
236
|
@outpath / "#{gem_name}@#{version}.rbi"
|
|
258
237
|
end
|
|
259
238
|
|
|
260
|
-
|
|
239
|
+
#: (Symbol cause, Array[String] files) -> String
|
|
261
240
|
def build_error_for_files(cause, files)
|
|
262
241
|
" File(s) #{cause}:\n - #{files.join("\n - ")}"
|
|
263
242
|
end
|
|
264
243
|
|
|
265
|
-
|
|
244
|
+
#: (Gemfile::GemSpec gem, RBI::File file) -> void
|
|
266
245
|
def merge_with_exported_rbi(gem, file)
|
|
267
246
|
return file unless gem.export_rbi_files?
|
|
268
247
|
|
|
@@ -6,15 +6,7 @@ module Tapioca
|
|
|
6
6
|
class Annotations < CommandWithoutTracker
|
|
7
7
|
extend T::Sig
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
params(
|
|
11
|
-
central_repo_root_uris: T::Array[String],
|
|
12
|
-
auth: T.nilable(String),
|
|
13
|
-
netrc_file: T.nilable(String),
|
|
14
|
-
central_repo_index_path: String,
|
|
15
|
-
typed_overrides: T::Hash[String, String],
|
|
16
|
-
).void
|
|
17
|
-
end
|
|
9
|
+
#: (central_repo_root_uris: Array[String], ?auth: String?, ?netrc_file: String?, ?central_repo_index_path: String, ?typed_overrides: Hash[String, String]) -> void
|
|
18
10
|
def initialize(
|
|
19
11
|
central_repo_root_uris:,
|
|
20
12
|
auth: nil,
|
|
@@ -23,19 +15,20 @@ module Tapioca
|
|
|
23
15
|
typed_overrides: {}
|
|
24
16
|
)
|
|
25
17
|
super()
|
|
26
|
-
@outpath =
|
|
18
|
+
@outpath = Pathname.new(DEFAULT_ANNOTATIONS_DIR) #: Pathname
|
|
27
19
|
@central_repo_root_uris = central_repo_root_uris
|
|
28
20
|
@auth = auth
|
|
29
21
|
@netrc_file = netrc_file
|
|
30
|
-
@netrc_info =
|
|
31
|
-
@tokens =
|
|
32
|
-
@indexes =
|
|
22
|
+
@netrc_info = nil #: Netrc?
|
|
23
|
+
@tokens = repo_tokens #: Hash[String, String?]
|
|
24
|
+
@indexes = {} #: Hash[String, RepoIndex]
|
|
33
25
|
@typed_overrides = typed_overrides
|
|
34
26
|
end
|
|
35
27
|
|
|
36
28
|
private
|
|
37
29
|
|
|
38
|
-
|
|
30
|
+
# @override
|
|
31
|
+
#: -> void
|
|
39
32
|
def execute
|
|
40
33
|
@indexes = fetch_indexes
|
|
41
34
|
project_gems = list_gemfile_gems
|
|
@@ -46,7 +39,7 @@ module Tapioca
|
|
|
46
39
|
GitAttributes.create_vendored_attribute_file(@outpath)
|
|
47
40
|
end
|
|
48
41
|
|
|
49
|
-
|
|
42
|
+
#: -> Array[GemInfo]
|
|
50
43
|
def list_gemfile_gems
|
|
51
44
|
say("Listing gems from Gemfile.lock... ", [:blue, :bold])
|
|
52
45
|
gemfile = Bundler.read_file("Gemfile.lock")
|
|
@@ -56,7 +49,7 @@ module Tapioca
|
|
|
56
49
|
gem_info
|
|
57
50
|
end
|
|
58
51
|
|
|
59
|
-
|
|
52
|
+
#: (Array[GemInfo] project_gems) -> void
|
|
60
53
|
def remove_expired_annotations(project_gems)
|
|
61
54
|
say("Removing annotations for gems that have been removed... ", [:blue, :bold])
|
|
62
55
|
|
|
@@ -77,11 +70,11 @@ module Tapioca
|
|
|
77
70
|
say("\nDone\n\n", :green)
|
|
78
71
|
end
|
|
79
72
|
|
|
80
|
-
|
|
73
|
+
#: -> Hash[String, RepoIndex]
|
|
81
74
|
def fetch_indexes
|
|
82
75
|
multiple_repos = @central_repo_root_uris.size > 1
|
|
83
76
|
repo_number = 1
|
|
84
|
-
indexes =
|
|
77
|
+
indexes = {} #: Hash[String, RepoIndex]
|
|
85
78
|
|
|
86
79
|
@central_repo_root_uris.each do |uri|
|
|
87
80
|
index = fetch_index(uri, repo_number: multiple_repos ? repo_number : nil)
|
|
@@ -92,13 +85,13 @@ module Tapioca
|
|
|
92
85
|
end
|
|
93
86
|
|
|
94
87
|
if indexes.empty?
|
|
95
|
-
raise
|
|
88
|
+
raise Tapioca::Error, set_color("Can't fetch annotations without sources (no index fetched)", :bold, :red)
|
|
96
89
|
end
|
|
97
90
|
|
|
98
91
|
indexes
|
|
99
92
|
end
|
|
100
93
|
|
|
101
|
-
|
|
94
|
+
#: (String repo_uri, repo_number: Integer?) -> RepoIndex?
|
|
102
95
|
def fetch_index(repo_uri, repo_number:)
|
|
103
96
|
say("Retrieving index from central repository#{repo_number ? " ##{repo_number}" : ""}... ", [:blue, :bold])
|
|
104
97
|
content = fetch_file(repo_uri, CENTRAL_REPO_INDEX_PATH)
|
|
@@ -109,10 +102,10 @@ module Tapioca
|
|
|
109
102
|
index
|
|
110
103
|
end
|
|
111
104
|
|
|
112
|
-
|
|
105
|
+
#: (Array[GemInfo] project_gems) -> Array[String]
|
|
113
106
|
def fetch_annotations(project_gems)
|
|
114
107
|
say("Fetching gem annotations from central repository... ", [:blue, :bold])
|
|
115
|
-
fetchable_gems =
|
|
108
|
+
fetchable_gems = Hash.new { |h, k| h[k] = [] } #: Hash[GemInfo, Array[String]]
|
|
116
109
|
|
|
117
110
|
project_gems.each_with_object(fetchable_gems) do |gem_info, hash|
|
|
118
111
|
@indexes.each do |uri, index|
|
|
@@ -132,7 +125,7 @@ module Tapioca
|
|
|
132
125
|
fetched_gems.keys.map(&:name).sort
|
|
133
126
|
end
|
|
134
127
|
|
|
135
|
-
|
|
128
|
+
#: (Array[String] repo_uris, GemInfo gem_info) -> bool
|
|
136
129
|
def fetch_annotation(repo_uris, gem_info)
|
|
137
130
|
gem_name = gem_info.name
|
|
138
131
|
gem_version = gem_info.version
|
|
@@ -142,7 +135,7 @@ module Tapioca
|
|
|
142
135
|
end
|
|
143
136
|
|
|
144
137
|
content = merge_files(gem_name, contents.compact)
|
|
145
|
-
return unless content
|
|
138
|
+
return false unless content
|
|
146
139
|
|
|
147
140
|
content = apply_typed_override(gem_name, content)
|
|
148
141
|
content = filter_versions(gem_version, content)
|
|
@@ -150,9 +143,10 @@ module Tapioca
|
|
|
150
143
|
|
|
151
144
|
say("\n Fetched #{set_color(gem_name, :yellow, :bold)}", :green)
|
|
152
145
|
create_file(@outpath.join("#{gem_name}.rbi"), content)
|
|
146
|
+
true
|
|
153
147
|
end
|
|
154
148
|
|
|
155
|
-
|
|
149
|
+
#: (String repo_uri, String path) -> String?
|
|
156
150
|
def fetch_file(repo_uri, path)
|
|
157
151
|
if repo_uri.start_with?(%r{https?://})
|
|
158
152
|
fetch_http_file(repo_uri, path)
|
|
@@ -161,7 +155,7 @@ module Tapioca
|
|
|
161
155
|
end
|
|
162
156
|
end
|
|
163
157
|
|
|
164
|
-
|
|
158
|
+
#: (String repo_uri, String path) -> String?
|
|
165
159
|
def fetch_local_file(repo_uri, path)
|
|
166
160
|
File.read("#{repo_uri}/#{path}")
|
|
167
161
|
rescue => e
|
|
@@ -169,7 +163,7 @@ module Tapioca
|
|
|
169
163
|
nil
|
|
170
164
|
end
|
|
171
165
|
|
|
172
|
-
|
|
166
|
+
#: (String repo_uri, String path) -> String?
|
|
173
167
|
def fetch_http_file(repo_uri, path)
|
|
174
168
|
auth = @tokens[repo_uri]
|
|
175
169
|
uri = URI("#{repo_uri}/#{path}")
|
|
@@ -193,7 +187,7 @@ module Tapioca
|
|
|
193
187
|
nil
|
|
194
188
|
end
|
|
195
189
|
|
|
196
|
-
|
|
190
|
+
#: (String name, String content) -> String
|
|
197
191
|
def add_header(name, content)
|
|
198
192
|
# WARNING: Changing this header could impact how GitHub determines if the file should be hidden:
|
|
199
193
|
# https://github.com/github/linguist/pull/6143
|
|
@@ -213,7 +207,7 @@ module Tapioca
|
|
|
213
207
|
end
|
|
214
208
|
end
|
|
215
209
|
|
|
216
|
-
|
|
210
|
+
#: (String name, String content) -> String
|
|
217
211
|
def apply_typed_override(name, content)
|
|
218
212
|
strictness = @typed_overrides[name]
|
|
219
213
|
return content unless strictness
|
|
@@ -225,7 +219,7 @@ module Tapioca
|
|
|
225
219
|
Spoom::Sorbet::Sigils.update_sigil(content, strictness)
|
|
226
220
|
end
|
|
227
221
|
|
|
228
|
-
|
|
222
|
+
#: (::Gem::Version gem_version, String content) -> String
|
|
229
223
|
def filter_versions(gem_version, content)
|
|
230
224
|
rbi = RBI::Parser.parse_string(content)
|
|
231
225
|
rbi.filter_versions!(gem_version)
|
|
@@ -233,7 +227,7 @@ module Tapioca
|
|
|
233
227
|
rbi.string
|
|
234
228
|
end
|
|
235
229
|
|
|
236
|
-
|
|
230
|
+
#: (String gem_name, Array[String] contents) -> String?
|
|
237
231
|
def merge_files(gem_name, contents)
|
|
238
232
|
return if contents.empty?
|
|
239
233
|
|
|
@@ -260,7 +254,7 @@ module Tapioca
|
|
|
260
254
|
nil
|
|
261
255
|
end
|
|
262
256
|
|
|
263
|
-
|
|
257
|
+
#: -> Hash[String, String?]
|
|
264
258
|
def repo_tokens
|
|
265
259
|
@netrc_info = Netrc.read(@netrc_file) if @netrc_file
|
|
266
260
|
@central_repo_root_uris.filter_map do |uri|
|
|
@@ -272,7 +266,7 @@ module Tapioca
|
|
|
272
266
|
end.to_h
|
|
273
267
|
end
|
|
274
268
|
|
|
275
|
-
|
|
269
|
+
#: (String repo_uri) -> String?
|
|
276
270
|
def token_for(repo_uri)
|
|
277
271
|
return unless @netrc_info
|
|
278
272
|
|
|
@@ -288,7 +282,7 @@ module Tapioca
|
|
|
288
282
|
"token #{token}"
|
|
289
283
|
end
|
|
290
284
|
|
|
291
|
-
|
|
285
|
+
#: (String path, String repo_uri, message: String) -> void
|
|
292
286
|
def say_http_error(path, repo_uri, message:)
|
|
293
287
|
say_error("\nCan't fetch file `#{path}` from #{repo_uri} (#{message})\n\n", :bold, :red)
|
|
294
288
|
say_error(<<~ERROR)
|