tapioca 0.9.4 → 0.10.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.
- checksums.yaml +4 -4
- data/LICENSE.txt +21 -0
- data/README.md +48 -22
- data/lib/tapioca/cli.rb +17 -23
- data/lib/tapioca/commands/annotations.rb +2 -2
- data/lib/tapioca/commands/dsl.rb +43 -65
- data/lib/tapioca/commands/gem.rb +18 -50
- data/lib/tapioca/commands/todo.rb +1 -2
- data/lib/tapioca/dsl/compiler.rb +34 -37
- data/lib/tapioca/dsl/compilers/aasm.rb +7 -3
- data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +7 -3
- data/lib/tapioca/dsl/compilers/action_mailer.rb +7 -3
- data/lib/tapioca/dsl/compilers/active_job.rb +7 -3
- data/lib/tapioca/dsl/compilers/active_model_attributes.rb +9 -5
- data/lib/tapioca/dsl/compilers/active_model_secure_password.rb +11 -7
- data/lib/tapioca/dsl/compilers/active_record_associations.rb +7 -3
- data/lib/tapioca/dsl/compilers/active_record_columns.rb +7 -3
- data/lib/tapioca/dsl/compilers/active_record_enum.rb +7 -3
- data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +8 -4
- data/lib/tapioca/dsl/compilers/active_record_relations.rb +7 -3
- data/lib/tapioca/dsl/compilers/active_record_scope.rb +5 -3
- data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +8 -4
- data/lib/tapioca/dsl/compilers/active_resource.rb +7 -3
- data/lib/tapioca/dsl/compilers/active_storage.rb +9 -5
- data/lib/tapioca/dsl/compilers/active_support_concern.rb +21 -18
- data/lib/tapioca/dsl/compilers/active_support_current_attributes.rb +7 -3
- data/lib/tapioca/dsl/compilers/config.rb +12 -8
- data/lib/tapioca/dsl/compilers/frozen_record.rb +7 -3
- data/lib/tapioca/dsl/compilers/graphql_input_object.rb +71 -0
- data/lib/tapioca/dsl/compilers/graphql_mutation.rb +81 -0
- data/lib/tapioca/dsl/compilers/identity_cache.rb +8 -4
- data/lib/tapioca/dsl/compilers/mixed_in_class_attributes.rb +9 -5
- data/lib/tapioca/dsl/compilers/protobuf.rb +69 -25
- data/lib/tapioca/dsl/compilers/rails_generators.rb +12 -8
- data/lib/tapioca/dsl/compilers/sidekiq_worker.rb +7 -3
- data/lib/tapioca/dsl/compilers/smart_properties.rb +10 -6
- data/lib/tapioca/dsl/compilers/state_machines.rb +7 -3
- data/lib/tapioca/dsl/compilers/url_helpers.rb +29 -26
- data/lib/tapioca/dsl/compilers.rb +0 -5
- data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +1 -9
- data/lib/tapioca/dsl/helpers/graphql_type_helper.rb +62 -0
- data/lib/tapioca/dsl/pipeline.rb +19 -11
- data/lib/tapioca/gem/listeners/source_location.rb +16 -9
- data/lib/tapioca/gemfile.rb +30 -0
- data/lib/tapioca/helpers/config_helper.rb +2 -2
- data/lib/tapioca/helpers/rbi_helper.rb +43 -30
- data/lib/tapioca/helpers/source_uri.rb +77 -0
- data/lib/tapioca/helpers/test/dsl_compiler.rb +1 -1
- data/lib/tapioca/helpers/test/isolation.rb +7 -3
- data/lib/tapioca/internal.rb +5 -1
- data/lib/tapioca/loaders/dsl.rb +84 -0
- data/lib/tapioca/loaders/gem.rb +85 -0
- data/lib/tapioca/{runtime → loaders}/loader.rb +39 -31
- data/lib/tapioca/repo_index.rb +12 -8
- data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +2 -2
- data/lib/tapioca/runtime/trackers/constant_definition.rb +15 -13
- data/lib/tapioca/runtime/trackers/mixin.rb +35 -31
- data/lib/tapioca/runtime/trackers/required_ancestor.rb +21 -19
- data/lib/tapioca/static/requires_compiler.rb +2 -3
- data/lib/tapioca/static/symbol_table_parser.rb +19 -17
- data/lib/tapioca/version.rb +1 -1
- data/lib/tapioca.rb +24 -20
- metadata +10 -5
- data/Gemfile +0 -53
- data/Rakefile +0 -18
data/lib/tapioca/dsl/compiler.rb
CHANGED
@@ -22,6 +22,40 @@ module Tapioca
|
|
22
22
|
sig { returns(RBI::Tree) }
|
23
23
|
attr_reader :root
|
24
24
|
|
25
|
+
class << self
|
26
|
+
extend T::Sig
|
27
|
+
|
28
|
+
sig { params(constant: Module).returns(T::Boolean) }
|
29
|
+
def handles?(constant)
|
30
|
+
processable_constants.include?(constant)
|
31
|
+
end
|
32
|
+
|
33
|
+
sig { abstract.returns(T::Enumerable[Module]) }
|
34
|
+
def gather_constants; end
|
35
|
+
|
36
|
+
sig { returns(T::Set[Module]) }
|
37
|
+
def processable_constants
|
38
|
+
@processable_constants ||= T.let(
|
39
|
+
T::Set[Module].new(gather_constants).compare_by_identity,
|
40
|
+
T.nilable(T::Set[Module])
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
sig { returns(T::Enumerable[Class]) }
|
47
|
+
def all_classes
|
48
|
+
@all_classes = T.let(@all_classes, T.nilable(T::Enumerable[Class]))
|
49
|
+
@all_classes ||= T.cast(ObjectSpace.each_object(Class), T::Enumerable[Class]).each
|
50
|
+
end
|
51
|
+
|
52
|
+
sig { returns(T::Enumerable[Module]) }
|
53
|
+
def all_modules
|
54
|
+
@all_modules = T.let(@all_modules, T.nilable(T::Enumerable[Module]))
|
55
|
+
@all_modules ||= T.cast(ObjectSpace.each_object(Module), T::Enumerable[Module]).each
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
25
59
|
sig { params(pipeline: Tapioca::Dsl::Pipeline, root: RBI::Tree, constant: ConstantType).void }
|
26
60
|
def initialize(pipeline, root, constant)
|
27
61
|
@pipeline = pipeline
|
@@ -30,11 +64,6 @@ module Tapioca
|
|
30
64
|
@errors = T.let([], T::Array[String])
|
31
65
|
end
|
32
66
|
|
33
|
-
sig { params(constant: Module).returns(T::Boolean) }
|
34
|
-
def self.handles?(constant)
|
35
|
-
processable_constants.include?(constant)
|
36
|
-
end
|
37
|
-
|
38
67
|
sig { params(compiler_name: String).returns(T::Boolean) }
|
39
68
|
def compiler_enabled?(compiler_name)
|
40
69
|
@pipeline.compiler_enabled?(compiler_name)
|
@@ -43,17 +72,6 @@ module Tapioca
|
|
43
72
|
sig { abstract.void }
|
44
73
|
def decorate; end
|
45
74
|
|
46
|
-
sig { abstract.returns(T::Enumerable[Module]) }
|
47
|
-
def self.gather_constants; end
|
48
|
-
|
49
|
-
sig { returns(T::Set[Module]) }
|
50
|
-
def self.processable_constants
|
51
|
-
@processable_constants ||= T.let(
|
52
|
-
T::Set[Module].new(gather_constants).compare_by_identity,
|
53
|
-
T.nilable(T::Set[Module])
|
54
|
-
)
|
55
|
-
end
|
56
|
-
|
57
75
|
# NOTE: This should eventually accept an `Error` object or `Exception` rather than simply a `String`.
|
58
76
|
sig { params(error: String).void }
|
59
77
|
def add_error(error)
|
@@ -62,18 +80,6 @@ module Tapioca
|
|
62
80
|
|
63
81
|
private
|
64
82
|
|
65
|
-
sig { returns(T::Enumerable[Class]) }
|
66
|
-
private_class_method def self.all_classes
|
67
|
-
@all_classes = T.let(@all_classes, T.nilable(T::Enumerable[Class]))
|
68
|
-
@all_classes ||= T.cast(ObjectSpace.each_object(Class), T::Enumerable[Class]).each
|
69
|
-
end
|
70
|
-
|
71
|
-
sig { returns(T::Enumerable[Module]) }
|
72
|
-
private_class_method def self.all_modules
|
73
|
-
@all_modules = T.let(@all_modules, T.nilable(T::Enumerable[Module]))
|
74
|
-
@all_modules ||= T.cast(ObjectSpace.each_object(Module), T::Enumerable[Module]).each
|
75
|
-
end
|
76
|
-
|
77
83
|
# Get the types of each parameter from a method signature
|
78
84
|
sig do
|
79
85
|
params(
|
@@ -158,15 +164,6 @@ module Tapioca
|
|
158
164
|
return_type = "T.untyped" if return_type == "<NOT-TYPED>"
|
159
165
|
return_type
|
160
166
|
end
|
161
|
-
|
162
|
-
sig { params(type: String).returns(String) }
|
163
|
-
def as_nilable_type(type)
|
164
|
-
if type.start_with?("T.nilable(", "::T.nilable(") || type == "T.untyped" || type == "::T.untyped"
|
165
|
-
type
|
166
|
-
else
|
167
|
-
"T.nilable(#{type})"
|
168
|
-
end
|
169
|
-
end
|
170
167
|
end
|
171
168
|
end
|
172
169
|
end
|
@@ -115,9 +115,13 @@ module Tapioca
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
118
|
-
|
119
|
-
|
120
|
-
|
118
|
+
class << self
|
119
|
+
extend T::Sig
|
120
|
+
|
121
|
+
sig { override.returns(T::Enumerable[Module]) }
|
122
|
+
def gather_constants
|
123
|
+
T.cast(ObjectSpace.each_object(::AASM::ClassMethods), T::Enumerable[Module])
|
124
|
+
end
|
121
125
|
end
|
122
126
|
end
|
123
127
|
end
|
@@ -121,9 +121,13 @@ module Tapioca
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
|
-
|
125
|
-
|
126
|
-
|
124
|
+
class << self
|
125
|
+
extend T::Sig
|
126
|
+
|
127
|
+
sig { override.returns(T::Enumerable[Module]) }
|
128
|
+
def gather_constants
|
129
|
+
descendants_of(::ActionController::Base).reject(&:abstract?).select(&:name)
|
130
|
+
end
|
127
131
|
end
|
128
132
|
|
129
133
|
private
|
@@ -54,9 +54,13 @@ module Tapioca
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
class << self
|
58
|
+
extend T::Sig
|
59
|
+
|
60
|
+
sig { override.returns(T::Enumerable[Module]) }
|
61
|
+
def gather_constants
|
62
|
+
descendants_of(::ActionMailer::Base).reject(&:abstract?)
|
63
|
+
end
|
60
64
|
end
|
61
65
|
end
|
62
66
|
end
|
@@ -67,9 +67,13 @@ module Tapioca
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
70
|
+
class << self
|
71
|
+
extend T::Sig
|
72
|
+
|
73
|
+
sig { override.returns(T::Enumerable[Module]) }
|
74
|
+
def gather_constants
|
75
|
+
descendants_of(::ActiveJob::Base)
|
76
|
+
end
|
73
77
|
end
|
74
78
|
end
|
75
79
|
end
|
@@ -53,9 +53,13 @@ module Tapioca
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
class << self
|
57
|
+
extend T::Sig
|
58
|
+
|
59
|
+
sig { override.returns(T::Enumerable[Module]) }
|
60
|
+
def gather_constants
|
61
|
+
all_classes.grep(::ActiveModel::Attributes::ClassMethods)
|
62
|
+
end
|
59
63
|
end
|
60
64
|
|
61
65
|
private
|
@@ -71,11 +75,11 @@ module Tapioca
|
|
71
75
|
constant.attribute_method_matchers
|
72
76
|
end
|
73
77
|
patterns.flat_map do |pattern|
|
74
|
-
constant.attribute_types.
|
78
|
+
constant.attribute_types.filter_map do |name, value|
|
75
79
|
next unless handle_method_pattern?(pattern)
|
76
80
|
|
77
81
|
[pattern.method_name(name), type_for(value)]
|
78
|
-
end
|
82
|
+
end
|
79
83
|
end
|
80
84
|
end
|
81
85
|
|
@@ -85,13 +85,17 @@ module Tapioca
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
88
|
+
class << self
|
89
|
+
extend T::Sig
|
90
|
+
|
91
|
+
sig { override.returns(T::Enumerable[Module]) }
|
92
|
+
def gather_constants
|
93
|
+
# This selects all classes that are `ActiveModel::SecurePassword::ClassMethods === klass`.
|
94
|
+
# In other words, we select all classes that have `ActiveModel::SecurePassword::ClassMethods`
|
95
|
+
# as an ancestor of its singleton class, i.e. all classes that have extended the
|
96
|
+
# `ActiveModel::SecurePassword::ClassMethods` module.
|
97
|
+
all_classes.grep(::ActiveModel::SecurePassword::ClassMethods)
|
98
|
+
end
|
95
99
|
end
|
96
100
|
end
|
97
101
|
end
|
@@ -135,9 +135,13 @@ module Tapioca
|
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
|
-
|
139
|
-
|
140
|
-
|
138
|
+
class << self
|
139
|
+
extend T::Sig
|
140
|
+
|
141
|
+
sig { override.returns(T::Enumerable[Module]) }
|
142
|
+
def gather_constants
|
143
|
+
descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
|
144
|
+
end
|
141
145
|
end
|
142
146
|
|
143
147
|
private
|
@@ -135,9 +135,13 @@ module Tapioca
|
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
|
-
|
139
|
-
|
140
|
-
|
138
|
+
class << self
|
139
|
+
extend T::Sig
|
140
|
+
|
141
|
+
sig { override.returns(T::Enumerable[Module]) }
|
142
|
+
def gather_constants
|
143
|
+
descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
|
144
|
+
end
|
141
145
|
end
|
142
146
|
|
143
147
|
private
|
@@ -80,9 +80,13 @@ module Tapioca
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
-
|
84
|
-
|
85
|
-
|
83
|
+
class << self
|
84
|
+
extend T::Sig
|
85
|
+
|
86
|
+
sig { override.returns(T::Enumerable[Module]) }
|
87
|
+
def gather_constants
|
88
|
+
descendants_of(::ActiveRecord::Base)
|
89
|
+
end
|
86
90
|
end
|
87
91
|
|
88
92
|
private
|
@@ -57,11 +57,15 @@ module Tapioca
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
return [] unless Rails.application
|
60
|
+
class << self
|
61
|
+
extend T::Sig
|
63
62
|
|
64
|
-
[
|
63
|
+
sig { override.returns(T::Enumerable[Module]) }
|
64
|
+
def gather_constants
|
65
|
+
return [] unless Rails.application
|
66
|
+
|
67
|
+
[ActiveSupport::TestCase]
|
68
|
+
end
|
65
69
|
end
|
66
70
|
|
67
71
|
private
|
@@ -166,9 +166,13 @@ module Tapioca
|
|
166
166
|
end
|
167
167
|
end
|
168
168
|
|
169
|
-
|
170
|
-
|
171
|
-
|
169
|
+
class << self
|
170
|
+
extend T::Sig
|
171
|
+
|
172
|
+
sig { override.returns(T::Enumerable[Module]) }
|
173
|
+
def gather_constants
|
174
|
+
ActiveRecord::Base.descendants.reject(&:abstract_class?)
|
175
|
+
end
|
172
176
|
end
|
173
177
|
|
174
178
|
ASSOCIATION_METHODS = T.let(
|
@@ -80,9 +80,11 @@ module Tapioca
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
-
|
84
|
-
|
85
|
-
|
83
|
+
class << self
|
84
|
+
sig { override.returns(T::Enumerable[Module]) }
|
85
|
+
def gather_constants
|
86
|
+
descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
|
87
|
+
end
|
86
88
|
end
|
87
89
|
|
88
90
|
private
|
@@ -113,10 +113,14 @@ module Tapioca
|
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
116
|
+
class << self
|
117
|
+
extend T::Sig
|
118
|
+
|
119
|
+
sig { override.returns(T::Enumerable[Module]) }
|
120
|
+
def gather_constants
|
121
|
+
descendants_of(::ActiveRecord::Base).select do |klass|
|
122
|
+
klass.include?(ActiveRecord::TypedStore::Behavior)
|
123
|
+
end
|
120
124
|
end
|
121
125
|
end
|
122
126
|
|
@@ -74,9 +74,13 @@ module Tapioca
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
class << self
|
78
|
+
extend T::Sig
|
79
|
+
|
80
|
+
sig { override.returns(T::Enumerable[Module]) }
|
81
|
+
def gather_constants
|
82
|
+
descendants_of(::ActiveResource::Base)
|
83
|
+
end
|
80
84
|
end
|
81
85
|
|
82
86
|
private
|
@@ -74,11 +74,15 @@ module Tapioca
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
77
|
+
class << self
|
78
|
+
extend T::Sig
|
79
|
+
|
80
|
+
sig { override.returns(T::Enumerable[Module]) }
|
81
|
+
def gather_constants
|
82
|
+
descendants_of(::ActiveRecord::Base)
|
83
|
+
.reject(&:abstract_class?)
|
84
|
+
.grep(::ActiveStorage::Reflection::ActiveRecordExtensions::ClassMethods)
|
85
|
+
end
|
82
86
|
end
|
83
87
|
|
84
88
|
private
|
@@ -52,10 +52,9 @@ module Tapioca
|
|
52
52
|
|
53
53
|
mixed_in_class_methods = dependencies
|
54
54
|
.uniq # Deduplicate
|
55
|
-
.
|
55
|
+
.filter_map do |concern| # Map to class methods module name, if exists
|
56
56
|
"#{qualified_name_of(concern)}::ClassMethods" if concern.const_defined?(:ClassMethods)
|
57
57
|
end
|
58
|
-
.compact # Remove non-existent records
|
59
58
|
|
60
59
|
return if mixed_in_class_methods.empty?
|
61
60
|
|
@@ -66,24 +65,28 @@ module Tapioca
|
|
66
65
|
end
|
67
66
|
end
|
68
67
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
68
|
+
class << self
|
69
|
+
extend T::Sig
|
70
|
+
|
71
|
+
sig { override.returns(T::Enumerable[Module]) }
|
72
|
+
def gather_constants
|
73
|
+
# Find all Modules that are:
|
74
|
+
all_modules.select do |mod|
|
75
|
+
# named (i.e. not anonymous)
|
76
|
+
name_of(mod) &&
|
77
|
+
# not singleton classes
|
78
|
+
!mod.singleton_class? &&
|
79
|
+
# extend ActiveSupport::Concern, and
|
80
|
+
mod.singleton_class < ActiveSupport::Concern &&
|
81
|
+
# have dependencies (i.e. include another concern)
|
82
|
+
!dependencies_of(mod).empty?
|
83
|
+
end
|
81
84
|
end
|
82
|
-
end
|
83
85
|
|
84
|
-
|
85
|
-
|
86
|
-
|
86
|
+
sig { params(concern: Module).returns(T::Array[Module]) }
|
87
|
+
def dependencies_of(concern)
|
88
|
+
concern.instance_variable_get(:@_dependencies)
|
89
|
+
end
|
87
90
|
end
|
88
91
|
|
89
92
|
private
|
@@ -88,9 +88,13 @@ module Tapioca
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
-
|
92
|
-
|
93
|
-
|
91
|
+
class << self
|
92
|
+
extend T::Sig
|
93
|
+
|
94
|
+
sig { override.returns(T::Enumerable[Module]) }
|
95
|
+
def gather_constants
|
96
|
+
descendants_of(::ActiveSupport::CurrentAttributes)
|
97
|
+
end
|
94
98
|
end
|
95
99
|
|
96
100
|
private
|
@@ -96,16 +96,20 @@ module Tapioca
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
-
|
100
|
-
|
101
|
-
name = ::Config.const_name
|
102
|
-
return [] unless Object.const_defined?(name)
|
99
|
+
class << self
|
100
|
+
extend T::Sig
|
103
101
|
|
104
|
-
|
105
|
-
|
106
|
-
|
102
|
+
sig { override.returns(T::Enumerable[Module]) }
|
103
|
+
def gather_constants
|
104
|
+
name = ::Config.const_name
|
105
|
+
return [] unless Object.const_defined?(name)
|
107
106
|
|
108
|
-
|
107
|
+
config_object = Object.const_get(name)
|
108
|
+
options_class_name = "#{name}#{CONFIG_OPTIONS_SUFFIX}"
|
109
|
+
Object.const_set(options_class_name, config_object.singleton_class)
|
110
|
+
|
111
|
+
Array(config_object.singleton_class)
|
112
|
+
end
|
109
113
|
end
|
110
114
|
end
|
111
115
|
end
|
@@ -88,9 +88,13 @@ module Tapioca
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
-
|
92
|
-
|
93
|
-
|
91
|
+
class << self
|
92
|
+
extend T::Sig
|
93
|
+
|
94
|
+
sig { override.returns(T::Enumerable[Module]) }
|
95
|
+
def gather_constants
|
96
|
+
descendants_of(::FrozenRecord::Base).reject(&:abstract_class?)
|
97
|
+
end
|
94
98
|
end
|
95
99
|
|
96
100
|
private
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
begin
|
5
|
+
require "graphql"
|
6
|
+
rescue LoadError
|
7
|
+
return
|
8
|
+
end
|
9
|
+
|
10
|
+
require "tapioca/dsl/helpers/graphql_type_helper"
|
11
|
+
|
12
|
+
module Tapioca
|
13
|
+
module Dsl
|
14
|
+
module Compilers
|
15
|
+
# `Tapioca::Dsl::Compilers::GraphqlInputObject` generates RBI files for subclasses of
|
16
|
+
# [`GraphQL::Schema::InputObject`](https://graphql-ruby.org/api-doc/2.0.11/GraphQL/Schema/InputObject).
|
17
|
+
#
|
18
|
+
# For example, with the following `GraphQL::Schema::InputObject` subclass:
|
19
|
+
#
|
20
|
+
# ~~~rb
|
21
|
+
# class CreateCommentInput < GraphQL::Schema::InputObject
|
22
|
+
# argument :body, String, required: true
|
23
|
+
# argument :post_id, ID, required: true
|
24
|
+
# end
|
25
|
+
# ~~~
|
26
|
+
#
|
27
|
+
# this compiler will produce the RBI file `notify_user_job.rbi` with the following content:
|
28
|
+
#
|
29
|
+
# ~~~rbi
|
30
|
+
# # create_comment.rbi
|
31
|
+
# # typed: true
|
32
|
+
# class CreateCommentInput
|
33
|
+
# sig { returns(String) }
|
34
|
+
# def body; end
|
35
|
+
#
|
36
|
+
# sig { returns(String) }
|
37
|
+
# def post_id; end
|
38
|
+
# end
|
39
|
+
# ~~~
|
40
|
+
class GraphqlInputObject < Compiler
|
41
|
+
extend T::Sig
|
42
|
+
|
43
|
+
ConstantType = type_member { { fixed: T.class_of(GraphQL::Schema::InputObject) } }
|
44
|
+
|
45
|
+
sig { override.void }
|
46
|
+
def decorate
|
47
|
+
arguments = constant.all_argument_definitions
|
48
|
+
return if arguments.empty?
|
49
|
+
|
50
|
+
graphql_type_helper = Helpers::GraphqlTypeHelper.new
|
51
|
+
|
52
|
+
root.create_path(constant) do |input_object|
|
53
|
+
arguments.each do |argument|
|
54
|
+
name = argument.keyword.to_s
|
55
|
+
input_object.create_method(name, return_type: graphql_type_helper.type_for(argument.type))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class << self
|
61
|
+
extend T::Sig
|
62
|
+
|
63
|
+
sig { override.returns(T::Enumerable[Module]) }
|
64
|
+
def gather_constants
|
65
|
+
all_classes.select { |c| c < GraphQL::Schema::InputObject }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|