tapioca 0.10.5 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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