tapioca 0.11.6 → 0.11.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ee3bcaf55b533576a46aa60a0a03b946552ee3fba42f8b136108dea8d0888ba
4
- data.tar.gz: b0d12f84750676a3b99eb7e76e10d3be64a92359f5a440c0c8c5ef9c7f3e5ac9
3
+ metadata.gz: 68b1a51d995ed5925df2983b0fdc55ef14bdfb828780077035048f1a6305ad74
4
+ data.tar.gz: 9689fa2965d90459e47618b2d41df0e24acdb9599d3552205ed973fa37126c9b
5
5
  SHA512:
6
- metadata.gz: cf6bb9e139fabc27048c5237f0e8662f5972051ae01fd1fcaae34f11c23fceb471f7d7118df9dabd507b24f7fccf8d4a6208dfd02d08ed37453b1ef2679ba04f
7
- data.tar.gz: 2860aaa02b120a10182e7928fdc54f48d6eca933f4eee8ec51df78ae59043bc59c6cc839b1a65d2fe610c3ec545ad68b2caf400821b32c7ee029ca0046b88009
6
+ metadata.gz: 78cfdeb935bd82157c0f98344af6e131f5c5d0b256076ac69b1518f044f08ace764cfe7efe153928c7209a451ce194ae7d2ac82cebf68c1aed937b3016ba6cb3
7
+ data.tar.gz: d51e8ca0aafb1764efa553387d2569aec765c0eb6d5ac8344843b131d75fa6b2daa5bca6daa4304229eb6313ef244752fb1ec66c2c10d5868ee8983174bf5f3e
data/README.md CHANGED
@@ -163,36 +163,38 @@ Usage:
163
163
  tapioca gem [gem...]
164
164
 
165
165
  Options:
166
- --out, -o, [--outdir=directory] # The output directory for generated gem RBI files
167
- # Default: sorbet/rbi/gems
168
- [--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
169
- # Default: true
170
- [--all], [--no-all] # Regenerate RBI files for all gems
171
- --pre, -b, [--prerequire=file] # A file to be required before Bundler.require is called
172
- --post, -a, [--postrequire=file] # A file to be required after Bundler.require is called
173
- # Default: sorbet/tapioca/require.rb
174
- -x, [--exclude=gem [gem ...]] # Exclude the given gem(s) from RBI generation
175
- --typed, -t, [--typed-overrides=gem:level [gem:level ...]] # Override for typed sigils for generated gem RBIs
176
- # Default: {"activesupport"=>"false"}
177
- [--verify], [--no-verify] # Verify RBIs are up-to-date
178
- [--doc], [--no-doc] # Include YARD documentation from sources when generating RBIs. Warning: this might be slow
179
- # Default: true
180
- [--loc], [--no-loc] # Include comments with source location when generating RBIs
181
- # Default: true
182
- [--exported-gem-rbis], [--no-exported-gem-rbis] # Include RBIs found in the `rbi/` directory of the gem
183
- # Default: true
184
- -w, [--workers=N] # Number of parallel workers to use when generating RBIs (default: auto)
185
- [--auto-strictness], [--no-auto-strictness] # Autocorrect strictness in gem RBIs in case of conflict with the DSL RBIs
186
- # Default: true
187
- --dsl-dir, [--dsl-dir=directory] # The DSL directory used to correct gems strictnesses
188
- # Default: sorbet/rbi/dsl
189
- [--rbi-max-line-length=N] # Set the max line length of generated RBIs. Signatures longer than the max line length will be wrapped
190
- # Default: 120
191
- -e, [--environment=ENVIRONMENT] # The Rack/Rails environment to use when generating RBIs
192
- # Default: development
193
- -c, [--config=<config file path>] # Path to the Tapioca configuration file
194
- # Default: sorbet/tapioca/config.yml
195
- -V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
166
+ --out, -o, [--outdir=directory] # The output directory for generated gem RBI files
167
+ # Default: sorbet/rbi/gems
168
+ [--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
169
+ # Default: true
170
+ [--all], [--no-all] # Regenerate RBI files for all gems
171
+ --pre, -b, [--prerequire=file] # A file to be required before Bundler.require is called
172
+ --post, -a, [--postrequire=file] # A file to be required after Bundler.require is called
173
+ # Default: sorbet/tapioca/require.rb
174
+ -x, [--exclude=gem [gem ...]] # Exclude the given gem(s) from RBI generation
175
+ --typed, -t, [--typed-overrides=gem:level [gem:level ...]] # Override for typed sigils for generated gem RBIs
176
+ # Default: {"activesupport"=>"false"}
177
+ [--verify], [--no-verify] # Verify RBIs are up-to-date
178
+ [--doc], [--no-doc] # Include YARD documentation from sources when generating RBIs. Warning: this might be slow
179
+ # Default: true
180
+ [--loc], [--no-loc] # Include comments with source location when generating RBIs
181
+ # Default: true
182
+ [--exported-gem-rbis], [--no-exported-gem-rbis] # Include RBIs found in the `rbi/` directory of the gem
183
+ # Default: true
184
+ -w, [--workers=N] # Number of parallel workers to use when generating RBIs (default: auto)
185
+ [--auto-strictness], [--no-auto-strictness] # Autocorrect strictness in gem RBIs in case of conflict with the DSL RBIs
186
+ # Default: true
187
+ --dsl-dir, [--dsl-dir=directory] # The DSL directory used to correct gems strictnesses
188
+ # Default: sorbet/rbi/dsl
189
+ [--rbi-max-line-length=N] # Set the max line length of generated RBIs. Signatures longer than the max line length will be wrapped
190
+ # Default: 120
191
+ -e, [--environment=ENVIRONMENT] # The Rack/Rails environment to use when generating RBIs
192
+ # Default: development
193
+ [--halt-upon-load-error], [--no-halt-upon-load-error] # Halt upon a load error while loading the Rails application
194
+ # Default: true
195
+ -c, [--config=<config file path>] # Path to the Tapioca configuration file
196
+ # Default: sorbet/tapioca/config.yml
197
+ -V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
196
198
 
197
199
  generate RBIs from gems
198
200
  ```
@@ -347,16 +349,16 @@ Usage:
347
349
  tapioca annotations
348
350
 
349
351
  Options:
350
- [--sources=one two three] # URIs of the sources to pull gem RBI annotations from
352
+ [--sources=one two three] # URIs of the sources to pull gem RBI annotations from
351
353
  # Default: ["https://raw.githubusercontent.com/Shopify/rbi-central/main"]
352
- [--netrc], [--no-netrc] # Use .netrc to authenticate to private sources
354
+ [--netrc], [--no-netrc] # Use .netrc to authenticate to private sources
353
355
  # Default: true
354
- [--netrc-file=NETRC_FILE] # Path to .netrc file
355
- [--auth=AUTH] # HTTP authorization header for private sources
356
+ [--netrc-file=NETRC_FILE] # Path to .netrc file
357
+ [--auth=AUTH] # HTTP authorization header for private sources
356
358
  --typed, -t, [--typed-overrides=gem:level [gem:level ...]] # Override for typed sigils for pulled annotations
357
- -c, [--config=<config file path>] # Path to the Tapioca configuration file
359
+ -c, [--config=<config file path>] # Path to the Tapioca configuration file
358
360
  # Default: sorbet/tapioca/config.yml
359
- -V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
361
+ -V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
360
362
 
361
363
  Pull gem RBI annotations from remote sources
362
364
  ```
@@ -458,26 +460,28 @@ Usage:
458
460
  tapioca dsl [constant...]
459
461
 
460
462
  Options:
461
- --out, -o, [--outdir=directory] # The output directory for generated DSL RBI files
462
- # Default: sorbet/rbi/dsl
463
- [--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
464
- # Default: true
465
- [--only=compiler [compiler ...]] # Only run supplied DSL compiler(s)
466
- [--exclude=compiler [compiler ...]] # Exclude supplied DSL compiler(s)
467
- [--verify], [--no-verify] # Verifies RBIs are up-to-date
468
- -q, [--quiet], [--no-quiet] # Suppresses file creation output
469
- -w, [--workers=N] # Number of parallel workers to use when generating RBIs (default: 2)
470
- # Default: 2
471
- [--rbi-max-line-length=N] # Set the max line length of generated RBIs. Signatures longer than the max line length will be wrapped
472
- # Default: 120
473
- -e, [--environment=ENVIRONMENT] # The Rack/Rails environment to use when generating RBIs
474
- # Default: development
475
- -l, [--list-compilers], [--no-list-compilers] # List all loaded compilers
476
- [--app-root=APP_ROOT] # The path to the Rails application
477
- # Default: .
478
- -c, [--config=<config file path>] # Path to the Tapioca configuration file
479
- # Default: sorbet/tapioca/config.yml
480
- -V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
463
+ --out, -o, [--outdir=directory] # The output directory for generated DSL RBI files
464
+ # Default: sorbet/rbi/dsl
465
+ [--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
466
+ # Default: true
467
+ [--only=compiler [compiler ...]] # Only run supplied DSL compiler(s)
468
+ [--exclude=compiler [compiler ...]] # Exclude supplied DSL compiler(s)
469
+ [--verify], [--no-verify] # Verifies RBIs are up-to-date
470
+ -q, [--quiet], [--no-quiet] # Suppresses file creation output
471
+ -w, [--workers=N] # Number of parallel workers to use when generating RBIs (default: 2)
472
+ # Default: 2
473
+ [--rbi-max-line-length=N] # Set the max line length of generated RBIs. Signatures longer than the max line length will be wrapped
474
+ # Default: 120
475
+ -e, [--environment=ENVIRONMENT] # The Rack/Rails environment to use when generating RBIs
476
+ # Default: development
477
+ -l, [--list-compilers], [--no-list-compilers] # List all loaded compilers
478
+ [--app-root=APP_ROOT] # The path to the Rails application
479
+ # Default: .
480
+ [--halt-upon-load-error], [--no-halt-upon-load-error] # Halt upon a load error while loading the Rails application
481
+ # Default: true
482
+ -c, [--config=<config file path>] # Path to the Tapioca configuration file
483
+ # Default: sorbet/tapioca/config.yml
484
+ -V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
481
485
 
482
486
  generate RBIs for dynamic methods
483
487
  ```
@@ -827,6 +831,7 @@ dsl:
827
831
  environment: development
828
832
  list_compilers: false
829
833
  app_root: "."
834
+ halt_upon_load_error: true
830
835
  gem:
831
836
  outdir: sorbet/rbi/gems
832
837
  file_header: true
@@ -845,6 +850,7 @@ gem:
845
850
  dsl_dir: sorbet/rbi/dsl
846
851
  rbi_max_line_length: 120
847
852
  environment: development
853
+ halt_upon_load_error: true
848
854
  check_shims:
849
855
  gem_rbi_dir: sorbet/rbi/gems
850
856
  dsl_rbi_dir: sorbet/rbi/dsl
@@ -0,0 +1,69 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Tapioca
5
+ module BundlerExt
6
+ # This is a module that gets prepended to `Bundler::Dependency` and
7
+ # makes sure even gems marked as `require: false` are required during
8
+ # `Bundler.require`.
9
+ module AutoRequireHook
10
+ extend T::Sig
11
+ extend T::Helpers
12
+
13
+ requires_ancestor { ::Bundler::Dependency }
14
+
15
+ @exclude = T.let([], T::Array[String])
16
+ @enabled = T.let(false, T::Boolean)
17
+
18
+ class << self
19
+ extend T::Sig
20
+
21
+ sig { params(name: T.untyped).returns(T::Boolean) }
22
+ def excluded?(name)
23
+ @exclude.include?(name)
24
+ end
25
+
26
+ def enabled?
27
+ @enabled
28
+ end
29
+
30
+ sig do
31
+ type_parameters(:Result).params(
32
+ exclude: T::Array[String],
33
+ blk: T.proc.returns(T.type_parameter(:Result)),
34
+ ).returns(T.type_parameter(:Result))
35
+ end
36
+ def override_require_false(exclude:, &blk)
37
+ @enabled = true
38
+ @exclude = exclude
39
+ blk.call
40
+ ensure
41
+ @enabled = false
42
+ end
43
+ end
44
+
45
+ sig { returns(T.untyped).checked(:never) }
46
+ def autorequire
47
+ value = super
48
+
49
+ # If autorequire is not enabled, we don't want to force require gems
50
+ return value unless AutoRequireHook.enabled?
51
+
52
+ # If the gem is excluded, we don't want to force require it, in case
53
+ # it has side-effects users don't want. For example, `fakefs` gem, if
54
+ # loaded, takes over filesystem operations.
55
+ return value if AutoRequireHook.excluded?(name)
56
+
57
+ # If a gem is marked as `require: false`, then its `autorequire`
58
+ # value will be `[]`. But, we want those gems to be loaded for our
59
+ # purposes as well, so we return `nil` in those cases, instead, which
60
+ # means `require: true`.
61
+ return nil if value == []
62
+
63
+ value
64
+ end
65
+
66
+ ::Bundler::Dependency.prepend(self)
67
+ end
68
+ end
69
+ end
data/lib/tapioca/cli.rb CHANGED
@@ -130,6 +130,10 @@ module Tapioca
130
130
  type: :string,
131
131
  desc: "The path to the Rails application",
132
132
  default: "."
133
+ option :halt_upon_load_error,
134
+ type: :boolean,
135
+ desc: "Halt upon a load error while loading the Rails application",
136
+ default: true
133
137
  def dsl(*constant_or_paths)
134
138
  set_environment(options)
135
139
 
@@ -150,6 +154,7 @@ module Tapioca
150
154
  number_of_workers: options[:workers],
151
155
  rbi_formatter: rbi_formatter(options),
152
156
  app_root: options[:app_root],
157
+ halt_upon_load_error: options[:halt_upon_load_error],
153
158
  )
154
159
 
155
160
  Tapioca.silence_warnings do
@@ -235,6 +240,10 @@ module Tapioca
235
240
  type: :string,
236
241
  desc: "The Rack/Rails environment to use when generating RBIs",
237
242
  default: DEFAULT_ENVIRONMENT
243
+ option :halt_upon_load_error,
244
+ type: :boolean,
245
+ desc: "Halt upon a load error while loading the Rails application",
246
+ default: true
238
247
  def gem(*gems)
239
248
  Tapioca.silence_warnings do
240
249
  set_environment(options)
@@ -257,6 +266,7 @@ module Tapioca
257
266
  auto_strictness: options[:auto_strictness],
258
267
  dsl_dir: options[:dsl_dir],
259
268
  rbi_formatter: rbi_formatter(options),
269
+ halt_upon_load_error: options[:halt_upon_load_error],
260
270
  )
261
271
 
262
272
  raise MalformattedArgumentError, "Options '--all' and '--verify' are mutually exclusive" if all && verify
@@ -24,6 +24,7 @@ module Tapioca
24
24
  gem_dir: String,
25
25
  rbi_formatter: RBIFormatter,
26
26
  app_root: String,
27
+ halt_upon_load_error: T::Boolean,
27
28
  ).void
28
29
  end
29
30
  def initialize(
@@ -41,7 +42,8 @@ module Tapioca
41
42
  auto_strictness: true,
42
43
  gem_dir: DEFAULT_GEM_DIR,
43
44
  rbi_formatter: DEFAULT_RBI_FORMATTER,
44
- app_root: "."
45
+ app_root: ".",
46
+ halt_upon_load_error: true
45
47
  )
46
48
  @requested_constants = requested_constants
47
49
  @requested_paths = requested_paths
@@ -58,6 +60,7 @@ module Tapioca
58
60
  @gem_dir = gem_dir
59
61
  @rbi_formatter = rbi_formatter
60
62
  @app_root = app_root
63
+ @halt_upon_load_error = halt_upon_load_error
61
64
 
62
65
  super()
63
66
  end
@@ -68,6 +71,7 @@ module Tapioca
68
71
  tapioca_path: @tapioca_path,
69
72
  eager_load: @requested_constants.empty? && @requested_paths.empty?,
70
73
  app_root: @app_root,
74
+ halt_upon_load_error: @halt_upon_load_error,
71
75
  )
72
76
 
73
77
  pipeline = create_pipeline
@@ -95,6 +99,7 @@ module Tapioca
95
99
  tapioca_path: @tapioca_path,
96
100
  eager_load: @requested_constants.empty? && @requested_paths.empty?,
97
101
  app_root: @app_root,
102
+ halt_upon_load_error: @halt_upon_load_error,
98
103
  )
99
104
 
100
105
  if @should_verify
@@ -23,6 +23,7 @@ module Tapioca
23
23
  auto_strictness: T::Boolean,
24
24
  dsl_dir: String,
25
25
  rbi_formatter: RBIFormatter,
26
+ halt_upon_load_error: T::Boolean,
26
27
  ).void
27
28
  end
28
29
  def initialize(
@@ -39,7 +40,8 @@ module Tapioca
39
40
  number_of_workers: nil,
40
41
  auto_strictness: true,
41
42
  dsl_dir: DEFAULT_DSL_DIR,
42
- rbi_formatter: DEFAULT_RBI_FORMATTER
43
+ rbi_formatter: DEFAULT_RBI_FORMATTER,
44
+ halt_upon_load_error: true
43
45
  )
44
46
  @gem_names = gem_names
45
47
  @exclude = exclude
@@ -61,6 +63,7 @@ module Tapioca
61
63
  @include_doc = T.let(include_doc, T::Boolean)
62
64
  @include_loc = T.let(include_loc, T::Boolean)
63
65
  @include_exported_rbis = include_exported_rbis
66
+ @halt_upon_load_error = halt_upon_load_error
64
67
  end
65
68
 
66
69
  sig { override.void }
@@ -70,6 +73,7 @@ module Tapioca
70
73
  prerequire: @prerequire,
71
74
  postrequire: @postrequire,
72
75
  default_command: default_command(:require),
76
+ halt_upon_load_error: @halt_upon_load_error,
73
77
  )
74
78
 
75
79
  gem_queue = gems_to_generate(@gem_names).reject { |gem| @exclude.include?(gem.name) }
@@ -245,6 +249,7 @@ module Tapioca
245
249
  prerequire: @prerequire,
246
250
  postrequire: @postrequire,
247
251
  default_command: default_command(:require),
252
+ halt_upon_load_error: @halt_upon_load_error,
248
253
  )
249
254
 
250
255
  Executor.new(gems, number_of_workers: @number_of_workers).run_in_parallel do |gem_name|
@@ -43,10 +43,10 @@ module Tapioca
43
43
 
44
44
  private
45
45
 
46
- sig { returns(T::Enumerable[Class]) }
46
+ sig { returns(T::Enumerable[T::Class[T.anything]]) }
47
47
  def all_classes
48
- @all_classes = T.let(@all_classes, T.nilable(T::Enumerable[Class]))
49
- @all_classes ||= T.cast(ObjectSpace.each_object(Class), T::Enumerable[Class]).each
48
+ @all_classes = T.let(@all_classes, T.nilable(T::Enumerable[T::Class[T.anything]]))
49
+ @all_classes ||= T.cast(ObjectSpace.each_object(Class), T::Enumerable[T::Class[T.anything]]).each
50
50
  end
51
51
 
52
52
  sig { returns(T::Enumerable[Module]) }
@@ -74,7 +74,7 @@ module Tapioca
74
74
  T::Array[String],
75
75
  )
76
76
 
77
- ConstantType = type_member { { fixed: T.all(::AASM::ClassMethods, Class) } }
77
+ ConstantType = type_member { { fixed: T.all(T::Class[::AASM], ::AASM::ClassMethods) } }
78
78
 
79
79
  sig { override.void }
80
80
  def decorate
@@ -39,7 +39,9 @@ module Tapioca
39
39
  class ActiveModelAttributes < Compiler
40
40
  extend T::Sig
41
41
 
42
- ConstantType = type_member { { fixed: T.all(Class, ::ActiveModel::Attributes::ClassMethods) } }
42
+ ConstantType = type_member do
43
+ { fixed: T.all(T::Class[::ActiveModel::Attributes], ::ActiveModel::Attributes::ClassMethods) }
44
+ end
43
45
 
44
46
  sig { override.void }
45
47
  def decorate
@@ -60,7 +60,9 @@ module Tapioca
60
60
  class ActiveModelSecurePassword < Compiler
61
61
  extend T::Sig
62
62
 
63
- ConstantType = type_member { { fixed: T.all(Class, ::ActiveModel::SecurePassword::ClassMethods) } }
63
+ ConstantType = type_member do
64
+ { fixed: T.all(T::Class[::ActiveModel::SecurePassword], ::ActiveModel::SecurePassword::ClassMethods) }
65
+ end
64
66
 
65
67
  sig { override.void }
66
68
  def decorate
@@ -110,10 +110,11 @@ module Tapioca
110
110
  return_type: "ActiveSupport::StringInquirer",
111
111
  )
112
112
 
113
+ return_type = sorbet_supports?(:generic_class) ? "T::Class[T.anything]" : "Class"
113
114
  mod.create_method(
114
115
  "#{role}_class",
115
116
  parameters: [],
116
- return_type: "Class",
117
+ return_type: return_type,
117
118
  )
118
119
 
119
120
  mod.create_method(
@@ -70,15 +70,24 @@ module Tapioca
70
70
 
71
71
  private
72
72
 
73
- sig { returns(Class) }
73
+ sig { returns(T::Class[ActiveRecord::TestFixtures]) }
74
74
  def fixture_loader
75
75
  @fixture_loader ||= T.let(
76
- Class.new do
77
- T.unsafe(self).include(ActiveRecord::TestFixtures)
78
- T.unsafe(self).fixture_path = Rails.root.join("test", "fixtures")
79
- T.unsafe(self).fixtures(:all)
80
- end,
81
- T.nilable(Class),
76
+ T.cast(
77
+ Class.new do
78
+ T.unsafe(self).include(ActiveRecord::TestFixtures)
79
+
80
+ T.unsafe(self).fixture_path = Rails.root.join("test", "fixtures")
81
+ # https://github.com/rails/rails/blob/7c70791470fc517deb7c640bead9f1b47efb5539/activerecord/lib/active_record/test_fixtures.rb#L46
82
+ singleton_class.define_method(:file_fixture_path) do
83
+ Rails.root.join("test", "fixtures", "files")
84
+ end
85
+
86
+ T.unsafe(self).fixtures(:all)
87
+ end,
88
+ T::Class[ActiveRecord::TestFixtures],
89
+ ),
90
+ T.nilable(T::Class[ActiveRecord::TestFixtures]),
82
91
  )
83
92
  end
84
93
 
@@ -70,7 +70,9 @@ module Tapioca
70
70
  class Kredis < Compiler
71
71
  extend T::Sig
72
72
 
73
- ConstantType = type_member { { fixed: T.all(Class, ::Kredis::Attributes::ClassMethods, Extensions::Kredis) } }
73
+ ConstantType = type_member do
74
+ { fixed: T.all(T::Class[::Kredis::Attributes], ::Kredis::Attributes::ClassMethods, Extensions::Kredis) }
75
+ end
74
76
 
75
77
  sig { override.void }
76
78
  def decorate
@@ -78,7 +78,7 @@ module Tapioca
78
78
 
79
79
  extend T::Sig
80
80
 
81
- ConstantType = type_member { { fixed: Module } }
81
+ ConstantType = type_member { { fixed: T::Class[T.anything] } }
82
82
 
83
83
  FIELD_RE = /^[a-z_][a-zA-Z0-9_]*$/
84
84
 
@@ -206,7 +206,7 @@ module Tapioca
206
206
  # > field, even if it was not defined in the enum.
207
207
  "T.any(Symbol, Integer)"
208
208
  when :message
209
- descriptor.subtype.msgclass.name
209
+ descriptor.subtype.msgclass.name || "T.untyped"
210
210
  when :int32, :int64, :uint32, :uint64
211
211
  "Integer"
212
212
  when :double, :float
@@ -225,14 +225,24 @@ module Tapioca
225
225
  descriptor.label == :optional && descriptor.type == :message
226
226
  end
227
227
 
228
+ sig { params(descriptor: Google::Protobuf::FieldDescriptor).returns(T::Boolean) }
229
+ def map_type?(descriptor)
230
+ # Defensively make sure that we are dealing with a repeated field
231
+ return false unless descriptor.label == :repeated
232
+
233
+ # Try to create a new instance with the field that maps to the descriptor name
234
+ # being assinged a hash value. If this goes through, then it's a map type.
235
+ constant.new(**{ descriptor.name => {} })
236
+ true
237
+ rescue ArgumentError
238
+ # This means the descriptor is not a map type
239
+ false
240
+ end
241
+
228
242
  sig { params(descriptor: Google::Protobuf::FieldDescriptor).returns(Field) }
229
243
  def field_of(descriptor)
230
244
  if descriptor.label == :repeated
231
- # Here we're going to check if the submsg_name is named according to
232
- # how Google names map entries.
233
- # https://github.com/protocolbuffers/protobuf/blob/f82e26/ruby/ext/google/protobuf_c/defs.c#L1963-L1966
234
- if descriptor.submsg_name.to_s.end_with?("_MapEntry_#{descriptor.name}") ||
235
- descriptor.submsg_name.to_s.end_with?("FieldsEntry")
245
+ if map_type?(descriptor)
236
246
  key = descriptor.subtype.lookup("key")
237
247
  value = descriptor.subtype.lookup("value")
238
248
 
@@ -20,7 +20,7 @@ module Tapioca
20
20
 
21
21
  compile_method(node, symbol, constant, initialize_method_for(constant))
22
22
  compile_directly_owned_methods(node, symbol, constant)
23
- compile_directly_owned_methods(node, symbol, singleton_class_of(constant))
23
+ compile_directly_owned_methods(node, symbol, singleton_class_of(constant), attached_class: constant)
24
24
  end
25
25
 
26
26
  sig do
@@ -29,14 +29,22 @@ module Tapioca
29
29
  module_name: String,
30
30
  mod: Module,
31
31
  for_visibility: T::Array[Symbol],
32
+ attached_class: T.nilable(Module),
32
33
  ).void
33
34
  end
34
- def compile_directly_owned_methods(tree, module_name, mod, for_visibility = [:public, :protected, :private])
35
+ def compile_directly_owned_methods(
36
+ tree,
37
+ module_name,
38
+ mod,
39
+ for_visibility = [:public, :protected, :private],
40
+ attached_class: nil
41
+ )
35
42
  method_names_by_visibility(mod)
36
43
  .delete_if { |visibility, _method_list| !for_visibility.include?(visibility) }
37
44
  .each do |visibility, method_list|
38
45
  method_list.sort!.map do |name|
39
46
  next if name == :initialize
47
+ next if method_new_in_abstract_class?(attached_class, name)
40
48
 
41
49
  vis = case visibility
42
50
  when :protected
@@ -180,6 +188,19 @@ module Tapioca
180
188
  .include?(method_name.gsub(/=$/, "").to_sym)
181
189
  end
182
190
 
191
+ sig do
192
+ params(
193
+ attached_class: T.nilable(Module),
194
+ method_name: Symbol,
195
+ ).returns(T.nilable(T::Boolean))
196
+ end
197
+ def method_new_in_abstract_class?(attached_class, method_name)
198
+ attached_class &&
199
+ method_name == :new &&
200
+ !!abstract_type_of(attached_class) &&
201
+ Class === attached_class.singleton_class
202
+ end
203
+
183
204
  sig { params(constant: Module).returns(T.nilable(UnboundMethod)) }
184
205
  def initialize_method_for(constant)
185
206
  constant.instance_method(:initialize)
@@ -16,12 +16,11 @@ module Tapioca
16
16
  constant = event.constant
17
17
  node = event.node
18
18
 
19
- abstract_type = T::Private::Abstract::Data.get(constant, :abstract_type) ||
20
- T::Private::Abstract::Data.get(singleton_class_of(constant), :abstract_type)
19
+ abstract_type = abstract_type_of(constant)
21
20
 
22
21
  node << RBI::Helper.new(abstract_type.to_s) if abstract_type
23
- node << RBI::Helper.new("final") if T::Private::Final.final_module?(constant)
24
- node << RBI::Helper.new("sealed") if T::Private::Sealed.sealed_module?(constant)
22
+ node << RBI::Helper.new("final") if final_module?(constant)
23
+ node << RBI::Helper.new("sealed") if sealed_module?(constant)
25
24
  end
26
25
 
27
26
  sig { override.params(event: NodeAdded).returns(T::Boolean) }
@@ -31,14 +31,14 @@ module Tapioca
31
31
 
32
32
  # Map each type variable to its string representation.
33
33
  #
34
- # Each entry of `type_variables` maps a Module to a String,
35
- # and the order they are inserted into the hash is the order they should be
36
- # defined in the source code.
37
- type_variable_declarations = type_variables.map do |type_variable|
38
- type_variable_name = type_variable.name
39
- next unless type_variable_name
34
+ # Each entry of `type_variables` maps a Module to a String, or
35
+ # is a `has_attached_class!` declaration, and the order they are inserted
36
+ # into the hash is the order they should be defined in the source code.
37
+ type_variable_declarations = type_variables.filter_map do |type_variable|
38
+ node = node_from_type_variable(type_variable)
39
+ next unless node
40
40
 
41
- tree << RBI::TypeMember.new(type_variable_name, type_variable.serialize)
41
+ tree << node
42
42
  end
43
43
 
44
44
  return if type_variable_declarations.empty?
@@ -46,6 +46,19 @@ module Tapioca
46
46
  tree << RBI::Extend.new("T::Generic")
47
47
  end
48
48
 
49
+ sig { params(type_variable: Tapioca::TypeVariableModule).returns(T.nilable(RBI::Node)) }
50
+ def node_from_type_variable(type_variable)
51
+ case type_variable.type
52
+ when Tapioca::TypeVariableModule::Type::HasAttachedClass
53
+ RBI::Send.new(type_variable.serialize)
54
+ else
55
+ type_variable_name = type_variable.name
56
+ return unless type_variable_name
57
+
58
+ RBI::TypeMember.new(type_variable_name, type_variable.serialize)
59
+ end
60
+ end
61
+
49
62
  sig { override.params(event: NodeAdded).returns(T::Boolean) }
50
63
  def ignore?(event)
51
64
  event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
@@ -304,9 +304,9 @@ module Tapioca
304
304
  @root << scope
305
305
  end
306
306
 
307
- sig { params(constant: Class).returns(T.nilable(String)) }
307
+ sig { params(constant: T::Class[T.anything]).returns(T.nilable(String)) }
308
308
  def compile_superclass(constant)
309
- superclass = T.let(nil, T.nilable(Class)) # rubocop:disable Lint/UselessAssignment
309
+ superclass = T.let(nil, T.nilable(T::Class[T.anything])) # rubocop:disable Lint/UselessAssignment
310
310
 
311
311
  while (superclass = superclass_of(constant))
312
312
  constant_name = name_of(constant)
@@ -1,6 +1,8 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "tapioca/bundler_ext/auto_require_hook"
5
+
4
6
  module Tapioca
5
7
  class Gemfile
6
8
  extend(T::Sig)
@@ -12,50 +14,6 @@ module Tapioca
12
14
  )
13
15
  end
14
16
 
15
- # This is a module that gets prepended to `Bundler::Dependency` and
16
- # makes sure even gems marked as `require: false` are required during
17
- # `Bundler.require`.
18
- module AutoRequireHook
19
- extend T::Sig
20
- extend T::Helpers
21
-
22
- requires_ancestor { ::Bundler::Dependency }
23
-
24
- @exclude = T.let([], T::Array[String])
25
-
26
- class << self
27
- extend T::Sig
28
-
29
- sig { params(exclude: T::Array[String]).returns(T::Array[String]) }
30
- attr_writer :exclude
31
-
32
- sig { params(name: T.untyped).returns(T::Boolean) }
33
- def excluded?(name)
34
- @exclude.include?(name)
35
- end
36
- end
37
-
38
- sig { returns(T.untyped).checked(:never) }
39
- def autorequire
40
- value = super
41
-
42
- # If the gem is excluded, we don't want to force require it, in case
43
- # it has side-effects users don't want. For example, `fakefs` gem, if
44
- # loaded, takes over filesystem operations.
45
- return value if AutoRequireHook.excluded?(name)
46
-
47
- # If a gem is marked as `require: false`, then its `autorequire`
48
- # value will be `[]`. But, we want those gems to be loaded for our
49
- # purposes as well, so we return `nil` in those cases, instead, which
50
- # means `require: true`.
51
- return nil if value == []
52
-
53
- value
54
- end
55
-
56
- ::Bundler::Dependency.prepend(self)
57
- end
58
-
59
17
  sig { returns(Bundler::Definition) }
60
18
  attr_reader(:definition)
61
19
 
@@ -65,13 +23,15 @@ module Tapioca
65
23
  sig { returns(T::Array[String]) }
66
24
  attr_reader(:missing_specs)
67
25
 
68
- sig { params(exclude: T::Array[String]).void }
69
- def initialize(exclude)
70
- AutoRequireHook.exclude = exclude
26
+ sig { params(excluded_gems: T::Array[String]).void }
27
+ def initialize(excluded_gems)
71
28
  @gemfile = T.let(File.new(Bundler.default_gemfile), File)
72
29
  @lockfile = T.let(File.new(Bundler.default_lockfile), File)
73
30
  @definition = T.let(Bundler::Dsl.evaluate(gemfile, lockfile, {}), Bundler::Definition)
31
+ @excluded_gems = excluded_gems
32
+
74
33
  dependencies, missing_specs = load_dependencies
34
+
75
35
  @dependencies = T.let(dependencies, T::Array[GemSpec])
76
36
  @missing_specs = T.let(missing_specs, T::Array[String])
77
37
  end
@@ -83,7 +43,9 @@ module Tapioca
83
43
 
84
44
  sig { void }
85
45
  def require_bundle
86
- T.unsafe(runtime).require(*groups)
46
+ BundlerExt::AutoRequireHook.override_require_false(exclude: @excluded_gems) do
47
+ T.unsafe(runtime).require(*groups)
48
+ end
87
49
  end
88
50
 
89
51
  private
@@ -80,7 +80,7 @@ module Tapioca
80
80
  dsl_dir: String,
81
81
  auto_strictness: T::Boolean,
82
82
  gems: T::Array[Gemfile::GemSpec],
83
- compilers: T::Enumerable[Class],
83
+ compilers: T::Enumerable[T.class_of(Dsl::Compiler)],
84
84
  ).void
85
85
  end
86
86
  def validate_rbi_files(command:, gem_dir:, dsl_dir:, auto_strictness:, gems: [], compilers: [])
@@ -25,6 +25,7 @@ module Tapioca
25
25
  {
26
26
  # feature_name: ::Gem::Requirement.new(">= ___"), # https://github.com/sorbet/sorbet/pull/___
27
27
  non_generic_weak_map: ::Gem::Requirement.new(">= 0.5.10587"), # https://github.com/sorbet/sorbet/pull/6610
28
+ generic_class: ::Gem::Requirement.new(">= 0.5.10820"), # https://github.com/sorbet/sorbet/pull/6781
28
29
  }.freeze,
29
30
  T::Hash[Symbol, ::Gem::Requirement],
30
31
  )
@@ -30,6 +30,7 @@ require "tapioca/helpers/gem_helper"
30
30
 
31
31
  require "tapioca/helpers/sorbet_helper"
32
32
  require "tapioca/helpers/rbi_helper"
33
+ require "tapioca/sorbet_ext/backcompat_patches"
33
34
  require "tapioca/sorbet_ext/fixed_hash_patch"
34
35
  require "tapioca/sorbet_ext/name_patch"
35
36
  require "tapioca/sorbet_ext/generic_name_patch"
@@ -9,9 +9,16 @@ module Tapioca
9
9
  class << self
10
10
  extend T::Sig
11
11
 
12
- sig { params(tapioca_path: String, eager_load: T::Boolean, app_root: String).void }
13
- def load_application(tapioca_path:, eager_load: true, app_root: ".")
14
- loader = new(tapioca_path: tapioca_path, eager_load: eager_load, app_root: app_root)
12
+ sig do
13
+ params(tapioca_path: String, eager_load: T::Boolean, app_root: String, halt_upon_load_error: T::Boolean).void
14
+ end
15
+ def load_application(tapioca_path:, eager_load: true, app_root: ".", halt_upon_load_error: true)
16
+ loader = new(
17
+ tapioca_path: tapioca_path,
18
+ eager_load: eager_load,
19
+ app_root: app_root,
20
+ halt_upon_load_error: halt_upon_load_error,
21
+ )
15
22
  loader.load
16
23
  end
17
24
  end
@@ -25,13 +32,16 @@ module Tapioca
25
32
 
26
33
  protected
27
34
 
28
- sig { params(tapioca_path: String, eager_load: T::Boolean, app_root: String).void }
29
- def initialize(tapioca_path:, eager_load: true, app_root: ".")
35
+ sig do
36
+ params(tapioca_path: String, eager_load: T::Boolean, app_root: String, halt_upon_load_error: T::Boolean).void
37
+ end
38
+ def initialize(tapioca_path:, eager_load: true, app_root: ".", halt_upon_load_error: true)
30
39
  super()
31
40
 
32
41
  @tapioca_path = tapioca_path
33
42
  @eager_load = eager_load
34
43
  @app_root = app_root
44
+ @halt_upon_load_error = halt_upon_load_error
35
45
  end
36
46
 
37
47
  sig { void }
@@ -65,6 +75,7 @@ module Tapioca
65
75
  environment_load: true,
66
76
  eager_load: @eager_load,
67
77
  app_root: @app_root,
78
+ halt_upon_load_error: @halt_upon_load_error,
68
79
  )
69
80
 
70
81
  say("Done", :green)
@@ -15,14 +15,16 @@ module Tapioca
15
15
  prerequire: T.nilable(String),
16
16
  postrequire: String,
17
17
  default_command: String,
18
+ halt_upon_load_error: T::Boolean,
18
19
  ).void
19
20
  end
20
- def load_application(bundle:, prerequire:, postrequire:, default_command:)
21
+ def load_application(bundle:, prerequire:, postrequire:, default_command:, halt_upon_load_error:)
21
22
  loader = new(
22
23
  bundle: bundle,
23
24
  prerequire: prerequire,
24
25
  postrequire: postrequire,
25
26
  default_command: default_command,
27
+ halt_upon_load_error: halt_upon_load_error,
26
28
  )
27
29
  loader.load
28
30
  end
@@ -41,22 +43,24 @@ module Tapioca
41
43
  prerequire: T.nilable(String),
42
44
  postrequire: String,
43
45
  default_command: String,
46
+ halt_upon_load_error: T::Boolean,
44
47
  ).void
45
48
  end
46
- def initialize(bundle:, prerequire:, postrequire:, default_command:)
49
+ def initialize(bundle:, prerequire:, postrequire:, default_command:, halt_upon_load_error:)
47
50
  super()
48
51
 
49
52
  @bundle = bundle
50
53
  @prerequire = prerequire
51
54
  @postrequire = postrequire
52
55
  @default_command = default_command
56
+ @halt_upon_load_error = halt_upon_load_error
53
57
  end
54
58
 
55
59
  sig { void }
56
60
  def require_gem_file
57
61
  say("Requiring all gems to prepare for compiling... ")
58
62
  begin
59
- load_bundle(@bundle, @prerequire, @postrequire)
63
+ load_bundle(@bundle, @prerequire, @postrequire, @halt_upon_load_error)
60
64
  rescue LoadError => e
61
65
  explain_failed_require(@postrequire, e)
62
66
  exit(1)
@@ -19,12 +19,17 @@ module Tapioca
19
19
  private
20
20
 
21
21
  sig do
22
- params(gemfile: Tapioca::Gemfile, initialize_file: T.nilable(String), require_file: T.nilable(String)).void
22
+ params(
23
+ gemfile: Tapioca::Gemfile,
24
+ initialize_file: T.nilable(String),
25
+ require_file: T.nilable(String),
26
+ halt_upon_load_error: T::Boolean,
27
+ ).void
23
28
  end
24
- def load_bundle(gemfile, initialize_file, require_file)
29
+ def load_bundle(gemfile, initialize_file, require_file, halt_upon_load_error)
25
30
  require_helper(initialize_file)
26
31
 
27
- load_rails_application
32
+ load_rails_application(halt_upon_load_error: halt_upon_load_error)
28
33
 
29
34
  gemfile.require_bundle
30
35
 
@@ -33,8 +38,15 @@ module Tapioca
33
38
  load_rails_engines
34
39
  end
35
40
 
36
- sig { params(environment_load: T::Boolean, eager_load: T::Boolean, app_root: String).void }
37
- def load_rails_application(environment_load: false, eager_load: false, app_root: ".")
41
+ sig do
42
+ params(
43
+ environment_load: T::Boolean,
44
+ eager_load: T::Boolean,
45
+ app_root: String,
46
+ halt_upon_load_error: T::Boolean,
47
+ ).void
48
+ end
49
+ def load_rails_application(environment_load: false, eager_load: false, app_root: ".", halt_upon_load_error: true)
38
50
  return unless File.exist?("#{app_root}/config/application.rb")
39
51
 
40
52
  silence_deprecations
@@ -50,9 +62,13 @@ module Tapioca
50
62
  say(
51
63
  "\nTapioca attempted to load the Rails application after encountering a `config/application.rb` file, " \
52
64
  "but it failed. If your application uses Rails please ensure it can be loaded correctly before " \
53
- "generating RBIs.\n#{e}",
65
+ "generating RBIs. If your application does not use Rails and you wish to continue RBI generation " \
66
+ "please pass `--no-halt-upon-load-error` to the tapioca command in sorbet/tapioca/config.yml or in CLI." \
67
+ "\n#{e}",
54
68
  :yellow,
55
69
  )
70
+ raise e if halt_upon_load_error
71
+
56
72
  if e.backtrace
57
73
  backtrace = T.must(e.backtrace).join("\n")
58
74
  say(backtrace, :cyan) # TODO: Check verbose flag to print backtrace.
@@ -151,7 +151,7 @@ module Tapioca
151
151
  generic_type
152
152
  end
153
153
 
154
- sig { params(constant: Class).returns(Class) }
154
+ sig { params(constant: T::Class[T.anything]).returns(T::Class[T.anything]) }
155
155
  def create_safe_subclass(constant)
156
156
  # Lookup the "inherited" class method
157
157
  inherited_method = constant.method(:inherited)
@@ -52,7 +52,7 @@ module Tapioca
52
52
  UNDEFINED_CONSTANT
53
53
  end
54
54
 
55
- sig { params(object: BasicObject).returns(Class).checked(:never) }
55
+ sig { params(object: BasicObject).returns(T::Class[T.anything]).checked(:never) }
56
56
  def class_of(object)
57
57
  CLASS_METHOD.bind_call(object)
58
58
  end
@@ -68,7 +68,7 @@ module Tapioca
68
68
  name&.start_with?("#<") ? nil : name
69
69
  end
70
70
 
71
- sig { params(constant: Module).returns(Class) }
71
+ sig { params(constant: Module).returns(T::Class[T.anything]) }
72
72
  def singleton_class_of(constant)
73
73
  SINGLETON_CLASS_METHOD.bind_call(constant)
74
74
  end
@@ -78,7 +78,7 @@ module Tapioca
78
78
  ANCESTORS_METHOD.bind_call(constant)
79
79
  end
80
80
 
81
- sig { params(constant: Class).returns(T.nilable(Class)) }
81
+ sig { params(constant: T::Class[T.anything]).returns(T.nilable(T::Class[T.anything])) }
82
82
  def superclass_of(constant)
83
83
  SUPERCLASS_METHOD.bind_call(constant)
84
84
  end
@@ -113,7 +113,7 @@ module Tapioca
113
113
  if Class === constant
114
114
  ancestors_of(superclass_of(constant) || Object)
115
115
  else
116
- Module.ancestors
116
+ Module.new.ancestors
117
117
  end
118
118
  end
119
119
 
@@ -161,7 +161,7 @@ module Tapioca
161
161
  # descendants_of(C) # => [B, A, D]
162
162
  sig do
163
163
  type_parameters(:U)
164
- .params(klass: T.all(Class, T.type_parameter(:U)))
164
+ .params(klass: T.all(T::Class[T.anything], T.type_parameter(:U)))
165
165
  .returns(T::Array[T.type_parameter(:U)])
166
166
  end
167
167
  def descendants_of(klass)
@@ -192,6 +192,22 @@ module Tapioca
192
192
  end.to_set
193
193
  end
194
194
 
195
+ sig { params(constant: Module).returns(T.untyped) }
196
+ def abstract_type_of(constant)
197
+ T::Private::Abstract::Data.get(constant, :abstract_type) ||
198
+ T::Private::Abstract::Data.get(singleton_class_of(constant), :abstract_type)
199
+ end
200
+
201
+ sig { params(constant: Module).returns(T::Boolean) }
202
+ def final_module?(constant)
203
+ T::Private::Final.final_module?(constant)
204
+ end
205
+
206
+ sig { params(constant: Module).returns(T::Boolean) }
207
+ def sealed_module?(constant)
208
+ T::Private::Sealed.sealed_module?(constant)
209
+ end
210
+
195
211
  private
196
212
 
197
213
  sig { params(constant: Module).returns(T::Array[UnboundMethod]) }
@@ -0,0 +1,24 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ unless defined?(T.anything)
5
+ module T
6
+ class << self
7
+ def anything
8
+ T.untyped
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ unless defined?(T::Class)
15
+ module T
16
+ module Class
17
+ class << self
18
+ def [](type)
19
+ T.untyped
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -49,6 +49,21 @@ module T
49
49
  Tapioca::Runtime::GenericTypeRegistry.register_type_variable(self, type_variable)
50
50
  end
51
51
  end
52
+
53
+ def has_attached_class!(variance = :invariant, &bounds_proc)
54
+ Tapioca::Runtime::GenericTypeRegistry.register_type_variable(
55
+ self,
56
+ Tapioca::TypeVariableModule.new(
57
+ T.cast(self, Module),
58
+ Tapioca::TypeVariableModule::Type::HasAttachedClass,
59
+ variance,
60
+ nil,
61
+ nil,
62
+ nil,
63
+ bounds_proc,
64
+ ),
65
+ )
66
+ end
52
67
  end
53
68
 
54
69
  prepend TypeStoragePatch
@@ -140,9 +155,13 @@ module Tapioca
140
155
  enums do
141
156
  Member = new("type_member")
142
157
  Template = new("type_template")
158
+ HasAttachedClass = new("has_attached_class!")
143
159
  end
144
160
  end
145
161
 
162
+ sig { returns(Type) }
163
+ attr_reader :type
164
+
146
165
  # rubocop:disable Metrics/ParameterLists
147
166
  sig do
148
167
  params(
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Tapioca
5
- VERSION = "0.11.6"
5
+ VERSION = "0.11.7"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tapioca
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.6
4
+ version: 0.11.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ufuk Kayserilioglu
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2023-05-12 00:00:00.000000000 Z
14
+ date: 2023-06-23 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -149,6 +149,7 @@ files:
149
149
  - README.md
150
150
  - exe/tapioca
151
151
  - lib/tapioca.rb
152
+ - lib/tapioca/bundler_ext/auto_require_hook.rb
152
153
  - lib/tapioca/cli.rb
153
154
  - lib/tapioca/commands.rb
154
155
  - lib/tapioca/commands/annotations.rb
@@ -253,6 +254,7 @@ files:
253
254
  - lib/tapioca/runtime/trackers/mixin.rb
254
255
  - lib/tapioca/runtime/trackers/required_ancestor.rb
255
256
  - lib/tapioca/runtime/trackers/tracker.rb
257
+ - lib/tapioca/sorbet_ext/backcompat_patches.rb
256
258
  - lib/tapioca/sorbet_ext/fixed_hash_patch.rb
257
259
  - lib/tapioca/sorbet_ext/generic_name_patch.rb
258
260
  - lib/tapioca/sorbet_ext/name_patch.rb
@@ -281,7 +283,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
281
283
  - !ruby/object:Gem::Version
282
284
  version: '0'
283
285
  requirements: []
284
- rubygems_version: 3.4.12
286
+ rubygems_version: 3.4.14
285
287
  signing_key:
286
288
  specification_version: 4
287
289
  summary: A Ruby Interface file generator for gems, core types and the Ruby standard