tapioca 0.9.4 → 0.10.0

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