tapioca 0.17.9 → 0.18.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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -2
  3. data/lib/tapioca/bundler_ext/auto_require_hook.rb +0 -3
  4. data/lib/tapioca/cli.rb +0 -2
  5. data/lib/tapioca/commands/abstract_dsl.rb +21 -2
  6. data/lib/tapioca/commands/abstract_gem.rb +20 -1
  7. data/lib/tapioca/commands/annotations.rb +7 -3
  8. data/lib/tapioca/commands/check_shims.rb +9 -2
  9. data/lib/tapioca/commands/command.rb +0 -1
  10. data/lib/tapioca/dsl/compiler.rb +17 -16
  11. data/lib/tapioca/dsl/compilers/aasm.rb +2 -6
  12. data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +2 -6
  13. data/lib/tapioca/dsl/compilers/action_mailer.rb +1 -5
  14. data/lib/tapioca/dsl/compilers/action_text.rb +1 -5
  15. data/lib/tapioca/dsl/compilers/active_job.rb +1 -5
  16. data/lib/tapioca/dsl/compilers/active_model_attributes.rb +1 -5
  17. data/lib/tapioca/dsl/compilers/active_model_secure_password.rb +1 -5
  18. data/lib/tapioca/dsl/compilers/active_model_validations_confirmation.rb +1 -3
  19. data/lib/tapioca/dsl/compilers/active_record_associations.rb +1 -6
  20. data/lib/tapioca/dsl/compilers/active_record_columns.rb +8 -5
  21. data/lib/tapioca/dsl/compilers/active_record_delegated_types.rb +1 -4
  22. data/lib/tapioca/dsl/compilers/active_record_enum.rb +1 -5
  23. data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +1 -5
  24. data/lib/tapioca/dsl/compilers/active_record_relations.rb +45 -87
  25. data/lib/tapioca/dsl/compilers/active_record_scope.rb +1 -2
  26. data/lib/tapioca/dsl/compilers/active_record_secure_token.rb +1 -4
  27. data/lib/tapioca/dsl/compilers/active_record_store.rb +1 -4
  28. data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +1 -5
  29. data/lib/tapioca/dsl/compilers/active_resource.rb +1 -5
  30. data/lib/tapioca/dsl/compilers/active_storage.rb +2 -6
  31. data/lib/tapioca/dsl/compilers/active_support_concern.rb +6 -10
  32. data/lib/tapioca/dsl/compilers/active_support_current_attributes.rb +4 -19
  33. data/lib/tapioca/dsl/compilers/active_support_environment_inquirer.rb +60 -0
  34. data/lib/tapioca/dsl/compilers/active_support_time_ext.rb +1 -5
  35. data/lib/tapioca/dsl/compilers/config.rb +2 -6
  36. data/lib/tapioca/dsl/compilers/frozen_record.rb +1 -5
  37. data/lib/tapioca/dsl/compilers/graphql_input_object.rb +1 -5
  38. data/lib/tapioca/dsl/compilers/graphql_mutation.rb +1 -5
  39. data/lib/tapioca/dsl/compilers/identity_cache.rb +2 -6
  40. data/lib/tapioca/dsl/compilers/json_api_client_resource.rb +4 -18
  41. data/lib/tapioca/dsl/compilers/kredis.rb +1 -5
  42. data/lib/tapioca/dsl/compilers/mixed_in_class_attributes.rb +2 -6
  43. data/lib/tapioca/dsl/compilers/protobuf.rb +2 -6
  44. data/lib/tapioca/dsl/compilers/rails_generators.rb +1 -5
  45. data/lib/tapioca/dsl/compilers/sidekiq_worker.rb +1 -5
  46. data/lib/tapioca/dsl/compilers/smart_properties.rb +1 -5
  47. data/lib/tapioca/dsl/compilers/state_machines.rb +2 -6
  48. data/lib/tapioca/dsl/compilers/url_helpers.rb +7 -10
  49. data/lib/tapioca/dsl/helpers/active_model_type_helper.rb +0 -2
  50. data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +3 -6
  51. data/lib/tapioca/dsl/helpers/active_record_constants_helper.rb +0 -2
  52. data/lib/tapioca/dsl/helpers/graphql_type_helper.rb +18 -5
  53. data/lib/tapioca/dsl/pipeline.rb +25 -13
  54. data/lib/tapioca/executor.rb +0 -2
  55. data/lib/tapioca/gem/events.rb +15 -23
  56. data/lib/tapioca/gem/listeners/base.rb +0 -1
  57. data/lib/tapioca/gem/listeners/dynamic_mixins.rb +0 -2
  58. data/lib/tapioca/gem/listeners/foreign_constants.rb +0 -2
  59. data/lib/tapioca/gem/listeners/methods.rb +19 -9
  60. data/lib/tapioca/gem/listeners/mixins.rb +3 -5
  61. data/lib/tapioca/gem/listeners/remove_empty_payload_scopes.rb +0 -2
  62. data/lib/tapioca/gem/listeners/sorbet_enums.rb +0 -2
  63. data/lib/tapioca/gem/listeners/sorbet_helpers.rb +0 -2
  64. data/lib/tapioca/gem/listeners/sorbet_props.rb +0 -1
  65. data/lib/tapioca/gem/listeners/sorbet_required_ancestors.rb +0 -2
  66. data/lib/tapioca/gem/listeners/sorbet_signatures.rb +0 -2
  67. data/lib/tapioca/gem/listeners/sorbet_type_variables.rb +1 -3
  68. data/lib/tapioca/gem/listeners/source_location.rb +6 -7
  69. data/lib/tapioca/gem/listeners/subconstants.rb +0 -2
  70. data/lib/tapioca/gem/listeners/yard_doc.rb +0 -2
  71. data/lib/tapioca/gem/pipeline.rb +25 -21
  72. data/lib/tapioca/gemfile.rb +1 -3
  73. data/lib/tapioca/helpers/cli_helper.rb +0 -1
  74. data/lib/tapioca/helpers/config_helper.rb +5 -2
  75. data/lib/tapioca/helpers/env_helper.rb +0 -1
  76. data/lib/tapioca/helpers/gem_helper.rb +0 -2
  77. data/lib/tapioca/helpers/git_attributes.rb +0 -2
  78. data/lib/tapioca/helpers/package_url.rb +416 -0
  79. data/lib/tapioca/helpers/rbi_files_helper.rb +8 -2
  80. data/lib/tapioca/helpers/rbi_helper.rb +0 -3
  81. data/lib/tapioca/helpers/sorbet_helper.rb +0 -2
  82. data/lib/tapioca/helpers/test/content.rb +0 -1
  83. data/lib/tapioca/helpers/test/dsl_compiler.rb +0 -3
  84. data/lib/tapioca/helpers/test/isolation.rb +0 -6
  85. data/lib/tapioca/helpers/test/template.rb +1 -9
  86. data/lib/tapioca/internal.rb +1 -1
  87. data/lib/tapioca/loaders/dsl.rb +0 -4
  88. data/lib/tapioca/loaders/gem.rb +14 -6
  89. data/lib/tapioca/loaders/loader.rb +0 -1
  90. data/lib/tapioca/rbi_ext/model.rb +9 -4
  91. data/lib/tapioca/rbi_formatter.rb +0 -2
  92. data/lib/tapioca/repo_index.rb +1 -4
  93. data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +6 -9
  94. data/lib/tapioca/runtime/generic_type_registry.rb +8 -12
  95. data/lib/tapioca/runtime/reflection.rb +25 -31
  96. data/lib/tapioca/runtime/trackers/autoload.rb +0 -3
  97. data/lib/tapioca/runtime/trackers/constant_definition.rb +30 -8
  98. data/lib/tapioca/runtime/trackers/method_definition.rb +4 -5
  99. data/lib/tapioca/runtime/trackers/mixin.rb +5 -8
  100. data/lib/tapioca/runtime/trackers/required_ancestor.rb +2 -4
  101. data/lib/tapioca/runtime/trackers/tracker.rb +1 -4
  102. data/lib/tapioca/runtime/trackers.rb +0 -4
  103. data/lib/tapioca/sorbet_ext/generic_name_patch.rb +1 -3
  104. data/lib/tapioca/static/requires_compiler.rb +1 -3
  105. data/lib/tapioca/static/symbol_loader.rb +0 -1
  106. data/lib/tapioca/static/symbol_table_parser.rb +0 -4
  107. data/lib/tapioca/version.rb +1 -1
  108. data/lib/tapioca.rb +0 -2
  109. metadata +18 -5
  110. data/lib/tapioca/helpers/source_uri.rb +0 -84
  111. data/lib/tapioca/runtime/attached_class_of_32.rb +0 -20
  112. data/lib/tapioca/runtime/attached_class_of_legacy.rb +0 -24
@@ -0,0 +1,416 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ # This is a copy of the implementation from the `package_url` gem with the
5
+ # following license. Original source can be found at:
6
+ # https://github.com/package-url/packageurl-ruby/blob/main/lib/package_url.rb
7
+
8
+ # MIT License
9
+ #
10
+ # Copyright (c) 2021 package-url
11
+ #
12
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ # of this software and associated documentation files (the "Software"), to deal
14
+ # in the Software without restriction, including without limitation the rights
15
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ # copies of the Software, and to permit persons to whom the Software is
17
+ # furnished to do so, subject to the following conditions:
18
+ #
19
+ # The above copyright notice and this permission notice shall be included in all
20
+ # copies or substantial portions of the Software.
21
+ #
22
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ # SOFTWARE.
29
+
30
+ require "uri"
31
+
32
+ # A package URL, or _purl_, is a URL string used to
33
+ # identify and locate a software package in a mostly universal and uniform way
34
+ # across programing languages, package managers, packaging conventions, tools,
35
+ # APIs and databases.
36
+ #
37
+ # A purl is a URL composed of seven components:
38
+ #
39
+ # ```
40
+ # scheme:type/namespace/name@version?qualifiers#subpath
41
+ # ```
42
+ #
43
+ # For example,
44
+ # the package URL for this Ruby package at version 0.1.0 is
45
+ # `pkg:ruby/mattt/packageurl-ruby@0.1.0`.
46
+ module Tapioca
47
+ module Helpers
48
+ class PackageURL
49
+ # Raised when attempting to parse an invalid package URL string.
50
+ # @see #parse
51
+ class InvalidPackageURL < ArgumentError; end
52
+
53
+ # The URL scheme, which has a constant value of `"pkg"`.
54
+ def scheme
55
+ "pkg"
56
+ end
57
+
58
+ # The package type or protocol, such as `"gem"`, `"npm"`, and `"github"`.
59
+ attr_reader :type
60
+
61
+ # A name prefix, specific to the type of package.
62
+ # For example, an npm scope, a Docker image owner, or a GitHub user.
63
+ attr_reader :namespace
64
+
65
+ # The name of the package.
66
+ attr_reader :name
67
+
68
+ # The version of the package.
69
+ attr_reader :version
70
+
71
+ # Extra qualifying data for a package, specific to the type of package.
72
+ # For example, the operating system or architecture.
73
+ attr_reader :qualifiers
74
+
75
+ # An extra subpath within a package, relative to the package root.
76
+ attr_reader :subpath
77
+
78
+ # Constructs a package URL from its components
79
+ # @param type [String] The package type or protocol.
80
+ # @param namespace [String] A name prefix, specific to the type of package.
81
+ # @param name [String] The name of the package.
82
+ # @param version [String] The version of the package.
83
+ # @param qualifiers [Hash] Extra qualifying data for a package, specific to the type of package.
84
+ # @param subpath [String] An extra subpath within a package, relative to the package root.
85
+ def initialize(type:, name:, namespace: nil, version: nil, qualifiers: nil, subpath: nil)
86
+ raise ArgumentError, "type is required" if type.nil? || type.empty?
87
+ raise ArgumentError, "name is required" if name.nil? || name.empty?
88
+
89
+ @type = type.downcase
90
+ @namespace = namespace
91
+ @name = name
92
+ @version = version
93
+ @qualifiers = qualifiers
94
+ @subpath = subpath
95
+ end
96
+
97
+ # Creates a new PackageURL from a string.
98
+ # @param [String] string The package URL string.
99
+ # @raise [InvalidPackageURL] If the string is not a valid package URL.
100
+ # @return [PackageURL]
101
+ def self.parse(string)
102
+ components = {
103
+ type: nil,
104
+ namespace: nil,
105
+ name: nil,
106
+ version: nil,
107
+ qualifiers: nil,
108
+ subpath: nil,
109
+ }
110
+
111
+ # Split the purl string once from right on '#'
112
+ # - The left side is the remainder
113
+ # - Strip the right side from leading and trailing '/'
114
+ # - Split this on '/'
115
+ # - Discard any empty string segment from that split
116
+ # - Discard any '.' or '..' segment from that split
117
+ # - Percent-decode each segment
118
+ # - UTF-8-decode each segment if needed in your programming language
119
+ # - Join segments back with a '/'
120
+ # - This is the subpath
121
+ case string.rpartition("#")
122
+ in String => remainder, separator, String => subpath unless separator.empty?
123
+ subpath_components = []
124
+ subpath.split("/").each do |segment|
125
+ next if segment.empty? || segment == "." || segment == ".."
126
+
127
+ subpath_components << URI.decode_www_form_component(segment)
128
+ end
129
+
130
+ components[:subpath] = subpath_components.compact.join("/")
131
+
132
+ string = remainder
133
+ else
134
+ components[:subpath] = nil
135
+ end
136
+
137
+ # Split the remainder once from right on '?'
138
+ # - The left side is the remainder
139
+ # - The right side is the qualifiers string
140
+ # - Split the qualifiers on '&'. Each part is a key=value pair
141
+ # - For each pair, split the key=value once from left on '=':
142
+ # - The key is the lowercase left side
143
+ # - The value is the percent-decoded right side
144
+ # - UTF-8-decode the value if needed in your programming language
145
+ # - Discard any key/value pairs where the value is empty
146
+ # - If the key is checksums,
147
+ # split the value on ',' to create a list of checksums
148
+ # - This list of key/value is the qualifiers object
149
+ case string.rpartition("?")
150
+ in String => remainder, separator, String => qualifiers unless separator.empty?
151
+ components[:qualifiers] = {}
152
+
153
+ qualifiers.split("&").each do |pair|
154
+ case pair.partition("=")
155
+ in String => key, separator, String => value unless separator.empty?
156
+ key = key.downcase
157
+ value = URI.decode_www_form_component(value)
158
+ next if value.empty?
159
+
160
+ components[:qualifiers][key] = case key
161
+ when "checksums"
162
+ value.split(",")
163
+ else
164
+ value
165
+ end
166
+ else
167
+ next
168
+ end
169
+ end
170
+
171
+ string = remainder
172
+ else
173
+ components[:qualifiers] = nil
174
+ end
175
+
176
+ # Split the remainder once from left on ':'
177
+ # - The left side lowercased is the scheme
178
+ # - The right side is the remainder
179
+ case string.partition(":")
180
+ in "pkg", separator, String => remainder unless separator.empty?
181
+ string = remainder
182
+ else
183
+ raise InvalidPackageURL, 'invalid or missing "pkg:" URL scheme'
184
+ end
185
+
186
+ # Strip the remainder from leading and trailing '/'
187
+ # Use gsub to remove ALL leading slashes instead of just one
188
+ string = string.gsub(%r{^/+}, "").delete_suffix("/")
189
+ # - Split this once from left on '/'
190
+ # - The left side lowercased is the type
191
+ # - The right side is the remainder
192
+ case string.partition("/")
193
+ in String => type, separator, remainder unless separator.empty?
194
+ components[:type] = type
195
+
196
+ string = remainder
197
+ else
198
+ raise InvalidPackageURL, "invalid or missing package type"
199
+ end
200
+
201
+ # Split the remainder once from right on '@'
202
+ # - The left side is the remainder
203
+ # - Percent-decode the right side. This is the version.
204
+ # - UTF-8-decode the version if needed in your programming language
205
+ # - This is the version
206
+ case string.rpartition("@")
207
+ in String => remainder, separator, String => version unless separator.empty?
208
+ components[:version] = URI.decode_www_form_component(version)
209
+
210
+ string = remainder
211
+ else
212
+ components[:version] = nil
213
+ end
214
+
215
+ # Split the remainder once from right on '/'
216
+ # - The left side is the remainder
217
+ # - Percent-decode the right side. This is the name
218
+ # - UTF-8-decode this name if needed in your programming language
219
+ # - Apply type-specific normalization to the name if needed
220
+ # - This is the name
221
+ case string.rpartition("/")
222
+ in String => remainder, separator, String => name unless separator.empty?
223
+ components[:name] = URI.decode_www_form_component(name)
224
+
225
+ # Split the remainder on '/'
226
+ # - Discard any empty segment from that split
227
+ # - Percent-decode each segment
228
+ # - UTF-8-decode the each segment if needed in your programming language
229
+ # - Apply type-specific normalization to each segment if needed
230
+ # - Join segments back with a '/'
231
+ # - This is the namespace
232
+ components[:namespace] = remainder.split("/").map { |s| URI.decode_www_form_component(s) }.compact.join("/")
233
+ in _, _, String => name
234
+ components[:name] = URI.decode_www_form_component(name)
235
+ components[:namespace] = nil
236
+ end
237
+
238
+ # Ensure type and name are not nil before creating the PackageURL instance
239
+ raise InvalidPackageURL, "missing package type" if components[:type].nil?
240
+ raise InvalidPackageURL, "missing package name" if components[:name].nil?
241
+
242
+ # Create a new PackageURL with validated components
243
+ type = components[:type] || "" # This ensures type is never nil
244
+ name = components[:name] || "" # This ensures name is never nil
245
+
246
+ new(
247
+ type: type,
248
+ name: name,
249
+ namespace: components[:namespace],
250
+ version: components[:version],
251
+ qualifiers: components[:qualifiers],
252
+ subpath: components[:subpath],
253
+ )
254
+ end
255
+
256
+ # Returns a hash containing the
257
+ # scheme, type, namespace, name, version, qualifiers, and subpath components
258
+ # of the package URL.
259
+ def to_h
260
+ {
261
+ scheme: scheme,
262
+ type: @type,
263
+ namespace: @namespace,
264
+ name: @name,
265
+ version: @version,
266
+ qualifiers: @qualifiers,
267
+ subpath: @subpath,
268
+ }
269
+ end
270
+
271
+ # Returns a string representation of the package URL.
272
+ # Package URL representations are created according to the instructions from
273
+ # https://github.com/package-url/purl-spec/blob/0b1559f76b79829e789c4f20e6d832c7314762c5/PURL-SPECIFICATION.rst#how-to-build-purl-string-from-its-components.
274
+ def to_s
275
+ # Start a purl string with the "pkg:" scheme as a lowercase ASCII string
276
+ purl = "pkg:"
277
+
278
+ # Append the type string to the purl as a lowercase ASCII string
279
+ # Append '/' to the purl
280
+
281
+ purl += @type
282
+ purl += "/"
283
+
284
+ # If the namespace is not empty:
285
+ # - Strip the namespace from leading and trailing '/'
286
+ # - Split on '/' as segments
287
+ # - Apply type-specific normalization to each segment if needed
288
+ # - UTF-8-encode each segment if needed in your programming language
289
+ # - Percent-encode each segment
290
+ # - Join the segments with '/'
291
+ # - Append this to the purl
292
+ # - Append '/' to the purl
293
+ # - Strip the name from leading and trailing '/'
294
+ # - Apply type-specific normalization to the name if needed
295
+ # - UTF-8-encode the name if needed in your programming language
296
+ # - Append the percent-encoded name to the purl
297
+ #
298
+ # If the namespace is empty:
299
+ # - Apply type-specific normalization to the name if needed
300
+ # - UTF-8-encode the name if needed in your programming language
301
+ # - Append the percent-encoded name to the purl
302
+ case @namespace
303
+ in String => namespace unless namespace.empty?
304
+ segments = []
305
+ @namespace.delete_prefix("/").delete_suffix("/").split("/").each do |segment|
306
+ next if segment.empty?
307
+
308
+ segments << URI.encode_www_form_component(segment)
309
+ end
310
+ purl += segments.join("/")
311
+
312
+ purl += "/"
313
+ purl += URI.encode_www_form_component(@name.delete_prefix("/").delete_suffix("/"))
314
+ else
315
+ purl += URI.encode_www_form_component(@name)
316
+ end
317
+
318
+ # If the version is not empty:
319
+ # - Append '@' to the purl
320
+ # - UTF-8-encode the version if needed in your programming language
321
+ # - Append the percent-encoded version to the purl
322
+ case @version
323
+ in String => version unless version.empty?
324
+ purl += "@"
325
+ purl += URI.encode_www_form_component(@version)
326
+ else
327
+ nil
328
+ end
329
+
330
+ # If the qualifiers are not empty and not composed only of key/value pairs
331
+ # where the value is empty:
332
+ # - Append '?' to the purl
333
+ # - Build a list from all key/value pair:
334
+ # - discard any pair where the value is empty.
335
+ # - UTF-8-encode each value if needed in your programming language
336
+ # - If the key is checksums and this is a list of checksums
337
+ # join this list with a ',' to create this qualifier value
338
+ # - create a string by joining the lowercased key,
339
+ # the equal '=' sign and the percent-encoded value to create a qualifier
340
+ # - sort this list of qualifier strings lexicographically
341
+ # - join this list of qualifier strings with a '&' ampersand
342
+ # - Append this string to the purl
343
+ case @qualifiers
344
+ in Hash => qualifiers unless qualifiers.empty?
345
+ list = []
346
+ qualifiers.each do |key, value|
347
+ next if value.empty?
348
+
349
+ list << case [key, value]
350
+ in "checksums", Array => checksums
351
+ "#{key.downcase}=#{checksums.join(",")}"
352
+ else
353
+ "#{key.downcase}=#{URI.encode_www_form_component(value)}"
354
+ end
355
+ end
356
+
357
+ unless list.empty?
358
+ purl += "?"
359
+ purl += list.sort.join("&")
360
+ end
361
+ else
362
+ nil
363
+ end
364
+
365
+ # If the subpath is not empty and not composed only of
366
+ # empty, '.' and '..' segments:
367
+ # - Append '#' to the purl
368
+ # - Strip the subpath from leading and trailing '/'
369
+ # - Split this on '/' as segments
370
+ # - Discard empty, '.' and '..' segments
371
+ # - Percent-encode each segment
372
+ # - UTF-8-encode each segment if needed in your programming language
373
+ # - Join the segments with '/'
374
+ # - Append this to the purl
375
+ case @subpath
376
+ in String => subpath unless subpath.empty?
377
+ segments = []
378
+ subpath.delete_prefix("/").delete_suffix("/").split("/").each do |segment|
379
+ next if segment.empty? || segment == "." || segment == ".."
380
+
381
+ # Custom encoding for URL fragment segments:
382
+ # 1. Explicitly encode % as %25 to prevent double-encoding issues
383
+ # 2. Percent-encode special characters according to URL fragment rules
384
+ # 3. This ensures proper round-trip encoding/decoding with the parse method
385
+ segments << segment.gsub(/%|[^A-Za-z0-9\-\._~:]/) do |m|
386
+ m == "%" ? "%25" : format("%%%02X", m.ord)
387
+ end
388
+ end
389
+
390
+ unless segments.empty?
391
+ purl += "#"
392
+ purl += segments.join("/")
393
+ end
394
+ else
395
+ nil
396
+ end
397
+
398
+ purl
399
+ end
400
+
401
+ # Returns an array containing the
402
+ # scheme, type, namespace, name, version, qualifiers, and subpath components
403
+ # of the package URL.
404
+ def deconstruct
405
+ [scheme, @type, @namespace, @name, @version, @qualifiers, @subpath]
406
+ end
407
+
408
+ # Returns a hash containing the
409
+ # scheme, type, namespace, name, version, qualifiers, and subpath components
410
+ # of the package URL.
411
+ def deconstruct_keys(_keys)
412
+ to_h
413
+ end
414
+ end
415
+ end
416
+ end
@@ -5,7 +5,6 @@ module Tapioca
5
5
  # @requires_ancestor: Thor::Shell
6
6
  # @requires_ancestor: SorbetHelper
7
7
  module RBIFilesHelper
8
- extend T::Sig
9
8
  #: (RBI::Index index, String kind, String file) -> void
10
9
  def index_rbi(index, kind, file)
11
10
  return unless File.exist?(file)
@@ -64,7 +63,14 @@ module Tapioca
64
63
  url
65
64
  end
66
65
 
67
- #: (command: String, gem_dir: String, dsl_dir: String, auto_strictness: bool, ?gems: Array[Gemfile::GemSpec], ?compilers: T::Enumerable[singleton(Dsl::Compiler)]) -> void
66
+ #: (
67
+ #| command: String,
68
+ #| gem_dir: String,
69
+ #| dsl_dir: String,
70
+ #| auto_strictness: bool,
71
+ #| ?gems: Array[Gemfile::GemSpec],
72
+ #| ?compilers: Enumerable[singleton(Dsl::Compiler)]
73
+ #| ) -> void
68
74
  def validate_rbi_files(command:, gem_dir:, dsl_dir:, auto_strictness:, gems: [], compilers: [])
69
75
  error_url_base = Spoom::Sorbet::Errors::DEFAULT_ERROR_URL_BASE
70
76
 
@@ -3,14 +3,11 @@
3
3
 
4
4
  module Tapioca
5
5
  module RBIHelper
6
- extend T::Sig
7
6
  include SorbetHelper
8
7
  extend SorbetHelper
9
8
  extend self
10
9
 
11
10
  class << self
12
- extend T::Sig
13
-
14
11
  #: (String type, Symbol variance, String? fixed, String? upper, String? lower) -> String
15
12
  def serialize_type_variable(type, variance, fixed, upper, lower)
16
13
  variance = nil if variance == :invariant
@@ -3,8 +3,6 @@
3
3
 
4
4
  module Tapioca
5
5
  module SorbetHelper
6
- extend T::Sig
7
-
8
6
  SORBET_GEM_SPEC = ::Gem::Specification.find_by_name("sorbet-static") #: ::Gem::Specification
9
7
 
10
8
  SORBET_BIN = Pathname.new(SORBET_GEM_SPEC.full_gem_path) / "libexec" / "sorbet" #: Pathname
@@ -6,7 +6,6 @@ module Tapioca
6
6
  module Test
7
7
  # @requires_ancestor: Kernel
8
8
  module Content
9
- extend T::Sig
10
9
  #: -> void
11
10
  def teardown
12
11
  super
@@ -12,7 +12,6 @@ module Tapioca
12
12
  module Test
13
13
  # @requires_ancestor: Kernel
14
14
  module DslCompiler
15
- extend T::Sig
16
15
  include Isolation
17
16
  include Content
18
17
  include Template
@@ -50,8 +49,6 @@ module Tapioca
50
49
  end
51
50
 
52
51
  class CompilerContext
53
- extend T::Sig
54
-
55
52
  include SorbetHelper
56
53
 
57
54
  #: singleton(Tapioca::Dsl::Compiler)
@@ -7,12 +7,9 @@ module Tapioca
7
7
  # Copied from ActiveSupport::Testing::Isolation since we cannot require
8
8
  # constants from ActiveSupport without polluting the global namespace.
9
9
  module Isolation
10
- extend T::Sig
11
10
  require "thread"
12
11
 
13
12
  class << self
14
- extend T::Sig
15
-
16
13
  #: -> bool
17
14
  def forking_env?
18
15
  !ENV["NO_FORK"] && Process.respond_to?(:fork)
@@ -30,7 +27,6 @@ module Tapioca
30
27
 
31
28
  # @requires_ancestor: Kernel
32
29
  module Forking
33
- extend T::Sig
34
30
  #: ?{ (?) -> untyped } -> String
35
31
  def run_in_isolation(&_blk)
36
32
  read, write = IO.pipe
@@ -72,8 +68,6 @@ module Tapioca
72
68
 
73
69
  # @requires_ancestor: Kernel
74
70
  module Subprocess
75
- extend T::Sig
76
-
77
71
  ORIG_ARGV = ARGV.dup #: Array[String]
78
72
 
79
73
  # Crazy H4X to get this working in windows / jruby with
@@ -6,9 +6,6 @@ module Tapioca
6
6
  module Test
7
7
  # @requires_ancestor: Kernel
8
8
  module Template
9
- extend T::Sig
10
- ERB_SUPPORTS_KVARGS = ::ERB.instance_method(:initialize).parameters.assoc(:key) #: [Symbol, Symbol]?
11
-
12
9
  #: (String selector) -> bool
13
10
  def ruby_version(selector)
14
11
  ::Gem::Requirement.new(selector).satisfied_by?(::Gem::Version.new(RUBY_VERSION))
@@ -21,12 +18,7 @@ module Tapioca
21
18
 
22
19
  #: (String src, ?trim_mode: String) -> String
23
20
  def template(src, trim_mode: ">")
24
- erb = if ERB_SUPPORTS_KVARGS
25
- ::ERB.new(src, trim_mode: trim_mode)
26
- else
27
- ::ERB.new(src, nil, trim_mode)
28
- end
29
-
21
+ erb = ::ERB.new(src, trim_mode: trim_mode)
30
22
  erb.result(binding)
31
23
  end
32
24
 
@@ -49,7 +49,7 @@ require "tapioca/helpers/git_attributes"
49
49
  require "tapioca/helpers/sorbet_helper"
50
50
  require "tapioca/helpers/rbi_helper"
51
51
 
52
- require "tapioca/helpers/source_uri"
52
+ require "tapioca/helpers/package_url"
53
53
  require "tapioca/helpers/cli_helper"
54
54
  require "tapioca/helpers/config_helper"
55
55
  require "tapioca/helpers/rbi_files_helper"
@@ -4,11 +4,7 @@
4
4
  module Tapioca
5
5
  module Loaders
6
6
  class Dsl < Loader
7
- extend T::Sig
8
-
9
7
  class << self
10
- extend T::Sig
11
-
12
8
  #: (tapioca_path: String, ?eager_load: bool, ?app_root: String, ?halt_upon_load_error: bool) -> void
13
9
  def load_application(
14
10
  tapioca_path:,
@@ -4,12 +4,14 @@
4
4
  module Tapioca
5
5
  module Loaders
6
6
  class Gem < Loader
7
- extend T::Sig
8
-
9
7
  class << self
10
- extend T::Sig
11
-
12
- #: (bundle: Gemfile, prerequire: String?, postrequire: String, default_command: String, halt_upon_load_error: bool) -> void
8
+ #: (
9
+ #| bundle: Gemfile,
10
+ #| prerequire: String?,
11
+ #| postrequire: String,
12
+ #| default_command: String,
13
+ #| halt_upon_load_error: bool
14
+ #| ) -> void
13
15
  def load_application(bundle:, prerequire:, postrequire:, default_command:, halt_upon_load_error:)
14
16
  loader = new(
15
17
  bundle: bundle,
@@ -30,7 +32,13 @@ module Tapioca
30
32
 
31
33
  protected
32
34
 
33
- #: (bundle: Gemfile, prerequire: String?, postrequire: String, default_command: String, halt_upon_load_error: bool) -> void
35
+ #: (
36
+ #| bundle: Gemfile,
37
+ #| prerequire: String?,
38
+ #| postrequire: String,
39
+ #| default_command: String,
40
+ #| halt_upon_load_error: bool
41
+ #| ) -> void
34
42
  def initialize(bundle:, prerequire:, postrequire:, default_command:, halt_upon_load_error:)
35
43
  super()
36
44
 
@@ -5,7 +5,6 @@ module Tapioca
5
5
  module Loaders
6
6
  # @abstract
7
7
  class Loader
8
- extend T::Sig
9
8
  include Thor::Base
10
9
  include CliHelper
11
10
  include Tapioca::GemHelper
@@ -3,9 +3,7 @@
3
3
 
4
4
  module RBI
5
5
  class Tree
6
- extend T::Sig
7
-
8
- #: (::Module constant) ?{ (Scope scope) -> void } -> Scope
6
+ #: (T::Module[top] constant) ?{ (Scope scope) -> void } -> Scope
9
7
  def create_path(constant, &block)
10
8
  constant_name = Tapioca::Runtime::Reflection.name_of(constant)
11
9
  raise "given constant does not have a name" unless constant_name
@@ -61,7 +59,14 @@ module RBI
61
59
  create_node(RBI::TypeMember.new(name, value))
62
60
  end
63
61
 
64
- #: (String name, ?parameters: Array[TypedParam], ?return_type: String?, ?class_method: bool, ?visibility: RBI::Visibility, ?comments: Array[RBI::Comment]) ?{ (RBI::Method node) -> void } -> void
62
+ #: (
63
+ #| String name,
64
+ #| ?parameters: Array[TypedParam],
65
+ #| ?return_type: String?,
66
+ #| ?class_method: bool,
67
+ #| ?visibility: RBI::Visibility,
68
+ #| ?comments: Array[RBI::Comment]
69
+ #| ) ?{ (RBI::Method node) -> void } -> void
65
70
  def create_method(name, parameters: [], return_type: nil, class_method: false, visibility: RBI::Public.new,
66
71
  comments: [], &block)
67
72
  return unless Tapioca::RBIHelper.valid_method_name?(name)
@@ -3,8 +3,6 @@
3
3
 
4
4
  module Tapioca
5
5
  class RBIFormatter < RBI::Formatter
6
- extend T::Sig
7
-
8
6
  #: (RBI::File file, String command, ?reason: String?) -> void
9
7
  def write_header!(file, command, reason: nil)
10
8
  file.comments << RBI::Comment.new("DO NOT EDIT MANUALLY")
@@ -3,10 +3,7 @@
3
3
 
4
4
  module Tapioca
5
5
  class RepoIndex
6
- extend T::Sig
7
6
  class << self
8
- extend T::Sig
9
-
10
7
  #: (String json) -> RepoIndex
11
8
  def from_json(json)
12
9
  RepoIndex.from_hash(JSON.parse(json))
@@ -30,7 +27,7 @@ module Tapioca
30
27
  @entries.add(gem_name)
31
28
  end
32
29
 
33
- #: -> T::Enumerable[String]
30
+ #: -> Enumerable[String]
34
31
  def gems
35
32
  @entries.sort
36
33
  end