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.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +21 -0
  3. data/exe/tapioca +6 -1
  4. data/lib/ruby_lsp/tapioca/addon.rb +73 -43
  5. data/lib/ruby_lsp/tapioca/run_gem_rbi_check.rb +43 -43
  6. data/lib/ruby_lsp/tapioca/server_addon.rb +13 -10
  7. data/lib/tapioca/bundler_ext/auto_require_hook.rb +6 -14
  8. data/lib/tapioca/cli.rb +16 -8
  9. data/lib/tapioca/commands/abstract_dsl.rb +39 -66
  10. data/lib/tapioca/commands/abstract_gem.rb +25 -46
  11. data/lib/tapioca/commands/annotations.rb +28 -34
  12. data/lib/tapioca/commands/check_shims.rb +6 -15
  13. data/lib/tapioca/commands/command.rb +12 -26
  14. data/lib/tapioca/commands/command_without_tracker.rb +2 -5
  15. data/lib/tapioca/commands/configure.rb +11 -16
  16. data/lib/tapioca/commands/dsl_compiler_list.rb +2 -1
  17. data/lib/tapioca/commands/dsl_generate.rb +2 -1
  18. data/lib/tapioca/commands/dsl_verify.rb +2 -1
  19. data/lib/tapioca/commands/gem_generate.rb +5 -9
  20. data/lib/tapioca/commands/gem_sync.rb +2 -1
  21. data/lib/tapioca/commands/gem_verify.rb +3 -2
  22. data/lib/tapioca/commands/require.rb +3 -7
  23. data/lib/tapioca/commands/todo.rb +6 -10
  24. data/lib/tapioca/dsl/compiler.rb +36 -63
  25. data/lib/tapioca/dsl/compilers/aasm.rb +33 -44
  26. data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +8 -7
  27. data/lib/tapioca/dsl/compilers/action_mailer.rb +6 -5
  28. data/lib/tapioca/dsl/compilers/action_text.rb +6 -5
  29. data/lib/tapioca/dsl/compilers/active_job.rb +6 -10
  30. data/lib/tapioca/dsl/compilers/active_model_attributes.rb +10 -11
  31. data/lib/tapioca/dsl/compilers/active_model_secure_password.rb +5 -6
  32. data/lib/tapioca/dsl/compilers/active_model_validations_confirmation.rb +5 -12
  33. data/lib/tapioca/dsl/compilers/active_record_associations.rb +17 -44
  34. data/lib/tapioca/dsl/compilers/active_record_columns.rb +20 -26
  35. data/lib/tapioca/dsl/compilers/active_record_delegated_types.rb +9 -8
  36. data/lib/tapioca/dsl/compilers/active_record_enum.rb +7 -6
  37. data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +54 -62
  38. data/lib/tapioca/dsl/compilers/active_record_relations.rb +148 -209
  39. data/lib/tapioca/dsl/compilers/active_record_scope.rb +8 -13
  40. data/lib/tapioca/dsl/compilers/active_record_secure_token.rb +5 -4
  41. data/lib/tapioca/dsl/compilers/active_record_store.rb +5 -4
  42. data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +19 -28
  43. data/lib/tapioca/dsl/compilers/active_resource.rb +19 -21
  44. data/lib/tapioca/dsl/compilers/active_storage.rb +6 -14
  45. data/lib/tapioca/dsl/compilers/active_support_concern.rb +9 -8
  46. data/lib/tapioca/dsl/compilers/active_support_current_attributes.rb +8 -7
  47. data/lib/tapioca/dsl/compilers/active_support_time_ext.rb +5 -4
  48. data/lib/tapioca/dsl/compilers/config.rb +5 -4
  49. data/lib/tapioca/dsl/compilers/frozen_record.rb +7 -11
  50. data/lib/tapioca/dsl/compilers/graphql_input_object.rb +9 -10
  51. data/lib/tapioca/dsl/compilers/graphql_mutation.rb +6 -10
  52. data/lib/tapioca/dsl/compilers/identity_cache.rb +11 -39
  53. data/lib/tapioca/dsl/compilers/json_api_client_resource.rb +9 -18
  54. data/lib/tapioca/dsl/compilers/kredis.rb +7 -8
  55. data/lib/tapioca/dsl/compilers/mixed_in_class_attributes.rb +5 -4
  56. data/lib/tapioca/dsl/compilers/protobuf.rb +13 -26
  57. data/lib/tapioca/dsl/compilers/rails_generators.rb +9 -11
  58. data/lib/tapioca/dsl/compilers/sidekiq_worker.rb +23 -13
  59. data/lib/tapioca/dsl/compilers/smart_properties.rb +32 -38
  60. data/lib/tapioca/dsl/compilers/state_machines.rb +15 -26
  61. data/lib/tapioca/dsl/compilers/url_helpers.rb +10 -9
  62. data/lib/tapioca/dsl/compilers.rb +4 -7
  63. data/lib/tapioca/dsl/helpers/active_model_type_helper.rb +13 -16
  64. data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +13 -28
  65. data/lib/tapioca/dsl/helpers/active_record_constants_helper.rb +19 -15
  66. data/lib/tapioca/dsl/helpers/graphql_type_helper.rb +5 -24
  67. data/lib/tapioca/dsl/pipeline.rb +30 -58
  68. data/lib/tapioca/executor.rb +6 -12
  69. data/lib/tapioca/gem/events.rb +24 -34
  70. data/lib/tapioca/gem/listeners/base.rb +7 -10
  71. data/lib/tapioca/gem/listeners/dynamic_mixins.rb +4 -2
  72. data/lib/tapioca/gem/listeners/foreign_constants.rb +5 -7
  73. data/lib/tapioca/gem/listeners/methods.rb +36 -47
  74. data/lib/tapioca/gem/listeners/mixins.rb +6 -18
  75. data/lib/tapioca/gem/listeners/remove_empty_payload_scopes.rb +4 -2
  76. data/lib/tapioca/gem/listeners/sorbet_enums.rb +4 -2
  77. data/lib/tapioca/gem/listeners/sorbet_helpers.rb +4 -2
  78. data/lib/tapioca/gem/listeners/sorbet_props.rb +4 -2
  79. data/lib/tapioca/gem/listeners/sorbet_required_ancestors.rb +4 -2
  80. data/lib/tapioca/gem/listeners/sorbet_signatures.rb +7 -5
  81. data/lib/tapioca/gem/listeners/sorbet_type_variables.rb +6 -4
  82. data/lib/tapioca/gem/listeners/source_location.rb +15 -8
  83. data/lib/tapioca/gem/listeners/subconstants.rb +5 -4
  84. data/lib/tapioca/gem/listeners/yard_doc.rb +30 -23
  85. data/lib/tapioca/gem/pipeline.rb +107 -91
  86. data/lib/tapioca/gem_info.rb +1 -1
  87. data/lib/tapioca/gemfile.rb +64 -73
  88. data/lib/tapioca/helpers/cli_helper.rb +4 -7
  89. data/lib/tapioca/helpers/config_helper.rb +17 -29
  90. data/lib/tapioca/helpers/env_helper.rb +2 -5
  91. data/lib/tapioca/helpers/gem_helper.rb +5 -5
  92. data/lib/tapioca/helpers/git_attributes.rb +3 -3
  93. data/lib/tapioca/helpers/rbi_files_helper.rb +76 -73
  94. data/lib/tapioca/helpers/rbi_helper.rb +14 -22
  95. data/lib/tapioca/helpers/sorbet_helper.rb +9 -18
  96. data/lib/tapioca/helpers/source_uri.rb +15 -25
  97. data/lib/tapioca/helpers/test/content.rb +7 -10
  98. data/lib/tapioca/helpers/test/dsl_compiler.rb +20 -33
  99. data/lib/tapioca/helpers/test/isolation.rb +10 -14
  100. data/lib/tapioca/helpers/test/template.rb +6 -11
  101. data/lib/tapioca/internal.rb +18 -8
  102. data/lib/tapioca/loaders/dsl.rb +11 -19
  103. data/lib/tapioca/loaders/gem.rb +6 -21
  104. data/lib/tapioca/loaders/loader.rb +21 -39
  105. data/lib/tapioca/rbi_ext/model.rb +12 -37
  106. data/lib/tapioca/rbi_formatter.rb +10 -19
  107. data/lib/tapioca/rbs/rewriter.rb +55 -0
  108. data/lib/tapioca/repo_index.rb +7 -9
  109. data/lib/tapioca/runtime/attached_class_of_32.rb +1 -1
  110. data/lib/tapioca/runtime/attached_class_of_legacy.rb +2 -5
  111. data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +23 -23
  112. data/lib/tapioca/runtime/generic_type_registry.rb +13 -23
  113. data/lib/tapioca/runtime/reflection.rb +81 -60
  114. data/lib/tapioca/runtime/source_location.rb +44 -0
  115. data/lib/tapioca/runtime/trackers/autoload.rb +7 -9
  116. data/lib/tapioca/runtime/trackers/constant_definition.rb +18 -14
  117. data/lib/tapioca/runtime/trackers/method_definition.rb +65 -0
  118. data/lib/tapioca/runtime/trackers/mixin.rb +8 -11
  119. data/lib/tapioca/runtime/trackers/required_ancestor.rb +3 -3
  120. data/lib/tapioca/runtime/trackers/tracker.rb +3 -6
  121. data/lib/tapioca/runtime/trackers.rb +5 -8
  122. data/lib/tapioca/sorbet_ext/generic_name_patch.rb +9 -15
  123. data/lib/tapioca/sorbet_ext/name_patch.rb +2 -2
  124. data/lib/tapioca/sorbet_ext/proc_bind_patch.rb +1 -1
  125. data/lib/tapioca/static/requires_compiler.rb +6 -6
  126. data/lib/tapioca/static/symbol_loader.rb +14 -16
  127. data/lib/tapioca/static/symbol_table_parser.rb +8 -8
  128. data/lib/tapioca/version.rb +1 -1
  129. data/lib/tapioca.rb +22 -29
  130. metadata +27 -10
@@ -148,33 +148,30 @@ module Tapioca
148
148
  # end
149
149
  # end
150
150
  # ~~~
151
+ #: [ConstantType = singleton(::ActiveRecord::Base)]
151
152
  class ActiveRecordRelations < Compiler
152
153
  extend T::Sig
153
154
  include Helpers::ActiveRecordConstantsHelper
154
155
  include SorbetHelper
155
156
 
156
- ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
157
-
158
157
  # From ActiveRecord::ConnectionAdapter::Quoting#quote, minus nil
159
- ID_TYPES = T.let(
160
- [
161
- "String",
162
- "Symbol",
163
- "::ActiveSupport::Multibyte::Chars",
164
- "T::Boolean",
165
- "BigDecimal",
166
- "Numeric",
167
- "::ActiveRecord::Type::Binary::Data",
168
- "::ActiveRecord::Type::Time::Value",
169
- "Date",
170
- "Time",
171
- "::ActiveSupport::Duration",
172
- "T::Class[T.anything]",
173
- ].to_set.freeze,
174
- T::Set[String],
175
- )
176
-
177
- sig { override.void }
158
+ ID_TYPES = [
159
+ "String",
160
+ "Symbol",
161
+ "::ActiveSupport::Multibyte::Chars",
162
+ "T::Boolean",
163
+ "BigDecimal",
164
+ "Numeric",
165
+ "::ActiveRecord::Type::Binary::Data",
166
+ "::ActiveRecord::Type::Time::Value",
167
+ "Date",
168
+ "Time",
169
+ "::ActiveSupport::Duration",
170
+ "T::Class[T.anything]",
171
+ ].to_set.freeze #: Set[String]
172
+
173
+ # @override
174
+ #: -> void
178
175
  def decorate
179
176
  create_classes_and_includes
180
177
  create_common_methods
@@ -185,104 +182,97 @@ module Tapioca
185
182
  class << self
186
183
  extend T::Sig
187
184
 
188
- sig { override.returns(T::Enumerable[Module]) }
185
+ # @override
186
+ #: -> T::Enumerable[Module]
189
187
  def gather_constants
190
188
  ActiveRecord::Base.descendants.reject(&:abstract_class?)
191
189
  end
192
190
  end
193
191
 
194
- ASSOCIATION_METHODS = T.let(
195
- ::ActiveRecord::AssociationRelation.instance_methods -
196
- ::ActiveRecord::Relation.instance_methods,
197
- T::Array[Symbol],
198
- )
199
- COLLECTION_PROXY_METHODS = T.let(
200
- ::ActiveRecord::Associations::CollectionProxy.instance_methods -
201
- ::ActiveRecord::AssociationRelation.instance_methods,
202
- T::Array[Symbol],
203
- )
204
-
205
- QUERY_METHODS = T.let(
206
- begin
207
- # Grab all Query methods
208
- query_methods = ActiveRecord::QueryMethods.instance_methods(false)
209
- # Grab all Spawn methods
210
- query_methods |= ActiveRecord::SpawnMethods.instance_methods(false)
211
- # Remove the ones we know are private API
212
- query_methods -= [:all, :arel, :build_subquery, :construct_join_dependency, :extensions, :spawn]
213
- # Remove the methods that ...
214
- query_methods
215
- .grep_v(/_clause$/) # end with "_clause"
216
- .grep_v(/_values?$/) # end with "_value" or "_values"
217
- .grep_v(/=$/) # end with "=""
218
- .grep_v(/(?<!uniq)!$/) # end with "!" except for "uniq!"
219
- end,
220
- T::Array[Symbol],
221
- )
222
- WHERE_CHAIN_QUERY_METHODS = T.let(
223
- ActiveRecord::QueryMethods::WhereChain.instance_methods(false),
224
- T::Array[Symbol],
225
- )
226
- FINDER_METHODS = T.let(ActiveRecord::FinderMethods.instance_methods(false), T::Array[Symbol])
227
- SIGNED_FINDER_METHODS = T.let(
228
- defined?(ActiveRecord::SignedId) ? ActiveRecord::SignedId::ClassMethods.instance_methods(false) : [],
229
- T::Array[Symbol],
230
- )
231
- BATCHES_METHODS = T.let(ActiveRecord::Batches.instance_methods(false), T::Array[Symbol])
232
- CALCULATION_METHODS = T.let(ActiveRecord::Calculations.instance_methods(false), T::Array[Symbol])
233
- ENUMERABLE_QUERY_METHODS = T.let([:any?, :many?, :none?, :one?], T::Array[Symbol])
234
- FIND_OR_CREATE_METHODS = T.let(
235
- [:find_or_create_by, :find_or_create_by!, :find_or_initialize_by, :create_or_find_by, :create_or_find_by!],
236
- T::Array[Symbol],
237
- )
238
- BUILDER_METHODS = T.let([:new, :create, :create!, :build], T::Array[Symbol])
239
- TO_ARRAY_METHODS = T.let([:to_ary, :to_a], T::Array[Symbol])
192
+ ASSOCIATION_METHODS = ::ActiveRecord::AssociationRelation.instance_methods -
193
+ ::ActiveRecord::Relation.instance_methods #: Array[Symbol]
194
+ COLLECTION_PROXY_METHODS = ::ActiveRecord::Associations::CollectionProxy.instance_methods -
195
+ ::ActiveRecord::AssociationRelation.instance_methods #: Array[Symbol]
196
+
197
+ QUERY_METHODS = begin
198
+ # Grab all Query methods
199
+ query_methods = ActiveRecord::QueryMethods.instance_methods(false)
200
+ # Grab all Spawn methods
201
+ query_methods |= ActiveRecord::SpawnMethods.instance_methods(false)
202
+ # Remove the ones we know are private API
203
+ query_methods -= [:all, :arel, :build_subquery, :construct_join_dependency, :extensions, :spawn]
204
+ # Remove the methods that ...
205
+ query_methods
206
+ .grep_v(/_clause$/) # end with "_clause"
207
+ .grep_v(/_values?$/) # end with "_value" or "_values"
208
+ .grep_v(/=$/) # end with "=""
209
+ .grep_v(/(?<!uniq)!$/) # end with "!" except for "uniq!"
210
+ end #: Array[Symbol]
211
+ WHERE_CHAIN_QUERY_METHODS = ActiveRecord::QueryMethods::WhereChain.instance_methods(false) #: Array[Symbol]
212
+ FINDER_METHODS = ActiveRecord::FinderMethods.instance_methods(false) #: Array[Symbol]
213
+ SIGNED_FINDER_METHODS = if defined?(ActiveRecord::SignedId)
214
+ ActiveRecord::SignedId::ClassMethods.instance_methods(false)
215
+ else
216
+ []
217
+ end #: Array[Symbol]
218
+ BATCHES_METHODS = ActiveRecord::Batches.instance_methods(false) #: Array[Symbol]
219
+ BATCHES_METHODS_PARAMETERS = {
220
+ start: ["T.untyped", "nil"],
221
+ finish: ["T.untyped", "nil"],
222
+ load: ["T.untyped", "false"],
223
+ batch_size: ["Integer", "1000"],
224
+ of: ["Integer", "1000"],
225
+ error_on_ignore: ["T.untyped", "nil"],
226
+ order: ["Symbol", ":asc"],
227
+ cursor: ["T.untyped", "primary_key"],
228
+ use_ranges: ["T.untyped", "nil"],
229
+ } #: Hash[Symbol, [String, String]]
230
+ CALCULATION_METHODS = ActiveRecord::Calculations.instance_methods(false) #: Array[Symbol]
231
+ ENUMERABLE_QUERY_METHODS = [:any?, :many?, :none?, :one?] #: Array[Symbol]
232
+ FIND_OR_CREATE_METHODS = [
233
+ :find_or_create_by,
234
+ :find_or_create_by!,
235
+ :find_or_initialize_by,
236
+ :create_or_find_by,
237
+ :create_or_find_by!,
238
+ ] #: Array[Symbol]
239
+ BUILDER_METHODS = [:new, :create, :create!, :build] #: Array[Symbol]
240
+ TO_ARRAY_METHODS = [:to_ary, :to_a] #: Array[Symbol]
240
241
 
241
242
  private
242
243
 
243
- sig { returns(RBI::Scope) }
244
+ #: -> RBI::Scope
244
245
  def model
245
- @model ||= T.let(
246
- root.create_path(constant),
247
- T.nilable(RBI::Scope),
248
- )
246
+ @model ||= root.create_path(constant) #: RBI::Scope?
249
247
  end
250
248
 
251
- sig { returns(RBI::Scope) }
249
+ #: -> RBI::Scope
252
250
  def relation_methods_module
253
- @relation_methods_module ||= T.let(
254
- model.create_module(RelationMethodsModuleName),
255
- T.nilable(RBI::Scope),
256
- )
251
+ @relation_methods_module ||= model.create_module(RelationMethodsModuleName) #: RBI::Scope?
257
252
  end
258
253
 
259
- sig { returns(RBI::Scope) }
254
+ #: -> RBI::Scope
260
255
  def association_relation_methods_module
261
- @association_relation_methods_module ||= T.let(
262
- model.create_module(AssociationRelationMethodsModuleName),
263
- T.nilable(RBI::Scope),
264
- )
256
+ @association_relation_methods_module ||=
257
+ model.create_module(AssociationRelationMethodsModuleName) #: RBI::Scope?
265
258
  end
266
259
 
267
- sig { returns(RBI::Scope) }
260
+ #: -> RBI::Scope
268
261
  def common_relation_methods_module
269
- @common_relation_methods_module ||= T.let(
270
- model.create_module(CommonRelationMethodsModuleName),
271
- T.nilable(RBI::Scope),
272
- )
262
+ @common_relation_methods_module ||= model.create_module(CommonRelationMethodsModuleName) #: RBI::Scope?
273
263
  end
274
264
 
275
- sig { returns(String) }
265
+ #: -> String
276
266
  def constant_name
277
- @constant_name ||= T.let(T.must(qualified_name_of(constant)), T.nilable(String))
267
+ @constant_name ||= T.must(qualified_name_of(constant)) #: String?
278
268
  end
279
269
 
280
- sig { params(method_name: Symbol).returns(T::Boolean) }
270
+ #: (Symbol method_name) -> bool
281
271
  def bang_method?(method_name)
282
272
  method_name.to_s.end_with?("!")
283
273
  end
284
274
 
285
- sig { void }
275
+ #: -> void
286
276
  def create_classes_and_includes
287
277
  model.create_extend(CommonRelationMethodsModuleName)
288
278
  # The model always extends the generated relation module
@@ -297,7 +287,7 @@ module Tapioca
297
287
  create_collection_proxy_class
298
288
  end
299
289
 
300
- sig { void }
290
+ #: -> void
301
291
  def create_relation_class
302
292
  superclass = "::ActiveRecord::Relation"
303
293
 
@@ -316,7 +306,7 @@ module Tapioca
316
306
  create_relation_where_chain_class
317
307
  end
318
308
 
319
- sig { void }
309
+ #: -> void
320
310
  def create_association_relation_class
321
311
  superclass = "::ActiveRecord::AssociationRelation"
322
312
 
@@ -335,7 +325,7 @@ module Tapioca
335
325
  create_association_relation_where_chain_class
336
326
  end
337
327
 
338
- sig { void }
328
+ #: -> void
339
329
  def create_relation_group_chain_class
340
330
  model.create_class(RelationGroupChainClassName, superclass_name: RelationClassName) do |klass|
341
331
  create_group_chain_methods(klass)
@@ -343,7 +333,7 @@ module Tapioca
343
333
  end
344
334
  end
345
335
 
346
- sig { void }
336
+ #: -> void
347
337
  def create_association_relation_group_chain_class
348
338
  model.create_class(
349
339
  AssociationRelationGroupChainClassName,
@@ -354,7 +344,7 @@ module Tapioca
354
344
  end
355
345
  end
356
346
 
357
- sig { params(klass: RBI::Scope).void }
347
+ #: (RBI::Scope klass) -> void
358
348
  def create_group_chain_methods(klass)
359
349
  # Calculation methods used with `group` return a hash where the keys cannot be typed
360
350
  # but the values can. Technically a `group` anywhere in the query chain produces
@@ -418,7 +408,7 @@ module Tapioca
418
408
  end
419
409
  end
420
410
 
421
- sig { void }
411
+ #: -> void
422
412
  def create_relation_where_chain_class
423
413
  model.create_class(RelationWhereChainClassName) do |klass|
424
414
  create_where_chain_methods(klass, RelationClassName)
@@ -426,7 +416,7 @@ module Tapioca
426
416
  end
427
417
  end
428
418
 
429
- sig { void }
419
+ #: -> void
430
420
  def create_association_relation_where_chain_class
431
421
  model.create_class(AssociationRelationWhereChainClassName) do |klass|
432
422
  create_where_chain_methods(klass, AssociationRelationClassName)
@@ -434,7 +424,7 @@ module Tapioca
434
424
  end
435
425
  end
436
426
 
437
- sig { params(klass: RBI::Scope, return_type: String).void }
427
+ #: (RBI::Scope klass, String return_type) -> void
438
428
  def create_where_chain_methods(klass, return_type)
439
429
  WHERE_CHAIN_QUERY_METHODS.each do |method_name|
440
430
  case method_name
@@ -459,7 +449,7 @@ module Tapioca
459
449
  end
460
450
  end
461
451
 
462
- sig { void }
452
+ #: -> void
463
453
  def create_collection_proxy_class
464
454
  superclass = "::ActiveRecord::Associations::CollectionProxy"
465
455
 
@@ -476,7 +466,7 @@ module Tapioca
476
466
  end
477
467
  end
478
468
 
479
- sig { params(klass: RBI::Scope).void }
469
+ #: (RBI::Scope klass) -> void
480
470
  def create_collection_proxy_methods(klass)
481
471
  # For these cases, it is valid to pass:
482
472
  # - a model instance, thus `Model`
@@ -555,7 +545,7 @@ module Tapioca
555
545
  end
556
546
  end
557
547
 
558
- sig { void }
548
+ #: -> void
559
549
  def create_relation_methods
560
550
  create_relation_method("all")
561
551
 
@@ -619,7 +609,7 @@ module Tapioca
619
609
  end
620
610
  end
621
611
 
622
- sig { void }
612
+ #: -> void
623
613
  def create_association_relation_methods
624
614
  returning_type = "T.nilable(T.any(T::Array[Symbol], FalseClass))"
625
615
  unique_by_type = "T.nilable(T.any(T::Array[Symbol], Symbol))"
@@ -664,7 +654,7 @@ module Tapioca
664
654
  end
665
655
  end
666
656
 
667
- sig { void }
657
+ #: -> void
668
658
  def create_common_methods
669
659
  create_common_method(
670
660
  "destroy_all",
@@ -846,7 +836,15 @@ module Tapioca
846
836
  end
847
837
  end
848
838
  when :ids
849
- create_common_method("ids", return_type: "Array")
839
+ if constant.table_exists?
840
+ primary_key_type = constant.type_for_attribute(constant.primary_key)
841
+ type = Tapioca::Dsl::Helpers::ActiveModelTypeHelper.type_for(primary_key_type)
842
+ type = RBIHelper.as_non_nilable_type(type)
843
+ create_common_method("ids", return_type: "T::Array[#{type}]")
844
+ else
845
+ create_common_method("ids", return_type: "Array")
846
+ end
847
+
850
848
  when :pick, :pluck
851
849
  create_common_method(
852
850
  method_name,
@@ -875,102 +873,31 @@ module Tapioca
875
873
  end
876
874
 
877
875
  BATCHES_METHODS.each do |method_name|
878
- case method_name
879
- when :find_each
880
- order = ActiveRecord::Batches.instance_method(:find_each).parameters.include?([:key, :order])
881
-
882
- common_relation_methods_module.create_method("find_each") do |method|
883
- method.add_kw_opt_param("start", "nil")
884
- method.add_kw_opt_param("finish", "nil")
885
- method.add_kw_opt_param("batch_size", "1000")
886
- method.add_kw_opt_param("error_on_ignore", "nil")
887
- method.add_kw_opt_param("order", ":asc") if order
888
- method.add_block_param("block")
876
+ block_param, return_type, parameters = batch_method_configs(method_name)
877
+ next if block_param.nil? || return_type.nil? || parameters.nil?
889
878
 
890
- method.add_sig do |sig|
891
- sig.add_param("start", "T.untyped")
892
- sig.add_param("finish", "T.untyped")
893
- sig.add_param("batch_size", "Integer")
894
- sig.add_param("error_on_ignore", "T.untyped")
895
- sig.add_param("order", "Symbol") if order
896
- sig.add_param("block", "T.proc.params(object: #{constant_name}).void")
897
- sig.return_type = "void"
898
- end
879
+ common_relation_methods_module.create_method(method_name.to_s) do |method|
880
+ parameters.each do |name, (style, _type, default)|
881
+ # The style is always "key", but this is a safeguard to prevent confusing errors in the future.
882
+ raise "Unexpected style #{style} for #{name}" unless style == :key
899
883
 
900
- method.add_sig do |sig|
901
- sig.add_param("start", "T.untyped")
902
- sig.add_param("finish", "T.untyped")
903
- sig.add_param("batch_size", "Integer")
904
- sig.add_param("error_on_ignore", "T.untyped")
905
- sig.add_param("order", "Symbol") if order
906
- sig.return_type = "T::Enumerator[#{constant_name}]"
907
- end
884
+ method.add_kw_opt_param(name, T.must(default))
908
885
  end
909
- when :find_in_batches
910
- order = ActiveRecord::Batches.instance_method(:find_in_batches).parameters.include?([:key, :order])
911
- common_relation_methods_module.create_method("find_in_batches") do |method|
912
- method.add_kw_opt_param("start", "nil")
913
- method.add_kw_opt_param("finish", "nil")
914
- method.add_kw_opt_param("batch_size", "1000")
915
- method.add_kw_opt_param("error_on_ignore", "nil")
916
- method.add_kw_opt_param("order", ":asc") if order
917
- method.add_block_param("block")
918
-
919
- method.add_sig do |sig|
920
- sig.add_param("start", "T.untyped")
921
- sig.add_param("finish", "T.untyped")
922
- sig.add_param("batch_size", "Integer")
923
- sig.add_param("error_on_ignore", "T.untyped")
924
- sig.add_param("order", "Symbol") if order
925
- sig.add_param("block", "T.proc.params(object: T::Array[#{constant_name}]).void")
926
- sig.return_type = "void"
927
- end
886
+ method.add_block_param("block")
928
887
 
929
- method.add_sig do |sig|
930
- sig.add_param("start", "T.untyped")
931
- sig.add_param("finish", "T.untyped")
932
- sig.add_param("batch_size", "Integer")
933
- sig.add_param("error_on_ignore", "T.untyped")
934
- sig.add_param("order", "Symbol") if order
935
- sig.return_type = "T::Enumerator[T::Enumerator[#{constant_name}]]"
888
+ method.add_sig do |sig|
889
+ parameters.each do |name, (_style, type, _default)|
890
+ sig.add_param(name, type)
936
891
  end
892
+ sig.add_param("block", "T.proc.params(object: #{block_param}).void")
893
+ sig.return_type = "void"
937
894
  end
938
- when :in_batches
939
- order = ActiveRecord::Batches.instance_method(:in_batches).parameters.include?([:key, :order])
940
- use_ranges = ActiveRecord::Batches.instance_method(:in_batches).parameters.include?([:key, :use_ranges])
941
-
942
- common_relation_methods_module.create_method("in_batches") do |method|
943
- method.add_kw_opt_param("of", "1000")
944
- method.add_kw_opt_param("start", "nil")
945
- method.add_kw_opt_param("finish", "nil")
946
- method.add_kw_opt_param("load", "false")
947
- method.add_kw_opt_param("error_on_ignore", "nil")
948
- method.add_kw_opt_param("order", ":asc") if order
949
- method.add_kw_opt_param("use_ranges", "nil") if use_ranges
950
- method.add_block_param("block")
951
895
 
952
- method.add_sig do |sig|
953
- sig.add_param("of", "Integer")
954
- sig.add_param("start", "T.untyped")
955
- sig.add_param("finish", "T.untyped")
956
- sig.add_param("load", "T.untyped")
957
- sig.add_param("error_on_ignore", "T.untyped")
958
- sig.add_param("order", "Symbol") if order
959
- sig.add_param("use_ranges", "T.untyped") if use_ranges
960
- sig.add_param("block", "T.proc.params(object: #{RelationClassName}).void")
961
- sig.return_type = "void"
962
- end
963
-
964
- method.add_sig do |sig|
965
- sig.add_param("of", "Integer")
966
- sig.add_param("start", "T.untyped")
967
- sig.add_param("finish", "T.untyped")
968
- sig.add_param("load", "T.untyped")
969
- sig.add_param("error_on_ignore", "T.untyped")
970
- sig.add_param("order", "Symbol") if order
971
- sig.add_param("use_ranges", "T.untyped") if use_ranges
972
- sig.return_type = "::ActiveRecord::Batches::BatchEnumerator"
896
+ method.add_sig do |sig|
897
+ parameters.each do |name, (_style, type, _default)|
898
+ sig.add_param(name, type)
973
899
  end
900
+ sig.return_type = return_type
974
901
  end
975
902
  end
976
903
  end
@@ -1049,13 +976,32 @@ module Tapioca
1049
976
  end
1050
977
  end
1051
978
 
1052
- sig do
1053
- params(
1054
- name: T.any(Symbol, String),
1055
- parameters: T::Array[RBI::TypedParam],
1056
- return_type: T.nilable(String),
1057
- ).void
979
+ #: (Symbol) -> [String, String, Hash[String, [Symbol, String, String?]]]?
980
+ def batch_method_configs(method_name)
981
+ block_param, return_type = case method_name
982
+ when :find_each
983
+ [constant_name, "T::Enumerator[#{constant_name}]"]
984
+ when :find_in_batches
985
+ ["T::Array[#{constant_name}]", "T::Enumerator[T::Enumerator[#{constant_name}]]"]
986
+ when :in_batches
987
+ [RelationClassName, "::ActiveRecord::Batches::BatchEnumerator"]
988
+ else
989
+ return
990
+ end
991
+
992
+ parameters = {}
993
+
994
+ ActiveRecord::Batches.instance_method(method_name).parameters.each do |style, name|
995
+ type, default = BATCHES_METHODS_PARAMETERS[name]
996
+ next if type.nil?
997
+
998
+ parameters[name.to_s] = [style, type, default]
999
+ end
1000
+
1001
+ [block_param, return_type, parameters]
1058
1002
  end
1003
+
1004
+ #: ((Symbol | String) name, ?parameters: Array[RBI::TypedParam], ?return_type: String?) -> void
1059
1005
  def create_common_method(name, parameters: [], return_type: nil)
1060
1006
  common_relation_methods_module.create_method(
1061
1007
  name.to_s,
@@ -1064,7 +1010,7 @@ module Tapioca
1064
1010
  )
1065
1011
  end
1066
1012
 
1067
- sig { void }
1013
+ #: -> void
1068
1014
  def create_where_relation_method
1069
1015
  relation_methods_module.create_method("where") do |method|
1070
1016
  method.add_rest_param("args")
@@ -1093,14 +1039,7 @@ module Tapioca
1093
1039
  end
1094
1040
  end
1095
1041
 
1096
- sig do
1097
- params(
1098
- name: T.any(Symbol, String),
1099
- parameters: T::Array[RBI::TypedParam],
1100
- relation_return_type: String,
1101
- association_return_type: String,
1102
- ).void
1103
- end
1042
+ #: ((Symbol | String) name, ?parameters: Array[RBI::TypedParam], ?relation_return_type: String, ?association_return_type: String) -> void
1104
1043
  def create_relation_method(
1105
1044
  name,
1106
1045
  parameters: [],
@@ -38,13 +38,13 @@ module Tapioca
38
38
  # end
39
39
  # end
40
40
  # ~~~
41
+ #: [ConstantType = singleton(::ActiveRecord::Base)]
41
42
  class ActiveRecordScope < Compiler
42
43
  extend T::Sig
43
44
  include Helpers::ActiveRecordConstantsHelper
44
45
 
45
- ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
46
-
47
- sig { override.void }
46
+ # @override
47
+ #: -> void
48
48
  def decorate
49
49
  method_names = scope_method_names
50
50
 
@@ -77,7 +77,8 @@ module Tapioca
77
77
  end
78
78
 
79
79
  class << self
80
- sig { override.returns(T::Enumerable[Module]) }
80
+ # @override
81
+ #: -> T::Enumerable[Module]
81
82
  def gather_constants
82
83
  descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
83
84
  end
@@ -85,9 +86,9 @@ module Tapioca
85
86
 
86
87
  private
87
88
 
88
- sig { returns(T::Array[Symbol]) }
89
+ #: -> Array[Symbol]
89
90
  def scope_method_names
90
- scope_methods = T.let([], T::Array[Symbol])
91
+ scope_methods = [] #: Array[Symbol]
91
92
  constant = self.constant
92
93
 
93
94
  # Keep gathering scope methods until we hit "ActiveRecord::Base"
@@ -104,13 +105,7 @@ module Tapioca
104
105
  scope_methods.uniq
105
106
  end
106
107
 
107
- sig do
108
- params(
109
- mod: RBI::Scope,
110
- scope_method: String,
111
- return_type: String,
112
- ).void
113
- end
108
+ #: (RBI::Scope mod, String scope_method, String return_type) -> void
114
109
  def generate_scope_method(mod, scope_method, return_type)
115
110
  mod.create_method(
116
111
  scope_method,
@@ -32,13 +32,13 @@ module Tapioca
32
32
  # def regenerate_auth_token; end
33
33
  # end
34
34
  # ~~~
35
+ #: [ConstantType = (singleton(ActiveRecord::Base) & Extensions::ActiveRecord)]
35
36
  class ActiveRecordSecureToken < Compiler
36
37
  extend T::Sig
37
38
  include Helpers::ActiveRecordConstantsHelper
38
39
 
39
- ConstantType = type_member { { fixed: T.all(T.class_of(ActiveRecord::Base), Extensions::ActiveRecord) } }
40
-
41
- sig { override.void }
40
+ # @override
41
+ #: -> void
42
42
  def decorate
43
43
  return if constant.__tapioca_secure_tokens.nil?
44
44
 
@@ -59,7 +59,8 @@ module Tapioca
59
59
  class << self
60
60
  extend T::Sig
61
61
 
62
- sig { override.returns(T::Enumerable[Module]) }
62
+ # @override
63
+ #: -> T::Enumerable[Module]
63
64
  def gather_constants
64
65
  descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
65
66
  end
@@ -78,13 +78,13 @@ module Tapioca
78
78
  # end
79
79
  # end
80
80
  # ~~~
81
+ #: [ConstantType = (singleton(ActiveRecord::Base) & Extensions::ActiveRecord)]
81
82
  class ActiveRecordStore < Compiler
82
83
  extend T::Sig
83
84
  include Helpers::ActiveRecordConstantsHelper
84
85
 
85
- ConstantType = type_member { { fixed: T.all(T.class_of(ActiveRecord::Base), Extensions::ActiveRecord) } }
86
-
87
- sig { override.void }
86
+ # @override
87
+ #: -> void
88
88
  def decorate
89
89
  return if constant.__tapioca_stored_attributes.nil?
90
90
 
@@ -134,7 +134,8 @@ module Tapioca
134
134
  class << self
135
135
  extend T::Sig
136
136
 
137
- sig { override.returns(T::Enumerable[Module]) }
137
+ # @override
138
+ #: -> T::Enumerable[Module]
138
139
  def gather_constants
139
140
  descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
140
141
  end