tapioca 0.10.5 → 0.11.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.
@@ -164,16 +164,10 @@ module Tapioca
164
164
 
165
165
  sig { override.void }
166
166
  def decorate
167
- root.create_path(constant) do |model|
168
- relation_methods_module = model.create_module(RelationMethodsModuleName)
169
- association_relation_methods_module = model.create_module(AssociationRelationMethodsModuleName)
170
- common_relation_methods_module = model.create_module(CommonRelationMethodsModuleName)
171
-
172
- create_classes_and_includes(model)
173
- create_common_methods(common_relation_methods_module)
174
- create_relation_methods(relation_methods_module, association_relation_methods_module)
175
- create_association_relation_methods(association_relation_methods_module)
176
- end
167
+ create_classes_and_includes
168
+ create_common_methods
169
+ create_relation_methods
170
+ create_association_relation_methods
177
171
  end
178
172
 
179
173
  class << self
@@ -181,7 +175,7 @@ module Tapioca
181
175
 
182
176
  sig { override.returns(T::Enumerable[Module]) }
183
177
  def gather_constants
184
- ActiveRecord::Base.descendants.reject(&:abstract_class?)
178
+ descendants_of(ActiveRecord::Base).reject(&:abstract_class?)
185
179
  end
186
180
  end
187
181
 
@@ -224,6 +218,7 @@ module Tapioca
224
218
  defined?(ActiveRecord::SignedId) ? ActiveRecord::SignedId::ClassMethods.instance_methods(false) : [],
225
219
  T::Array[Symbol],
226
220
  )
221
+ BATCHES_METHODS = T.let(ActiveRecord::Batches.instance_methods(false), T::Array[Symbol])
227
222
  CALCULATION_METHODS = T.let(ActiveRecord::Calculations.instance_methods(false), T::Array[Symbol])
228
223
  ENUMERABLE_QUERY_METHODS = T.let([:any?, :many?, :none?, :one?], T::Array[Symbol])
229
224
  FIND_OR_CREATE_METHODS = T.let(
@@ -234,6 +229,38 @@ module Tapioca
234
229
 
235
230
  private
236
231
 
232
+ sig { returns(RBI::Scope) }
233
+ def model
234
+ @model ||= T.let(
235
+ root.create_path(constant),
236
+ T.nilable(RBI::Scope),
237
+ )
238
+ end
239
+
240
+ sig { returns(RBI::Scope) }
241
+ def relation_methods_module
242
+ @relation_methods_module ||= T.let(
243
+ model.create_module(RelationMethodsModuleName),
244
+ T.nilable(RBI::Scope),
245
+ )
246
+ end
247
+
248
+ sig { returns(RBI::Scope) }
249
+ def association_relation_methods_module
250
+ @association_relation_methods_module ||= T.let(
251
+ model.create_module(AssociationRelationMethodsModuleName),
252
+ T.nilable(RBI::Scope),
253
+ )
254
+ end
255
+
256
+ sig { returns(RBI::Scope) }
257
+ def common_relation_methods_module
258
+ @common_relation_methods_module ||= T.let(
259
+ model.create_module(CommonRelationMethodsModuleName),
260
+ T.nilable(RBI::Scope),
261
+ )
262
+ end
263
+
237
264
  sig { returns(String) }
238
265
  def constant_name
239
266
  @constant_name ||= T.let(T.must(qualified_name_of(constant)), T.nilable(String))
@@ -244,8 +271,8 @@ module Tapioca
244
271
  method_name.to_s.end_with?("!")
245
272
  end
246
273
 
247
- sig { params(model: RBI::Scope).void }
248
- def create_classes_and_includes(model)
274
+ sig { void }
275
+ def create_classes_and_includes
249
276
  model.create_extend(CommonRelationMethodsModuleName)
250
277
  # The model always extends the generated relation module
251
278
  model.create_extend(RelationMethodsModuleName)
@@ -254,13 +281,13 @@ module Tapioca
254
281
  # See https://github.com/sorbet/sorbet/pull/4706 for details
255
282
  model.create_method("to_ary", return_type: "NilClass", visibility: RBI::Private.new)
256
283
 
257
- create_relation_class(model)
258
- create_association_relation_class(model)
259
- create_collection_proxy_class(model)
284
+ create_relation_class
285
+ create_association_relation_class
286
+ create_collection_proxy_class
260
287
  end
261
288
 
262
- sig { params(model: RBI::Scope).void }
263
- def create_relation_class(model)
289
+ sig { void }
290
+ def create_relation_class
264
291
  superclass = "::ActiveRecord::Relation"
265
292
 
266
293
  # The relation subclass includes the generated relation module
@@ -272,11 +299,11 @@ module Tapioca
272
299
  klass.create_method("to_ary", return_type: "T::Array[#{constant_name}]")
273
300
  end
274
301
 
275
- create_relation_where_chain_class(model)
302
+ create_relation_where_chain_class
276
303
  end
277
304
 
278
- sig { params(model: RBI::Scope).void }
279
- def create_association_relation_class(model)
305
+ sig { void }
306
+ def create_association_relation_class
280
307
  superclass = "::ActiveRecord::AssociationRelation"
281
308
 
282
309
  # Association subclasses include the generated association relation module
@@ -288,19 +315,19 @@ module Tapioca
288
315
  klass.create_method("to_ary", return_type: "T::Array[#{constant_name}]")
289
316
  end
290
317
 
291
- create_association_relation_where_chain_class(model)
318
+ create_association_relation_where_chain_class
292
319
  end
293
320
 
294
- sig { params(model: RBI::Scope).void }
295
- def create_relation_where_chain_class(model)
321
+ sig { void }
322
+ def create_relation_where_chain_class
296
323
  model.create_class(RelationWhereChainClassName, superclass_name: RelationClassName) do |klass|
297
324
  create_where_chain_methods(klass, RelationClassName)
298
325
  klass.create_type_variable("Elem", type: "type_member", fixed: constant_name)
299
326
  end
300
327
  end
301
328
 
302
- sig { params(model: RBI::Scope).void }
303
- def create_association_relation_where_chain_class(model)
329
+ sig { void }
330
+ def create_association_relation_where_chain_class
304
331
  model.create_class(
305
332
  AssociationRelationWhereChainClassName,
306
333
  superclass_name: AssociationRelationClassName,
@@ -335,8 +362,8 @@ module Tapioca
335
362
  end
336
363
  end
337
364
 
338
- sig { params(model: RBI::Scope).void }
339
- def create_collection_proxy_class(model)
365
+ sig { void }
366
+ def create_collection_proxy_class
340
367
  superclass = "::ActiveRecord::Associations::CollectionProxy"
341
368
 
342
369
  # The relation subclass includes the generated association relation module
@@ -429,13 +456,11 @@ module Tapioca
429
456
  end
430
457
  end
431
458
 
432
- sig { params(relation_methods_module: RBI::Scope, association_relation_methods_module: RBI::Scope).void }
433
- def create_relation_methods(relation_methods_module, association_relation_methods_module)
434
- create_relation_method("all", relation_methods_module, association_relation_methods_module)
459
+ sig { void }
460
+ def create_relation_methods
461
+ create_relation_method("all")
435
462
  create_relation_method(
436
463
  "where",
437
- relation_methods_module,
438
- association_relation_methods_module,
439
464
  parameters: [
440
465
  create_rest_param("args", type: "T.untyped"),
441
466
  create_block_param("blk", type: "T.untyped"),
@@ -447,8 +472,6 @@ module Tapioca
447
472
  QUERY_METHODS.each do |method_name|
448
473
  create_relation_method(
449
474
  method_name,
450
- relation_methods_module,
451
- association_relation_methods_module,
452
475
  parameters: [
453
476
  create_rest_param("args", type: "T.untyped"),
454
477
  create_block_param("blk", type: "T.untyped"),
@@ -457,8 +480,8 @@ module Tapioca
457
480
  end
458
481
  end
459
482
 
460
- sig { params(association_relation_methods_module: RBI::Scope).void }
461
- def create_association_relation_methods(association_relation_methods_module)
483
+ sig { void }
484
+ def create_association_relation_methods
462
485
  returning_type = "T.nilable(T.any(T::Array[Symbol], FalseClass))"
463
486
  unique_by_type = "T.nilable(T.any(T::Array[Symbol], Symbol))"
464
487
 
@@ -502,11 +525,10 @@ module Tapioca
502
525
  end
503
526
  end
504
527
 
505
- sig { params(common_relation_methods_module: RBI::Scope).void }
506
- def create_common_methods(common_relation_methods_module)
528
+ sig { void }
529
+ def create_common_methods
507
530
  create_common_method(
508
531
  "destroy_all",
509
- common_relation_methods_module,
510
532
  return_type: "T::Array[#{constant_name}]",
511
533
  )
512
534
 
@@ -515,7 +537,6 @@ module Tapioca
515
537
  when :exists?
516
538
  create_common_method(
517
539
  "exists?",
518
- common_relation_methods_module,
519
540
  parameters: [
520
541
  create_opt_param("conditions", type: "T.untyped", default: ":none"),
521
542
  ],
@@ -524,7 +545,6 @@ module Tapioca
524
545
  when :include?, :member?
525
546
  create_common_method(
526
547
  method_name,
527
- common_relation_methods_module,
528
548
  parameters: [
529
549
  create_param("record", type: "T.untyped"),
530
550
  ],
@@ -533,7 +553,6 @@ module Tapioca
533
553
  when :find
534
554
  create_common_method(
535
555
  "find",
536
- common_relation_methods_module,
537
556
  parameters: [
538
557
  create_rest_param("args", type: "T.untyped"),
539
558
  ],
@@ -542,7 +561,6 @@ module Tapioca
542
561
  when :find_by
543
562
  create_common_method(
544
563
  "find_by",
545
- common_relation_methods_module,
546
564
  parameters: [
547
565
  create_rest_param("args", type: "T.untyped"),
548
566
  ],
@@ -551,7 +569,6 @@ module Tapioca
551
569
  when :find_by!
552
570
  create_common_method(
553
571
  "find_by!",
554
- common_relation_methods_module,
555
572
  parameters: [
556
573
  create_rest_param("args", type: "T.untyped"),
557
574
  ],
@@ -560,7 +577,6 @@ module Tapioca
560
577
  when :find_sole_by
561
578
  create_common_method(
562
579
  "find_sole_by",
563
- common_relation_methods_module,
564
580
  parameters: [
565
581
  create_param("arg", type: "T.untyped"),
566
582
  create_rest_param("args", type: "T.untyped"),
@@ -570,14 +586,12 @@ module Tapioca
570
586
  when :sole
571
587
  create_common_method(
572
588
  "sole",
573
- common_relation_methods_module,
574
589
  parameters: [],
575
590
  return_type: constant_name,
576
591
  )
577
592
  when :first, :last, :take
578
593
  create_common_method(
579
594
  method_name,
580
- common_relation_methods_module,
581
595
  parameters: [
582
596
  create_opt_param("limit", type: "T.untyped", default: "nil"),
583
597
  ],
@@ -594,7 +608,6 @@ module Tapioca
594
608
 
595
609
  create_common_method(
596
610
  method_name,
597
- common_relation_methods_module,
598
611
  return_type: return_type,
599
612
  )
600
613
  end
@@ -605,7 +618,6 @@ module Tapioca
605
618
  when :find_signed
606
619
  create_common_method(
607
620
  "find_signed",
608
- common_relation_methods_module,
609
621
  parameters: [
610
622
  create_param("signed_id", type: "T.untyped"),
611
623
  create_kw_opt_param("purpose", type: "T.untyped", default: "nil"),
@@ -615,7 +627,6 @@ module Tapioca
615
627
  when :find_signed!
616
628
  create_common_method(
617
629
  "find_signed!",
618
- common_relation_methods_module,
619
630
  parameters: [
620
631
  create_param("signed_id", type: "T.untyped"),
621
632
  create_kw_opt_param("purpose", type: "T.untyped", default: "nil"),
@@ -630,7 +641,6 @@ module Tapioca
630
641
  when :average, :maximum, :minimum
631
642
  create_common_method(
632
643
  method_name,
633
- common_relation_methods_module,
634
644
  parameters: [
635
645
  create_param("column_name", type: "T.any(String, Symbol)"),
636
646
  ],
@@ -639,7 +649,6 @@ module Tapioca
639
649
  when :calculate
640
650
  create_common_method(
641
651
  "calculate",
642
- common_relation_methods_module,
643
652
  parameters: [
644
653
  create_param("operation", type: "Symbol"),
645
654
  create_param("column_name", type: "T.any(String, Symbol)"),
@@ -649,18 +658,16 @@ module Tapioca
649
658
  when :count
650
659
  create_common_method(
651
660
  "count",
652
- common_relation_methods_module,
653
661
  parameters: [
654
662
  create_opt_param("column_name", type: "T.untyped", default: "nil"),
655
663
  ],
656
664
  return_type: "T.untyped",
657
665
  )
658
666
  when :ids
659
- create_common_method("ids", common_relation_methods_module, return_type: "Array")
667
+ create_common_method("ids", return_type: "Array")
660
668
  when :pick, :pluck
661
669
  create_common_method(
662
670
  method_name,
663
- common_relation_methods_module,
664
671
  parameters: [
665
672
  create_rest_param("column_names", type: "T.untyped"),
666
673
  ],
@@ -669,7 +676,6 @@ module Tapioca
669
676
  when :sum
670
677
  create_common_method(
671
678
  "sum",
672
- common_relation_methods_module,
673
679
  parameters: [
674
680
  create_opt_param("column_name", type: "T.nilable(T.any(String, Symbol))", default: "nil"),
675
681
  create_block_param("block", type: "T.nilable(T.proc.params(record: T.untyped).returns(T.untyped))"),
@@ -679,11 +685,63 @@ module Tapioca
679
685
  end
680
686
  end
681
687
 
688
+ BATCHES_METHODS.each do |method_name|
689
+ case method_name
690
+ when :find_each
691
+ order = ActiveRecord::Batches.instance_method(:find_each).parameters.include?([:key, :order])
692
+ create_common_method(
693
+ "find_each",
694
+ parameters: [
695
+ create_kw_opt_param("start", type: "T.untyped", default: "nil"),
696
+ create_kw_opt_param("finish", type: "T.untyped", default: "nil"),
697
+ create_kw_opt_param("batch_size", type: "Integer", default: "1000"),
698
+ create_kw_opt_param("error_on_ignore", type: "T.untyped", default: "nil"),
699
+ *(create_kw_opt_param("order", type: "Symbol", default: ":asc") if order),
700
+ create_block_param("block", type: "T.nilable(T.proc.params(object: #{constant_name}).void)"),
701
+ ],
702
+ return_type: "T.nilable(T::Enumerator[#{constant_name}])",
703
+ )
704
+ when :find_in_batches
705
+ order = ActiveRecord::Batches.instance_method(:find_in_batches).parameters.include?([:key, :order])
706
+ create_common_method(
707
+ "find_in_batches",
708
+ parameters: [
709
+ create_kw_opt_param("start", type: "T.untyped", default: "nil"),
710
+ create_kw_opt_param("finish", type: "T.untyped", default: "nil"),
711
+ create_kw_opt_param("batch_size", type: "Integer", default: "1000"),
712
+ create_kw_opt_param("error_on_ignore", type: "T.untyped", default: "nil"),
713
+ *(create_kw_opt_param("order", type: "Symbol", default: ":asc") if order),
714
+ create_block_param(
715
+ "block",
716
+ type: "T.nilable(T.proc.params(object: T::Array[#{constant_name}]).void)",
717
+ ),
718
+ ],
719
+ return_type: "T.nilable(T::Enumerator[T::Enumerator[#{constant_name}]])",
720
+ )
721
+ when :in_batches
722
+ order = ActiveRecord::Batches.instance_method(:in_batches).parameters.include?([:key, :order])
723
+ use_ranges = ActiveRecord::Batches.instance_method(:in_batches).parameters.include?([:key, :use_ranges])
724
+ create_common_method(
725
+ "in_batches",
726
+ parameters: [
727
+ create_kw_opt_param("of", type: "Integer", default: "1000"),
728
+ create_kw_opt_param("start", type: "T.untyped", default: "nil"),
729
+ create_kw_opt_param("finish", type: "T.untyped", default: "nil"),
730
+ create_kw_opt_param("load", type: "T.untyped", default: "false"),
731
+ create_kw_opt_param("error_on_ignore", type: "T.untyped", default: "nil"),
732
+ *(create_kw_opt_param("order", type: "Symbol", default: ":asc") if order),
733
+ *(create_kw_opt_param("use_ranges", type: "T.untyped", default: "nil") if use_ranges),
734
+ create_block_param("block", type: "T.nilable(T.proc.params(object: #{RelationClassName}).void)"),
735
+ ],
736
+ return_type: "T.nilable(::ActiveRecord::Batches::BatchEnumerator)",
737
+ )
738
+ end
739
+ end
740
+
682
741
  ENUMERABLE_QUERY_METHODS.each do |method_name|
683
742
  block_type = "T.nilable(T.proc.params(record: #{constant_name}).returns(T.untyped))"
684
743
  create_common_method(
685
744
  method_name,
686
- common_relation_methods_module,
687
745
  parameters: [
688
746
  create_block_param("block", type: block_type),
689
747
  ],
@@ -695,7 +753,6 @@ module Tapioca
695
753
  block_type = "T.nilable(T.proc.params(object: #{constant_name}).void)"
696
754
  create_common_method(
697
755
  method_name,
698
- common_relation_methods_module,
699
756
  parameters: [
700
757
  create_param("attributes", type: "T.untyped"),
701
758
  create_block_param("block", type: block_type),
@@ -707,7 +764,6 @@ module Tapioca
707
764
  BUILDER_METHODS.each do |method_name|
708
765
  create_common_method(
709
766
  method_name,
710
- common_relation_methods_module,
711
767
  parameters: [
712
768
  create_opt_param("attributes", type: "T.untyped", default: "nil"),
713
769
  create_block_param("block", type: "T.nilable(T.proc.params(object: #{constant_name}).void)"),
@@ -720,12 +776,11 @@ module Tapioca
720
776
  sig do
721
777
  params(
722
778
  name: T.any(Symbol, String),
723
- common_relation_methods_module: RBI::Scope,
724
779
  parameters: T::Array[RBI::TypedParam],
725
780
  return_type: T.nilable(String),
726
781
  ).void
727
782
  end
728
- def create_common_method(name, common_relation_methods_module, parameters: [], return_type: nil)
783
+ def create_common_method(name, parameters: [], return_type: nil)
729
784
  common_relation_methods_module.create_method(
730
785
  name.to_s,
731
786
  parameters: parameters,
@@ -736,8 +791,6 @@ module Tapioca
736
791
  sig do
737
792
  params(
738
793
  name: T.any(Symbol, String),
739
- relation_methods_module: RBI::Scope,
740
- association_relation_methods_module: RBI::Scope,
741
794
  parameters: T::Array[RBI::TypedParam],
742
795
  relation_return_type: String,
743
796
  association_return_type: String,
@@ -745,8 +798,6 @@ module Tapioca
745
798
  end
746
799
  def create_relation_method(
747
800
  name,
748
- relation_methods_module,
749
- association_relation_methods_module,
750
801
  parameters: [],
751
802
  relation_return_type: RelationClassName,
752
803
  association_return_type: AssociationRelationClassName
@@ -83,7 +83,7 @@ module Tapioca
83
83
  class << self
84
84
  sig { override.returns(T::Enumerable[Module]) }
85
85
  def gather_constants
86
- descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
86
+ descendants_of(::ActiveRecord::Base)
87
87
  end
88
88
  end
89
89
 
@@ -0,0 +1,74 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ begin
5
+ require "active_record"
6
+ rescue LoadError
7
+ return
8
+ end
9
+
10
+ require "tapioca/dsl/helpers/active_record_constants_helper"
11
+
12
+ module Tapioca
13
+ module Dsl
14
+ module Compilers
15
+ # `Tapioca::Dsl::Compilers::ActiveModelSecurePassword` decorates RBI files for all
16
+ # classes that use [`ActiveRecord::SecureToken`](https://api.rubyonrails.org/classes/ActiveRecord/SecureToken/ClassMethods.html).
17
+ #
18
+ # For example, with the following class:
19
+ #
20
+ # ~~~rb
21
+ # class User < ActiveRecord::Base
22
+ # has_secure_token
23
+ # has_secure_token :auth_token, length: 36
24
+ # end
25
+ # ~~~
26
+ #
27
+ # this compiler will produce an RBI file with the following content:
28
+ # ~~~rbi
29
+ # # typed: true
30
+ #
31
+ # class User
32
+ # sig { returns(T::Boolean) }
33
+ # def regenerate_token; end
34
+ #
35
+ # sig { returns(T::Boolean) }
36
+ # def regenerate_auth_token; end
37
+ # end
38
+ # ~~~
39
+ class ActiveRecordSecureToken < Compiler
40
+ extend T::Sig
41
+ include Helpers::ActiveRecordConstantsHelper
42
+
43
+ ConstantType = type_member { { fixed: T.all(T.class_of(ActiveRecord::Base), Extensions::ActiveRecord) } }
44
+
45
+ sig { override.void }
46
+ def decorate
47
+ return if constant.__tapioca_secure_tokens.nil?
48
+
49
+ root.create_path(constant) do |model|
50
+ model.create_module(SecureTokensModuleName) do |mod|
51
+ constant.__tapioca_secure_tokens.each do |attribute|
52
+ mod.create_method(
53
+ "regenerate_#{attribute}",
54
+ return_type: "T::Boolean",
55
+ )
56
+ end
57
+ end
58
+
59
+ model.create_include(SecureTokensModuleName)
60
+ end
61
+ end
62
+
63
+ class << self
64
+ extend T::Sig
65
+
66
+ sig { override.returns(T::Enumerable[Module]) }
67
+ def gather_constants
68
+ descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -45,7 +45,11 @@ module Tapioca
45
45
 
46
46
  sig { override.void }
47
47
  def decorate
48
- arguments = constant.all_argument_definitions
48
+ # Skip methods explicitly defined in code
49
+ arguments = constant.all_argument_definitions.select do |argument|
50
+ method_defined_by_graphql?(argument.keyword.to_s)
51
+ end
52
+
49
53
  return if arguments.empty?
50
54
 
51
55
  root.create_path(constant) do |input_object|
@@ -56,6 +60,22 @@ module Tapioca
56
60
  end
57
61
  end
58
62
 
63
+ private
64
+
65
+ sig { returns(T.nilable(String)) }
66
+ def graphql_input_object_argument_source_file
67
+ @graphql_input_object_argument_source_file ||= T.let(
68
+ GraphQL::Schema::InputObject.method(:argument).source_location&.first,
69
+ T.nilable(String),
70
+ )
71
+ end
72
+
73
+ sig { params(method_name: String).returns(T::Boolean) }
74
+ def method_defined_by_graphql?(method_name)
75
+ method_file = constant.instance_method(method_name).source_location&.first
76
+ !!(method_file && graphql_input_object_argument_source_file == method_file)
77
+ end
78
+
59
79
  class << self
60
80
  extend T::Sig
61
81
 
@@ -0,0 +1,130 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ begin
5
+ require "kredis"
6
+ rescue LoadError
7
+ return
8
+ end
9
+
10
+ module Tapioca
11
+ module Dsl
12
+ module Compilers
13
+ # `Tapioca::Dsl::Compilers::Kredis` decorates RBI files for all
14
+ # classes that include [`Kredis::Attributes`](https://github.com/rails/kredis/blob/main/lib/kredis/attributes.rb).
15
+ #
16
+ # For example, with the following class:
17
+ #
18
+ # ~~~rb
19
+ # class Person < ApplicationRecord
20
+ # kredis_list :names
21
+ # kredis_flag :awesome
22
+ # kredis_counter :steps, expires_in: 1.hour
23
+ # kredis_enum :morning, values: %w[ bright blue black ], default: "bright"
24
+ # end
25
+ # ~~~
26
+ #
27
+ # this compiler will produce an RBI file with the following content:
28
+ # ~~~rbi
29
+ # # typed: true
30
+ #
31
+ # class Person
32
+ # module GeneratedKredisAttributeMethods
33
+ # sig { returns(Kredis::Types::Flag) }
34
+ # def awesome; end
35
+ #
36
+ # sig { returns(T::Boolean) }
37
+ # def awesome?; end
38
+ #
39
+ # sig { returns(PrivateEnumMorning) }
40
+ # def morning; end
41
+ #
42
+ # sig { returns(Kredis::Types::List) }
43
+ # def names; end
44
+ #
45
+ # sig { returns(Kredis::Types::Counter) }
46
+ # def steps; end
47
+ #
48
+ # class PrivateEnumMorning < Kredis::Types::Enum
49
+ # sig { void }
50
+ # def black!; end
51
+ #
52
+ # sig { returns(T::Boolean) }
53
+ # def black?; end
54
+ #
55
+ # sig { void }
56
+ # def blue!; end
57
+ #
58
+ # sig { returns(T::Boolean) }
59
+ # def blue?; end
60
+ #
61
+ # sig { void }
62
+ # def bright!; end
63
+ #
64
+ # sig { returns(T::Boolean) }
65
+ # def bright?; end
66
+ # end
67
+ # end
68
+ # end
69
+ # ~~~
70
+ class Kredis < Compiler
71
+ extend T::Sig
72
+
73
+ ConstantType = type_member { { fixed: T.all(Class, ::Kredis::Attributes::ClassMethods, Extensions::Kredis) } }
74
+
75
+ sig { override.void }
76
+ def decorate
77
+ return if constant.__tapioca_kredis_types.nil?
78
+
79
+ module_name = "GeneratedKredisAttributeMethods"
80
+
81
+ root.create_path(constant) do |model|
82
+ model.create_module(module_name) do |mod|
83
+ constant.__tapioca_kredis_types.each do |method, data|
84
+ generate_methods(mod, method, data)
85
+ end
86
+ end
87
+ model.create_include(module_name)
88
+ end
89
+ end
90
+
91
+ class << self
92
+ extend T::Sig
93
+
94
+ sig { override.returns(T::Enumerable[Module]) }
95
+ def gather_constants
96
+ all_classes
97
+ .grep(::Kredis::Attributes::ClassMethods)
98
+ .reject { |klass| klass.to_s == "ActiveRecord::Base" || klass.try(:abstract_class?) }
99
+ end
100
+ end
101
+
102
+ private
103
+
104
+ sig { params(mod: RBI::Scope, method: String, data: T::Hash[Symbol, T.untyped]).void }
105
+ def generate_methods(mod, method, data)
106
+ return_type = data.fetch(:type)
107
+ case return_type
108
+ when "Kredis::Types::Enum"
109
+ klass_name = "PrivateEnum#{method.split("_").map(&:capitalize).join}"
110
+ create_enum_class(mod, klass_name, data.fetch(:values))
111
+ return_type = klass_name
112
+ when "Kredis::Types::Flag"
113
+ mod.create_method("#{method}?", return_type: "T::Boolean")
114
+ end
115
+
116
+ mod.create_method(method, return_type: return_type)
117
+ end
118
+
119
+ sig { params(mod: RBI::Scope, klass_name: String, values: T::Array[T.untyped]).void }
120
+ def create_enum_class(mod, klass_name, values)
121
+ klass = mod.create_class(klass_name, superclass_name: "Kredis::Types::Enum")
122
+ values.each do |value|
123
+ klass.create_method("#{value}!", return_type: "void")
124
+ klass.create_method("#{value}?", return_type: "T::Boolean")
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end