tapioca 0.6.4 → 0.7.2

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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +8 -2
  3. data/README.md +27 -15
  4. data/Rakefile +10 -14
  5. data/lib/tapioca/cli.rb +65 -80
  6. data/lib/tapioca/{generators/base.rb → commands/command.rb} +16 -9
  7. data/lib/tapioca/{generators → commands}/dsl.rb +59 -45
  8. data/lib/tapioca/{generators → commands}/gem.rb +93 -30
  9. data/lib/tapioca/{generators → commands}/init.rb +9 -13
  10. data/lib/tapioca/{generators → commands}/require.rb +8 -10
  11. data/lib/tapioca/commands/todo.rb +86 -0
  12. data/lib/tapioca/commands.rb +13 -0
  13. data/lib/tapioca/dsl/compiler.rb +185 -0
  14. data/lib/tapioca/{compilers/dsl → dsl/compilers}/aasm.rb +12 -9
  15. data/lib/tapioca/{compilers/dsl → dsl/compilers}/action_controller_helpers.rb +13 -20
  16. data/lib/tapioca/{compilers/dsl → dsl/compilers}/action_mailer.rb +10 -8
  17. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_job.rb +11 -9
  18. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_model_attributes.rb +13 -11
  19. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_model_secure_password.rb +10 -12
  20. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_associations.rb +28 -34
  21. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_columns.rb +18 -16
  22. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_enum.rb +14 -12
  23. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_fixtures.rb +12 -8
  24. data/lib/tapioca/dsl/compilers/active_record_relations.rb +712 -0
  25. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_scope.rb +21 -20
  26. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_typed_store.rb +11 -16
  27. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_resource.rb +10 -8
  28. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_storage.rb +14 -10
  29. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_support_concern.rb +19 -14
  30. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_support_current_attributes.rb +16 -21
  31. data/lib/tapioca/{compilers/dsl → dsl/compilers}/config.rb +11 -9
  32. data/lib/tapioca/{compilers/dsl → dsl/compilers}/frozen_record.rb +13 -11
  33. data/lib/tapioca/{compilers/dsl → dsl/compilers}/identity_cache.rb +23 -22
  34. data/lib/tapioca/{compilers/dsl → dsl/compilers}/mixed_in_class_attributes.rb +12 -10
  35. data/lib/tapioca/{compilers/dsl → dsl/compilers}/protobuf.rb +22 -10
  36. data/lib/tapioca/{compilers/dsl → dsl/compilers}/rails_generators.rb +12 -13
  37. data/lib/tapioca/{compilers/dsl → dsl/compilers}/sidekiq_worker.rb +14 -13
  38. data/lib/tapioca/{compilers/dsl → dsl/compilers}/smart_properties.rb +11 -9
  39. data/lib/tapioca/{compilers/dsl → dsl/compilers}/state_machines.rb +12 -10
  40. data/lib/tapioca/{compilers/dsl → dsl/compilers}/url_helpers.rb +20 -15
  41. data/lib/tapioca/dsl/compilers.rb +31 -0
  42. data/lib/tapioca/{compilers/dsl → dsl}/extensions/frozen_record.rb +2 -2
  43. data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +114 -0
  44. data/lib/tapioca/dsl/helpers/active_record_constants_helper.rb +29 -0
  45. data/lib/tapioca/{compilers/dsl → dsl/helpers}/param_helper.rb +6 -3
  46. data/lib/tapioca/dsl/pipeline.rb +169 -0
  47. data/lib/tapioca/gem/events.rb +120 -0
  48. data/lib/tapioca/gem/listeners/base.rb +48 -0
  49. data/lib/tapioca/gem/listeners/dynamic_mixins.rb +32 -0
  50. data/lib/tapioca/gem/listeners/methods.rb +183 -0
  51. data/lib/tapioca/gem/listeners/mixins.rb +101 -0
  52. data/lib/tapioca/gem/listeners/remove_empty_payload_scopes.rb +21 -0
  53. data/lib/tapioca/gem/listeners/sorbet_enums.rb +26 -0
  54. data/lib/tapioca/gem/listeners/sorbet_helpers.rb +29 -0
  55. data/lib/tapioca/gem/listeners/sorbet_props.rb +33 -0
  56. data/lib/tapioca/gem/listeners/sorbet_required_ancestors.rb +23 -0
  57. data/lib/tapioca/gem/listeners/sorbet_signatures.rb +79 -0
  58. data/lib/tapioca/gem/listeners/sorbet_type_variables.rb +51 -0
  59. data/lib/tapioca/gem/listeners/subconstants.rb +37 -0
  60. data/lib/tapioca/gem/listeners/yard_doc.rb +96 -0
  61. data/lib/tapioca/gem/listeners.rb +16 -0
  62. data/lib/tapioca/gem/pipeline.rb +365 -0
  63. data/lib/tapioca/helpers/cli_helper.rb +7 -0
  64. data/lib/tapioca/helpers/config_helper.rb +5 -8
  65. data/lib/tapioca/helpers/shims_helper.rb +87 -0
  66. data/lib/tapioca/helpers/signatures_helper.rb +17 -0
  67. data/lib/tapioca/helpers/sorbet_helper.rb +57 -0
  68. data/lib/tapioca/helpers/test/dsl_compiler.rb +118 -0
  69. data/lib/tapioca/helpers/test/isolation.rb +1 -1
  70. data/lib/tapioca/helpers/test/template.rb +13 -2
  71. data/lib/tapioca/helpers/type_variable_helper.rb +43 -0
  72. data/lib/tapioca/internal.rb +18 -10
  73. data/lib/tapioca/rbi_ext/model.rb +14 -50
  74. data/lib/tapioca/rbi_formatter.rb +37 -0
  75. data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +227 -0
  76. data/lib/tapioca/runtime/generic_type_registry.rb +168 -0
  77. data/lib/tapioca/runtime/loader.rb +123 -0
  78. data/lib/tapioca/runtime/reflection.rb +157 -0
  79. data/lib/tapioca/runtime/trackers/autoload.rb +72 -0
  80. data/lib/tapioca/runtime/trackers/constant_definition.rb +44 -0
  81. data/lib/tapioca/runtime/trackers/mixin.rb +80 -0
  82. data/lib/tapioca/runtime/trackers/required_ancestor.rb +50 -0
  83. data/lib/tapioca/{trackers.rb → runtime/trackers.rb} +4 -3
  84. data/lib/tapioca/sorbet_ext/generic_name_patch.rb +69 -34
  85. data/lib/tapioca/sorbet_ext/name_patch.rb +7 -1
  86. data/lib/tapioca/{compilers → static}/requires_compiler.rb +2 -2
  87. data/lib/tapioca/static/symbol_loader.rb +83 -0
  88. data/lib/tapioca/static/symbol_table_parser.rb +63 -0
  89. data/lib/tapioca/version.rb +1 -1
  90. data/lib/tapioca.rb +2 -7
  91. metadata +83 -62
  92. data/lib/tapioca/compilers/dsl/active_record_relations.rb +0 -720
  93. data/lib/tapioca/compilers/dsl/base.rb +0 -195
  94. data/lib/tapioca/compilers/dsl/helper/active_record_constants.rb +0 -27
  95. data/lib/tapioca/compilers/dsl_compiler.rb +0 -134
  96. data/lib/tapioca/compilers/dynamic_mixin_compiler.rb +0 -223
  97. data/lib/tapioca/compilers/sorbet.rb +0 -59
  98. data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +0 -780
  99. data/lib/tapioca/compilers/symbol_table/symbol_loader.rb +0 -90
  100. data/lib/tapioca/compilers/symbol_table_compiler.rb +0 -17
  101. data/lib/tapioca/compilers/todos_compiler.rb +0 -32
  102. data/lib/tapioca/generators/todo.rb +0 -76
  103. data/lib/tapioca/generators.rb +0 -9
  104. data/lib/tapioca/generic_type_registry.rb +0 -164
  105. data/lib/tapioca/helpers/active_record_column_type_helper.rb +0 -108
  106. data/lib/tapioca/loader.rb +0 -119
  107. data/lib/tapioca/reflection.rb +0 -151
  108. data/lib/tapioca/trackers/autoload.rb +0 -70
  109. data/lib/tapioca/trackers/constant_definition.rb +0 -42
  110. data/lib/tapioca/trackers/mixin.rb +0 -78
@@ -7,12 +7,12 @@ rescue LoadError
7
7
  return
8
8
  end
9
9
 
10
- require "tapioca/compilers/dsl/helper/active_record_constants"
10
+ require "tapioca/dsl/helpers/active_record_constants_helper"
11
11
 
12
12
  module Tapioca
13
- module Compilers
14
- module Dsl
15
- # `Tapioca::Compilers::Dsl::ActiveRecordScope` decorates RBI files for
13
+ module Dsl
14
+ module Compilers
15
+ # `Tapioca::Dsl::Compilers::ActiveRecordScope` decorates RBI files for
16
16
  # subclasses of `ActiveRecord::Base` which declare
17
17
  # [`scope` fields](https://api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html#method-i-scope).
18
18
  #
@@ -25,7 +25,7 @@ module Tapioca
25
25
  # end
26
26
  # ~~~
27
27
  #
28
- # this generator will produce the RBI file `post.rbi` with the following content:
28
+ # this compiler will produce the RBI file `post.rbi` with the following content:
29
29
  #
30
30
  # ~~~rbi
31
31
  # # post.rbi
@@ -42,23 +42,20 @@ module Tapioca
42
42
  # end
43
43
  # end
44
44
  # ~~~
45
- class ActiveRecordScope < Base
45
+ class ActiveRecordScope < Compiler
46
46
  extend T::Sig
47
- include Helper::ActiveRecordConstants
47
+ include Helpers::ActiveRecordConstantsHelper
48
48
 
49
- sig do
50
- override.params(
51
- root: RBI::Tree,
52
- constant: T.class_of(::ActiveRecord::Base)
53
- ).void
54
- end
55
- def decorate(root, constant)
56
- method_names = scope_method_names(constant)
49
+ ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
50
+
51
+ sig { override.void }
52
+ def decorate
53
+ method_names = scope_method_names
57
54
 
58
55
  return if method_names.empty?
59
56
 
60
57
  root.create_path(constant) do |model|
61
- relations_enabled = generator_enabled?("ActiveRecordRelations")
58
+ relations_enabled = compiler_enabled?("ActiveRecordRelations")
62
59
 
63
60
  relation_methods_module = model.create_module(RelationMethodsModuleName)
64
61
  assoc_relation_methods_mod = model.create_module(AssociationRelationMethodsModuleName) if relations_enabled
@@ -84,22 +81,26 @@ module Tapioca
84
81
  end
85
82
 
86
83
  sig { override.returns(T::Enumerable[Module]) }
87
- def gather_constants
84
+ def self.gather_constants
88
85
  descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
89
86
  end
90
87
 
91
88
  private
92
89
 
93
- sig { params(constant: T.class_of(::ActiveRecord::Base)).returns(T::Array[Symbol]) }
94
- def scope_method_names(constant)
90
+ sig { returns(T::Array[Symbol]) }
91
+ def scope_method_names
95
92
  scope_methods = T.let([], T::Array[Symbol])
93
+ constant = self.constant
96
94
 
97
95
  # Keep gathering scope methods until we hit "ActiveRecord::Base"
98
96
  until constant == ActiveRecord::Base
99
97
  scope_methods.concat(constant.send(:generated_relation_methods).instance_methods(false))
100
98
 
99
+ superclass = superclass_of(constant)
100
+ break unless superclass
101
+
101
102
  # we are guaranteed to have a superclass that is of type "ActiveRecord::Base"
102
- constant = T.cast(constant.superclass, T.class_of(ActiveRecord::Base))
103
+ constant = T.cast(superclass, T.class_of(ActiveRecord::Base))
103
104
  end
104
105
 
105
106
  scope_methods
@@ -5,14 +5,14 @@ begin
5
5
  require "activerecord-typedstore"
6
6
  rescue LoadError
7
7
  # means ActiveRecord::TypedStore is not installed,
8
- # so let's not even define the generator.
8
+ # so let's not even define the compiler.
9
9
  return
10
10
  end
11
11
 
12
12
  module Tapioca
13
- module Compilers
14
- module Dsl
15
- # `Tapioca::Compilers::DSL::ActiveRecordTypedStore` generates RBI files for Active Record models that use
13
+ module Dsl
14
+ module Compilers
15
+ # `Tapioca::Dsl::Compilers::ActiveRecordTypedStore` generates RBI files for Active Record models that use
16
16
  # [`ActiveRecord::TypedStore`](https://github.com/byroot/activerecord-typedstore) features.
17
17
  #
18
18
  # For example, with the following ActiveRecord class:
@@ -28,7 +28,7 @@ module Tapioca
28
28
  # end
29
29
  # ~~~
30
30
  #
31
- # this generator will produce the RBI file `post.rbi` with the following content:
31
+ # this compiler will produce the RBI file `post.rbi` with the following content:
32
32
  #
33
33
  # ~~~rbi
34
34
  # # post.rbi
@@ -87,18 +87,13 @@ module Tapioca
87
87
  # end
88
88
  # end
89
89
  # ~~~
90
- class ActiveRecordTypedStore < Base
90
+ class ActiveRecordTypedStore < Compiler
91
91
  extend T::Sig
92
92
 
93
- sig do
94
- override
95
- .params(
96
- root: RBI::Tree,
97
- constant: T.class_of(::ActiveRecord::Base)
98
- )
99
- .void
100
- end
101
- def decorate(root, constant)
93
+ ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
94
+
95
+ sig { override.void }
96
+ def decorate
102
97
  stores = constant.typed_stores
103
98
  return if stores.values.flat_map(&:accessors).empty?
104
99
 
@@ -118,7 +113,7 @@ module Tapioca
118
113
  end
119
114
 
120
115
  sig { override.returns(T::Enumerable[Module]) }
121
- def gather_constants
116
+ def self.gather_constants
122
117
  descendants_of(::ActiveRecord::Base).select do |klass|
123
118
  klass.include?(ActiveRecord::TypedStore::Behavior)
124
119
  end
@@ -8,9 +8,9 @@ rescue LoadError
8
8
  end
9
9
 
10
10
  module Tapioca
11
- module Compilers
12
- module Dsl
13
- # `Tapioca::Compilers::Dsl::ActiveResource` decorates RBI files for subclasses of
11
+ module Dsl
12
+ module Compilers
13
+ # `Tapioca::Dsl::Compilers::ActiveResource` decorates RBI files for subclasses of
14
14
  # [`ActiveResource::Base`](https://github.com/rails/activeresource) which declare
15
15
  # `schema` fields.
16
16
  #
@@ -24,7 +24,7 @@ module Tapioca
24
24
  # end
25
25
  # ~~~
26
26
  #
27
- # this generator will produce the RBI file `post.rbi` with the following content:
27
+ # this compiler will produce the RBI file `post.rbi` with the following content:
28
28
  #
29
29
  # ~~~rbi
30
30
  # # post.rbi
@@ -58,11 +58,13 @@ module Tapioca
58
58
  # def year?; end
59
59
  # end
60
60
  # ~~~
61
- class ActiveResource < Base
61
+ class ActiveResource < Compiler
62
62
  extend T::Sig
63
63
 
64
- sig { override.params(root: RBI::Tree, constant: T.class_of(::ActiveResource::Base)).void }
65
- def decorate(root, constant)
64
+ ConstantType = type_member { { fixed: T.class_of(::ActiveResource::Base) } }
65
+
66
+ sig { override.void }
67
+ def decorate
66
68
  return if constant.schema.blank?
67
69
 
68
70
  root.create_path(constant) do |resource|
@@ -73,7 +75,7 @@ module Tapioca
73
75
  end
74
76
 
75
77
  sig { override.returns(T::Enumerable[Module]) }
76
- def gather_constants
78
+ def self.gather_constants
77
79
  descendants_of(::ActiveResource::Base)
78
80
  end
79
81
 
@@ -9,9 +9,9 @@ rescue LoadError
9
9
  end
10
10
 
11
11
  module Tapioca
12
- module Compilers
13
- module Dsl
14
- # `Tapioca::Compilers::Dsl::ActiveStorage` decorates RBI files for subclasses of
12
+ module Dsl
13
+ module Compilers
14
+ # `Tapioca::Dsl::Compilers::ActiveStorage` decorates RBI files for subclasses of
15
15
  # `ActiveRecord::Base` that declare [one](https://edgeguides.rubyonrails.org/active_storage_overview.html#has-one-attached)
16
16
  # or [many](https://edgeguides.rubyonrails.org/active_storage_overview.html#has-many-attached) attachments.
17
17
  #
@@ -24,7 +24,7 @@ module Tapioca
24
24
  # end
25
25
  # ~~~
26
26
  #
27
- # this generator will produce the RBI file `post.rbi` with the following content:
27
+ # this compiler will produce the RBI file `post.rbi` with the following content:
28
28
  #
29
29
  # ~~~rbi
30
30
  # # typed: strong
@@ -43,14 +43,18 @@ module Tapioca
43
43
  # def photo=(attachable); end
44
44
  # end
45
45
  # ~~~
46
- class ActiveStorage < Base
46
+ class ActiveStorage < Compiler
47
47
  extend T::Sig
48
48
 
49
- sig do
50
- override.params(root: RBI::Tree,
51
- constant: T.all(Module, ::ActiveStorage::Reflection::ActiveRecordExtensions::ClassMethods)).void
49
+ ConstantType = type_member do
50
+ {
51
+ fixed: T.all(Module,
52
+ ::ActiveStorage::Reflection::ActiveRecordExtensions::ClassMethods),
53
+ }
52
54
  end
53
- def decorate(root, constant)
55
+
56
+ sig { override.void }
57
+ def decorate
54
58
  return if constant.reflect_on_all_attachments.empty?
55
59
 
56
60
  root.create_path(constant) do |scope|
@@ -71,7 +75,7 @@ module Tapioca
71
75
  end
72
76
 
73
77
  sig { override.returns(T::Enumerable[Module]) }
74
- def gather_constants
78
+ def self.gather_constants
75
79
  descendants_of(::ActiveRecord::Base)
76
80
  .reject(&:abstract_class?)
77
81
  .grep(::ActiveStorage::Reflection::ActiveRecordExtensions::ClassMethods)
@@ -1,8 +1,6 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "tapioca/compilers/sorbet"
5
-
6
4
  begin
7
5
  require "active_support"
8
6
  rescue LoadError
@@ -10,9 +8,9 @@ rescue LoadError
10
8
  end
11
9
 
12
10
  module Tapioca
13
- module Compilers
14
- module Dsl
15
- # `Tapioca::Compilers::Dsl::ActiveSupportConcern` generates RBI files for classes that both `extend`
11
+ module Dsl
12
+ module Compilers
13
+ # `Tapioca::Dsl::Compilers::ActiveSupportConcern` generates RBI files for classes that both `extend`
16
14
  # `ActiveSupport::Concern` and `include` another class that extends `ActiveSupport::Concern`
17
15
  #
18
16
  # For example for the following hierarchy:
@@ -35,7 +33,7 @@ module Tapioca
35
33
  # end
36
34
  # ~~~
37
35
  #
38
- # this generator will produce the RBI file `concern.rbi` with the following content:
36
+ # this compiler will produce the RBI file `concern.rbi` with the following content:
39
37
  #
40
38
  # ~~~rbi
41
39
  # # typed: true
@@ -43,12 +41,14 @@ module Tapioca
43
41
  # mixes_in_class_methods(::Foo::ClassMethods)
44
42
  # end
45
43
  # ~~~
46
- class ActiveSupportConcern < Base
44
+ class ActiveSupportConcern < Compiler
47
45
  extend T::Sig
48
46
 
49
- sig { override.params(root: RBI::Tree, constant: Module).void }
50
- def decorate(root, constant)
51
- dependencies = linearized_dependencies_of(constant)
47
+ ConstantType = type_member { { fixed: Module } }
48
+
49
+ sig { override.void }
50
+ def decorate
51
+ dependencies = linearized_dependencies
52
52
 
53
53
  mixed_in_class_methods = dependencies
54
54
  .uniq # Deduplicate
@@ -67,7 +67,7 @@ module Tapioca
67
67
  end
68
68
 
69
69
  sig { override.returns(T::Enumerable[Module]) }
70
- def gather_constants
70
+ def self.gather_constants
71
71
  # Find all Modules that are:
72
72
  all_modules.select do |mod|
73
73
  # named (i.e. not anonymous)
@@ -81,15 +81,20 @@ module Tapioca
81
81
  end
82
82
  end
83
83
 
84
+ sig { params(concern: Module).returns(T::Array[Module]) }
85
+ def self.dependencies_of(concern)
86
+ concern.instance_variable_get(:@_dependencies)
87
+ end
88
+
84
89
  private
85
90
 
86
91
  sig { params(concern: Module).returns(T::Array[Module]) }
87
92
  def dependencies_of(concern)
88
- concern.instance_variable_get(:@_dependencies)
93
+ self.class.dependencies_of(concern)
89
94
  end
90
95
 
91
96
  sig { params(concern: Module).returns(T::Array[Module]) }
92
- def linearized_dependencies_of(concern)
97
+ def linearized_dependencies(concern = constant)
93
98
  # Grab all the dependencies of the concern
94
99
  dependencies = dependencies_of(concern)
95
100
 
@@ -97,7 +102,7 @@ module Tapioca
97
102
  dependencies.flat_map do |dependency|
98
103
  # Linearize dependencies of the current dependency,
99
104
  # which, itself, is a concern
100
- linearized_dependencies_of(dependency) << dependency
105
+ linearized_dependencies(dependency) << dependency
101
106
  end
102
107
  end
103
108
  end
@@ -10,9 +10,9 @@ rescue LoadError
10
10
  end
11
11
 
12
12
  module Tapioca
13
- module Compilers
14
- module Dsl
15
- # `Tapioca::Compilers::Dsl::ActiveSupportCurrentAttributes` decorates RBI files for all
13
+ module Dsl
14
+ module Compilers
15
+ # `Tapioca::Dsl::Compilers::ActiveSupportCurrentAttributes` decorates RBI files for all
16
16
  # subclasses of
17
17
  # [`ActiveSupport::CurrentAttributes`](https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html).
18
18
  #
@@ -35,7 +35,7 @@ module Tapioca
35
35
  # end
36
36
  # ~~~
37
37
  #
38
- # this generator will produce an RBI file with the following content:
38
+ # this compiler will produce an RBI file with the following content:
39
39
  # ~~~rbi
40
40
  # # typed: true
41
41
  #
@@ -59,20 +59,15 @@ module Tapioca
59
59
  # def self.helper; end
60
60
  # end
61
61
  # ~~~
62
- class ActiveSupportCurrentAttributes < Base
62
+ class ActiveSupportCurrentAttributes < Compiler
63
63
  extend T::Sig
64
64
 
65
- sig do
66
- override
67
- .params(
68
- root: RBI::Tree,
69
- constant: T.class_of(::ActiveSupport::CurrentAttributes)
70
- )
71
- .void
72
- end
73
- def decorate(root, constant)
74
- dynamic_methods = dynamic_methods_for(constant)
75
- instance_methods = instance_methods_for(constant) - dynamic_methods
65
+ ConstantType = type_member { { fixed: T.class_of(::ActiveSupport::CurrentAttributes) } }
66
+
67
+ sig { override.void }
68
+ def decorate
69
+ dynamic_methods = dynamic_methods_of_constant
70
+ instance_methods = instance_methods_of_constant - dynamic_methods
76
71
  return if dynamic_methods.empty? && instance_methods.empty?
77
72
 
78
73
  root.create_path(constant) do |current_attributes|
@@ -94,19 +89,19 @@ module Tapioca
94
89
  end
95
90
 
96
91
  sig { override.returns(T::Enumerable[Module]) }
97
- def gather_constants
92
+ def self.gather_constants
98
93
  descendants_of(::ActiveSupport::CurrentAttributes)
99
94
  end
100
95
 
101
96
  private
102
97
 
103
- sig { params(constant: T.class_of(::ActiveSupport::CurrentAttributes)).returns(T::Array[Symbol]) }
104
- def dynamic_methods_for(constant)
98
+ sig { returns(T::Array[Symbol]) }
99
+ def dynamic_methods_of_constant
105
100
  constant.instance_variable_get(:@generated_attribute_methods)&.instance_methods(false) || []
106
101
  end
107
102
 
108
- sig { params(constant: T.class_of(::ActiveSupport::CurrentAttributes)).returns(T::Array[Symbol]) }
109
- def instance_methods_for(constant)
103
+ sig { returns(T::Array[Symbol]) }
104
+ def instance_methods_of_constant
110
105
  constant.instance_methods(false)
111
106
  end
112
107
 
@@ -8,9 +8,9 @@ rescue LoadError
8
8
  end
9
9
 
10
10
  module Tapioca
11
- module Compilers
12
- module Dsl
13
- # `Tapioca::Compilers::Dsl::Config` generates RBI files for classes generated by the
11
+ module Dsl
12
+ module Compilers
13
+ # `Tapioca::Dsl::Compilers::Config` generates RBI files for classes generated by the
14
14
  # [`config`](https://github.com/rubyconfig/config) gem.
15
15
  #
16
16
  # The gem creates a `Config::Options` instance based on the settings files and/or
@@ -32,7 +32,7 @@ module Tapioca
32
32
  # config.const_name = "AppSettings"
33
33
  # end
34
34
  # ```
35
- # this generator will produce the following RBI file:
35
+ # this compiler will produce the following RBI file:
36
36
  # ```rbi
37
37
  # AppSettings = T.let(T.unsafe(nil), AppSettingsConfigOptions)
38
38
  #
@@ -44,13 +44,15 @@ module Tapioca
44
44
  # def github=(value); end
45
45
  # end
46
46
  # ```
47
- class Config < Base
47
+ class Config < Compiler
48
48
  extend T::Sig
49
49
 
50
50
  CONFIG_OPTIONS_SUFFIX = "ConfigOptions"
51
51
 
52
- sig { override.params(root: RBI::Tree, constant: Module).void }
53
- def decorate(root, constant)
52
+ ConstantType = type_member { { fixed: Module } }
53
+
54
+ sig { override.void }
55
+ def decorate
54
56
  # The constant we are given is the specialized config options type
55
57
  option_class_name = constant.name
56
58
  return unless option_class_name
@@ -75,7 +77,7 @@ module Tapioca
75
77
  # enumerates the entries, we don't make any assumptions about their
76
78
  # types.
77
79
  mod.create_extend("T::Generic")
78
- mod.create_type_member("Elem", value: "type_member(fixed: T.untyped)")
80
+ mod.create_type_variable("Elem", type: "type_member", fixed: "T.untyped")
79
81
 
80
82
  method_names.each do |method_name|
81
83
  # Create getter method
@@ -95,7 +97,7 @@ module Tapioca
95
97
  end
96
98
 
97
99
  sig { override.returns(T::Enumerable[Module]) }
98
- def gather_constants
100
+ def self.gather_constants
99
101
  name = ::Config.const_name
100
102
  return [] unless Object.const_defined?(name)
101
103
 
@@ -8,9 +8,9 @@ rescue LoadError
8
8
  end
9
9
 
10
10
  module Tapioca
11
- module Compilers
12
- module Dsl
13
- # `Tapioca::Compilers::Dsl::FrozenRecord` generates RBI files for subclasses of
11
+ module Dsl
12
+ module Compilers
13
+ # `Tapioca::Dsl::Compilers::FrozenRecord` generates RBI files for subclasses of
14
14
  # [`FrozenRecord::Base`](https://github.com/byroot/frozen_record).
15
15
  #
16
16
  # For example, with the following FrozenRecord class:
@@ -33,7 +33,7 @@ module Tapioca
33
33
  # last_name: Lord
34
34
  # ~~~
35
35
  #
36
- # this generator will produce the RBI file `student.rbi` with the following content:
36
+ # this compiler will produce the RBI file `student.rbi` with the following content:
37
37
  #
38
38
  # ~~~rbi
39
39
  # # Student.rbi
@@ -62,11 +62,13 @@ module Tapioca
62
62
  # end
63
63
  # end
64
64
  # ~~~
65
- class FrozenRecord < Base
65
+ class FrozenRecord < Compiler
66
66
  extend T::Sig
67
67
 
68
- sig { override.params(root: RBI::Tree, constant: T.class_of(::FrozenRecord::Base)).void }
69
- def decorate(root, constant)
68
+ ConstantType = type_member { { fixed: T.class_of(::FrozenRecord::Base) } }
69
+
70
+ sig { override.void }
71
+ def decorate
70
72
  attributes = constant.attributes
71
73
  return if attributes.empty?
72
74
 
@@ -82,19 +84,19 @@ module Tapioca
82
84
 
83
85
  record.create_include(module_name)
84
86
 
85
- decorate_scopes(constant, record)
87
+ decorate_scopes(record)
86
88
  end
87
89
  end
88
90
 
89
91
  sig { override.returns(T::Enumerable[Module]) }
90
- def gather_constants
92
+ def self.gather_constants
91
93
  descendants_of(::FrozenRecord::Base).reject(&:abstract_class?)
92
94
  end
93
95
 
94
96
  private
95
97
 
96
- sig { params(constant: T.class_of(::FrozenRecord::Base), record: RBI::Scope).void }
97
- def decorate_scopes(constant, record)
98
+ sig { params(record: RBI::Scope).void }
99
+ def decorate_scopes(record)
98
100
  scopes = T.unsafe(constant).__tapioca_scope_names
99
101
  return if scopes.nil?
100
102
 
@@ -5,14 +5,16 @@ begin
5
5
  require "identity_cache"
6
6
  rescue LoadError
7
7
  # means IdentityCache is not installed,
8
- # so let's not even define the generator.
8
+ # so let's not even define the compiler.
9
9
  return
10
10
  end
11
11
 
12
+ require "tapioca/dsl/helpers/active_record_column_type_helper"
13
+
12
14
  module Tapioca
13
- module Compilers
14
- module Dsl
15
- # `Tapioca::Compilers::DSL::IdentityCache` generates RBI files for Active Record models
15
+ module Dsl
16
+ module Compilers
17
+ # `Tapioca::Dsl::Compilers::IdentityCache` generates RBI files for Active Record models
16
18
  # that use `include IdentityCache`.
17
19
  # [`IdentityCache`](https://github.com/Shopify/identity_cache) is a blob level caching solution
18
20
  # to plug into Active Record.
@@ -31,7 +33,7 @@ module Tapioca
31
33
  # end
32
34
  # ~~~
33
35
  #
34
- # this generator will produce the RBI file `post.rbi` with the following content:
36
+ # this compiler will produce the RBI file `post.rbi` with the following content:
35
37
  #
36
38
  # ~~~rbi
37
39
  # # post.rbi
@@ -59,7 +61,7 @@ module Tapioca
59
61
  # def fetch_by_title_and_review_date(title, review_date, includes: nil); end
60
62
  # end
61
63
  # ~~~
62
- class IdentityCache < Base
64
+ class IdentityCache < Compiler
63
65
  extend T::Sig
64
66
 
65
67
  COLLECTION_TYPE = T.let(
@@ -67,8 +69,10 @@ module Tapioca
67
69
  T.proc.params(type: T.any(Module, String)).returns(String)
68
70
  )
69
71
 
70
- sig { override.params(root: RBI::Tree, constant: T.class_of(::ActiveRecord::Base)).void }
71
- def decorate(root, constant)
72
+ ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
73
+
74
+ sig { override.void }
75
+ def decorate
72
76
  caches = constant.send(:all_cached_associations)
73
77
  cache_indexes = constant.send(:cache_indexes)
74
78
  return if caches.empty? && cache_indexes.empty?
@@ -79,7 +83,7 @@ module Tapioca
79
83
  cache_belongs = constant.send(:cached_belongs_tos)
80
84
 
81
85
  cache_indexes.each do |field|
82
- create_fetch_by_methods(field, model, constant)
86
+ create_fetch_by_methods(field, model)
83
87
  end
84
88
 
85
89
  cache_manys.values.each do |field|
@@ -97,7 +101,7 @@ module Tapioca
97
101
  end
98
102
 
99
103
  sig { override.returns(T::Enumerable[Module]) }
100
- def gather_constants
104
+ def self.gather_constants
101
105
  descendants_of(::ActiveRecord::Base).select do |klass|
102
106
  klass < ::IdentityCache::WithoutPrimaryIndex
103
107
  end
@@ -144,28 +148,26 @@ module Tapioca
144
148
  sig do
145
149
  params(
146
150
  field: T.untyped,
147
- klass: RBI::Scope,
148
- constant: T.class_of(::ActiveRecord::Base),
151
+ klass: RBI::Scope
149
152
  ).void
150
153
  end
151
- def create_fetch_by_methods(field, klass, constant)
154
+ def create_fetch_by_methods(field, klass)
152
155
  is_cache_index = field.instance_variable_defined?(:@attribute_proc)
153
156
 
154
157
  # Both `cache_index` and `cache_attribute` generate aliased methods
155
- create_aliased_fetch_by_methods(field, klass, constant)
158
+ create_aliased_fetch_by_methods(field, klass)
156
159
 
157
160
  # If the method used was `cache_index` a few extra methods are created
158
- create_index_fetch_by_methods(field, klass, constant) if is_cache_index
161
+ create_index_fetch_by_methods(field, klass) if is_cache_index
159
162
  end
160
163
 
161
164
  sig do
162
165
  params(
163
166
  field: T.untyped,
164
- klass: RBI::Scope,
165
- constant: T.class_of(::ActiveRecord::Base),
167
+ klass: RBI::Scope
166
168
  ).void
167
169
  end
168
- def create_index_fetch_by_methods(field, klass, constant)
170
+ def create_index_fetch_by_methods(field, klass)
169
171
  field_length = field.key_fields.length
170
172
  fields_name = field.key_fields.join("_and_")
171
173
  name = "fetch_by_#{fields_name}"
@@ -215,12 +217,11 @@ module Tapioca
215
217
  sig do
216
218
  params(
217
219
  field: T.untyped,
218
- klass: RBI::Scope,
219
- constant: T.class_of(::ActiveRecord::Base),
220
+ klass: RBI::Scope
220
221
  ).void
221
222
  end
222
- def create_aliased_fetch_by_methods(field, klass, constant)
223
- type, _ = ActiveRecordColumnTypeHelper.new(constant).type_for(field.alias_name.to_s)
223
+ def create_aliased_fetch_by_methods(field, klass)
224
+ type, _ = Helpers::ActiveRecordColumnTypeHelper.new(constant).type_for(field.alias_name.to_s)
224
225
  multi_type = type.delete_prefix("T.nilable(").delete_suffix(")").delete_prefix("::")
225
226
  length = field.key_fields.length
226
227
  suffix = field.send(:fetch_method_suffix)