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.
- checksums.yaml +4 -4
- data/Gemfile +8 -2
- data/README.md +27 -15
- data/Rakefile +10 -14
- data/lib/tapioca/cli.rb +65 -80
- data/lib/tapioca/{generators/base.rb → commands/command.rb} +16 -9
- data/lib/tapioca/{generators → commands}/dsl.rb +59 -45
- data/lib/tapioca/{generators → commands}/gem.rb +93 -30
- data/lib/tapioca/{generators → commands}/init.rb +9 -13
- data/lib/tapioca/{generators → commands}/require.rb +8 -10
- data/lib/tapioca/commands/todo.rb +86 -0
- data/lib/tapioca/commands.rb +13 -0
- data/lib/tapioca/dsl/compiler.rb +185 -0
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/aasm.rb +12 -9
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/action_controller_helpers.rb +13 -20
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/action_mailer.rb +10 -8
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_job.rb +11 -9
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_model_attributes.rb +13 -11
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_model_secure_password.rb +10 -12
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_associations.rb +28 -34
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_columns.rb +18 -16
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_enum.rb +14 -12
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_fixtures.rb +12 -8
- data/lib/tapioca/dsl/compilers/active_record_relations.rb +712 -0
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_scope.rb +21 -20
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_typed_store.rb +11 -16
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_resource.rb +10 -8
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_storage.rb +14 -10
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_support_concern.rb +19 -14
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_support_current_attributes.rb +16 -21
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/config.rb +11 -9
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/frozen_record.rb +13 -11
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/identity_cache.rb +23 -22
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/mixed_in_class_attributes.rb +12 -10
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/protobuf.rb +22 -10
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/rails_generators.rb +12 -13
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/sidekiq_worker.rb +14 -13
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/smart_properties.rb +11 -9
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/state_machines.rb +12 -10
- data/lib/tapioca/{compilers/dsl → dsl/compilers}/url_helpers.rb +20 -15
- data/lib/tapioca/dsl/compilers.rb +31 -0
- data/lib/tapioca/{compilers/dsl → dsl}/extensions/frozen_record.rb +2 -2
- data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +114 -0
- data/lib/tapioca/dsl/helpers/active_record_constants_helper.rb +29 -0
- data/lib/tapioca/{compilers/dsl → dsl/helpers}/param_helper.rb +6 -3
- data/lib/tapioca/dsl/pipeline.rb +169 -0
- data/lib/tapioca/gem/events.rb +120 -0
- data/lib/tapioca/gem/listeners/base.rb +48 -0
- data/lib/tapioca/gem/listeners/dynamic_mixins.rb +32 -0
- data/lib/tapioca/gem/listeners/methods.rb +183 -0
- data/lib/tapioca/gem/listeners/mixins.rb +101 -0
- data/lib/tapioca/gem/listeners/remove_empty_payload_scopes.rb +21 -0
- data/lib/tapioca/gem/listeners/sorbet_enums.rb +26 -0
- data/lib/tapioca/gem/listeners/sorbet_helpers.rb +29 -0
- data/lib/tapioca/gem/listeners/sorbet_props.rb +33 -0
- data/lib/tapioca/gem/listeners/sorbet_required_ancestors.rb +23 -0
- data/lib/tapioca/gem/listeners/sorbet_signatures.rb +79 -0
- data/lib/tapioca/gem/listeners/sorbet_type_variables.rb +51 -0
- data/lib/tapioca/gem/listeners/subconstants.rb +37 -0
- data/lib/tapioca/gem/listeners/yard_doc.rb +96 -0
- data/lib/tapioca/gem/listeners.rb +16 -0
- data/lib/tapioca/gem/pipeline.rb +365 -0
- data/lib/tapioca/helpers/cli_helper.rb +7 -0
- data/lib/tapioca/helpers/config_helper.rb +5 -8
- data/lib/tapioca/helpers/shims_helper.rb +87 -0
- data/lib/tapioca/helpers/signatures_helper.rb +17 -0
- data/lib/tapioca/helpers/sorbet_helper.rb +57 -0
- data/lib/tapioca/helpers/test/dsl_compiler.rb +118 -0
- data/lib/tapioca/helpers/test/isolation.rb +1 -1
- data/lib/tapioca/helpers/test/template.rb +13 -2
- data/lib/tapioca/helpers/type_variable_helper.rb +43 -0
- data/lib/tapioca/internal.rb +18 -10
- data/lib/tapioca/rbi_ext/model.rb +14 -50
- data/lib/tapioca/rbi_formatter.rb +37 -0
- data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +227 -0
- data/lib/tapioca/runtime/generic_type_registry.rb +168 -0
- data/lib/tapioca/runtime/loader.rb +123 -0
- data/lib/tapioca/runtime/reflection.rb +157 -0
- data/lib/tapioca/runtime/trackers/autoload.rb +72 -0
- data/lib/tapioca/runtime/trackers/constant_definition.rb +44 -0
- data/lib/tapioca/runtime/trackers/mixin.rb +80 -0
- data/lib/tapioca/runtime/trackers/required_ancestor.rb +50 -0
- data/lib/tapioca/{trackers.rb → runtime/trackers.rb} +4 -3
- data/lib/tapioca/sorbet_ext/generic_name_patch.rb +69 -34
- data/lib/tapioca/sorbet_ext/name_patch.rb +7 -1
- data/lib/tapioca/{compilers → static}/requires_compiler.rb +2 -2
- data/lib/tapioca/static/symbol_loader.rb +83 -0
- data/lib/tapioca/static/symbol_table_parser.rb +63 -0
- data/lib/tapioca/version.rb +1 -1
- data/lib/tapioca.rb +2 -7
- metadata +83 -62
- data/lib/tapioca/compilers/dsl/active_record_relations.rb +0 -720
- data/lib/tapioca/compilers/dsl/base.rb +0 -195
- data/lib/tapioca/compilers/dsl/helper/active_record_constants.rb +0 -27
- data/lib/tapioca/compilers/dsl_compiler.rb +0 -134
- data/lib/tapioca/compilers/dynamic_mixin_compiler.rb +0 -223
- data/lib/tapioca/compilers/sorbet.rb +0 -59
- data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +0 -780
- data/lib/tapioca/compilers/symbol_table/symbol_loader.rb +0 -90
- data/lib/tapioca/compilers/symbol_table_compiler.rb +0 -17
- data/lib/tapioca/compilers/todos_compiler.rb +0 -32
- data/lib/tapioca/generators/todo.rb +0 -76
- data/lib/tapioca/generators.rb +0 -9
- data/lib/tapioca/generic_type_registry.rb +0 -164
- data/lib/tapioca/helpers/active_record_column_type_helper.rb +0 -108
- data/lib/tapioca/loader.rb +0 -119
- data/lib/tapioca/reflection.rb +0 -151
- data/lib/tapioca/trackers/autoload.rb +0 -70
- data/lib/tapioca/trackers/constant_definition.rb +0 -42
- 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/
|
|
10
|
+
require "tapioca/dsl/helpers/active_record_constants_helper"
|
|
11
11
|
|
|
12
12
|
module Tapioca
|
|
13
|
-
module
|
|
14
|
-
module
|
|
15
|
-
# `Tapioca::Compilers::
|
|
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
|
|
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 <
|
|
45
|
+
class ActiveRecordScope < Compiler
|
|
46
46
|
extend T::Sig
|
|
47
|
-
include
|
|
47
|
+
include Helpers::ActiveRecordConstantsHelper
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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 =
|
|
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 {
|
|
94
|
-
def scope_method_names
|
|
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(
|
|
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
|
|
8
|
+
# so let's not even define the compiler.
|
|
9
9
|
return
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
module Tapioca
|
|
13
|
-
module
|
|
14
|
-
module
|
|
15
|
-
# `Tapioca::Compilers::
|
|
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
|
|
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 <
|
|
90
|
+
class ActiveRecordTypedStore < Compiler
|
|
91
91
|
extend T::Sig
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
|
12
|
-
module
|
|
13
|
-
# `Tapioca::Compilers::
|
|
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
|
|
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 <
|
|
61
|
+
class ActiveResource < Compiler
|
|
62
62
|
extend T::Sig
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
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
|
|
13
|
-
module
|
|
14
|
-
# `Tapioca::Compilers::
|
|
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
|
|
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 <
|
|
46
|
+
class ActiveStorage < Compiler
|
|
47
47
|
extend T::Sig
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
ConstantType = type_member do
|
|
50
|
+
{
|
|
51
|
+
fixed: T.all(Module,
|
|
52
|
+
::ActiveStorage::Reflection::ActiveRecordExtensions::ClassMethods),
|
|
53
|
+
}
|
|
52
54
|
end
|
|
53
|
-
|
|
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
|
|
14
|
-
module
|
|
15
|
-
# `Tapioca::Compilers::
|
|
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
|
|
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 <
|
|
44
|
+
class ActiveSupportConcern < Compiler
|
|
47
45
|
extend T::Sig
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
93
|
+
self.class.dependencies_of(concern)
|
|
89
94
|
end
|
|
90
95
|
|
|
91
96
|
sig { params(concern: Module).returns(T::Array[Module]) }
|
|
92
|
-
def
|
|
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
|
-
|
|
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
|
|
14
|
-
module
|
|
15
|
-
# `Tapioca::Compilers::
|
|
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
|
|
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 <
|
|
62
|
+
class ActiveSupportCurrentAttributes < Compiler
|
|
63
63
|
extend T::Sig
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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 {
|
|
104
|
-
def
|
|
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 {
|
|
109
|
-
def
|
|
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
|
|
12
|
-
module
|
|
13
|
-
# `Tapioca::Compilers::
|
|
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
|
|
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 <
|
|
47
|
+
class Config < Compiler
|
|
48
48
|
extend T::Sig
|
|
49
49
|
|
|
50
50
|
CONFIG_OPTIONS_SUFFIX = "ConfigOptions"
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
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.
|
|
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
|
|
12
|
-
module
|
|
13
|
-
# `Tapioca::Compilers::
|
|
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
|
|
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 <
|
|
65
|
+
class FrozenRecord < Compiler
|
|
66
66
|
extend T::Sig
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
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(
|
|
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(
|
|
97
|
-
def decorate_scopes(
|
|
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
|
|
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
|
|
14
|
-
module
|
|
15
|
-
# `Tapioca::Compilers::
|
|
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
|
|
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 <
|
|
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
|
-
|
|
71
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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)
|