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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +21 -0
  3. data/README.md +48 -22
  4. data/lib/tapioca/cli.rb +17 -23
  5. data/lib/tapioca/commands/annotations.rb +2 -2
  6. data/lib/tapioca/commands/dsl.rb +43 -65
  7. data/lib/tapioca/commands/gem.rb +18 -50
  8. data/lib/tapioca/commands/todo.rb +1 -2
  9. data/lib/tapioca/dsl/compiler.rb +34 -37
  10. data/lib/tapioca/dsl/compilers/aasm.rb +7 -3
  11. data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +7 -3
  12. data/lib/tapioca/dsl/compilers/action_mailer.rb +7 -3
  13. data/lib/tapioca/dsl/compilers/active_job.rb +7 -3
  14. data/lib/tapioca/dsl/compilers/active_model_attributes.rb +9 -5
  15. data/lib/tapioca/dsl/compilers/active_model_secure_password.rb +11 -7
  16. data/lib/tapioca/dsl/compilers/active_record_associations.rb +7 -3
  17. data/lib/tapioca/dsl/compilers/active_record_columns.rb +7 -3
  18. data/lib/tapioca/dsl/compilers/active_record_enum.rb +7 -3
  19. data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +8 -4
  20. data/lib/tapioca/dsl/compilers/active_record_relations.rb +7 -3
  21. data/lib/tapioca/dsl/compilers/active_record_scope.rb +5 -3
  22. data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +8 -4
  23. data/lib/tapioca/dsl/compilers/active_resource.rb +7 -3
  24. data/lib/tapioca/dsl/compilers/active_storage.rb +9 -5
  25. data/lib/tapioca/dsl/compilers/active_support_concern.rb +21 -18
  26. data/lib/tapioca/dsl/compilers/active_support_current_attributes.rb +7 -3
  27. data/lib/tapioca/dsl/compilers/config.rb +12 -8
  28. data/lib/tapioca/dsl/compilers/frozen_record.rb +7 -3
  29. data/lib/tapioca/dsl/compilers/graphql_input_object.rb +71 -0
  30. data/lib/tapioca/dsl/compilers/graphql_mutation.rb +81 -0
  31. data/lib/tapioca/dsl/compilers/identity_cache.rb +8 -4
  32. data/lib/tapioca/dsl/compilers/mixed_in_class_attributes.rb +9 -5
  33. data/lib/tapioca/dsl/compilers/protobuf.rb +69 -25
  34. data/lib/tapioca/dsl/compilers/rails_generators.rb +12 -8
  35. data/lib/tapioca/dsl/compilers/sidekiq_worker.rb +7 -3
  36. data/lib/tapioca/dsl/compilers/smart_properties.rb +10 -6
  37. data/lib/tapioca/dsl/compilers/state_machines.rb +7 -3
  38. data/lib/tapioca/dsl/compilers/url_helpers.rb +29 -26
  39. data/lib/tapioca/dsl/compilers.rb +0 -5
  40. data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +1 -9
  41. data/lib/tapioca/dsl/helpers/graphql_type_helper.rb +62 -0
  42. data/lib/tapioca/dsl/pipeline.rb +19 -11
  43. data/lib/tapioca/gem/listeners/source_location.rb +16 -9
  44. data/lib/tapioca/gemfile.rb +30 -0
  45. data/lib/tapioca/helpers/config_helper.rb +2 -2
  46. data/lib/tapioca/helpers/rbi_helper.rb +43 -30
  47. data/lib/tapioca/helpers/source_uri.rb +77 -0
  48. data/lib/tapioca/helpers/test/dsl_compiler.rb +1 -1
  49. data/lib/tapioca/helpers/test/isolation.rb +7 -3
  50. data/lib/tapioca/internal.rb +5 -1
  51. data/lib/tapioca/loaders/dsl.rb +84 -0
  52. data/lib/tapioca/loaders/gem.rb +85 -0
  53. data/lib/tapioca/{runtime → loaders}/loader.rb +39 -31
  54. data/lib/tapioca/repo_index.rb +12 -8
  55. data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +2 -2
  56. data/lib/tapioca/runtime/trackers/constant_definition.rb +15 -13
  57. data/lib/tapioca/runtime/trackers/mixin.rb +35 -31
  58. data/lib/tapioca/runtime/trackers/required_ancestor.rb +21 -19
  59. data/lib/tapioca/static/requires_compiler.rb +2 -3
  60. data/lib/tapioca/static/symbol_table_parser.rb +19 -17
  61. data/lib/tapioca/version.rb +1 -1
  62. data/lib/tapioca.rb +24 -20
  63. metadata +10 -5
  64. data/Gemfile +0 -53
  65. data/Rakefile +0 -18
@@ -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
- sig { override.returns(T::Enumerable[Module]) }
119
- def self.gather_constants
120
- T.cast(ObjectSpace.each_object(::AASM::ClassMethods), T::Enumerable[Module])
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
- sig { override.returns(T::Enumerable[Module]) }
125
- def self.gather_constants
126
- descendants_of(::ActionController::Base).reject(&:abstract?).select(&:name)
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
- sig { override.returns(T::Enumerable[Module]) }
58
- def self.gather_constants
59
- descendants_of(::ActionMailer::Base).reject(&:abstract?)
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
- sig { override.returns(T::Enumerable[Module]) }
71
- def self.gather_constants
72
- descendants_of(::ActiveJob::Base)
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
- sig { override.returns(T::Enumerable[Module]) }
57
- def self.gather_constants
58
- all_classes.grep(::ActiveModel::Attributes::ClassMethods)
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.map do |name, value|
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.compact
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
- sig { override.returns(T::Enumerable[Module]) }
89
- def self.gather_constants
90
- # This selects all classes that are `ActiveModel::SecurePassword::ClassMethods === klass`.
91
- # In other words, we select all classes that have `ActiveModel::SecurePassword::ClassMethods`
92
- # as an ancestor of its singleton class, i.e. all classes that have extended the
93
- # `ActiveModel::SecurePassword::ClassMethods` module.
94
- all_classes.grep(::ActiveModel::SecurePassword::ClassMethods)
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
- sig { override.returns(T::Enumerable[Module]) }
139
- def self.gather_constants
140
- descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
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
- sig { override.returns(T::Enumerable[Module]) }
139
- def self.gather_constants
140
- descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
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
- sig { override.returns(T::Enumerable[Module]) }
84
- def self.gather_constants
85
- descendants_of(::ActiveRecord::Base)
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
- sig { override.returns(T::Enumerable[Module]) }
61
- def self.gather_constants
62
- return [] unless Rails.application
60
+ class << self
61
+ extend T::Sig
63
62
 
64
- [ActiveSupport::TestCase]
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
- sig { override.returns(T::Enumerable[Module]) }
170
- def self.gather_constants
171
- ActiveRecord::Base.descendants.reject(&:abstract_class?)
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
- sig { override.returns(T::Enumerable[Module]) }
84
- def self.gather_constants
85
- descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
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
- sig { override.returns(T::Enumerable[Module]) }
117
- def self.gather_constants
118
- descendants_of(::ActiveRecord::Base).select do |klass|
119
- klass.include?(ActiveRecord::TypedStore::Behavior)
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
- sig { override.returns(T::Enumerable[Module]) }
78
- def self.gather_constants
79
- descendants_of(::ActiveResource::Base)
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
- sig { override.returns(T::Enumerable[Module]) }
78
- def self.gather_constants
79
- descendants_of(::ActiveRecord::Base)
80
- .reject(&:abstract_class?)
81
- .grep(::ActiveStorage::Reflection::ActiveRecordExtensions::ClassMethods)
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
- .map do |concern| # Map to class methods module name, if exists
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
- sig { override.returns(T::Enumerable[Module]) }
70
- def self.gather_constants
71
- # Find all Modules that are:
72
- all_modules.select do |mod|
73
- # named (i.e. not anonymous)
74
- name_of(mod) &&
75
- # not singleton classes
76
- !mod.singleton_class? &&
77
- # extend ActiveSupport::Concern, and
78
- mod.singleton_class < ActiveSupport::Concern &&
79
- # have dependencies (i.e. include another concern)
80
- !dependencies_of(mod).empty?
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
- sig { params(concern: Module).returns(T::Array[Module]) }
85
- def self.dependencies_of(concern)
86
- concern.instance_variable_get(:@_dependencies)
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
- sig { override.returns(T::Enumerable[Module]) }
92
- def self.gather_constants
93
- descendants_of(::ActiveSupport::CurrentAttributes)
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
- sig { override.returns(T::Enumerable[Module]) }
100
- def self.gather_constants
101
- name = ::Config.const_name
102
- return [] unless Object.const_defined?(name)
99
+ class << self
100
+ extend T::Sig
103
101
 
104
- config_object = Object.const_get(name)
105
- options_class_name = "#{name}#{CONFIG_OPTIONS_SUFFIX}"
106
- Object.const_set(options_class_name, config_object.singleton_class)
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
- Array(config_object.singleton_class)
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
- sig { override.returns(T::Enumerable[Module]) }
92
- def self.gather_constants
93
- descendants_of(::FrozenRecord::Base).reject(&:abstract_class?)
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