tapioca 0.10.5 → 0.11.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.
@@ -21,6 +21,15 @@ module Tapioca
21
21
  super
22
22
  end
23
23
 
24
+ attr_reader :__tapioca_secure_tokens
25
+
26
+ def has_secure_token(attribute = :token, length: ::ActiveRecord::SecureToken::MINIMUM_TOKEN_LENGTH)
27
+ @__tapioca_secure_tokens ||= []
28
+ @__tapioca_secure_tokens << attribute
29
+
30
+ super
31
+ end
32
+
24
33
  ::ActiveRecord::Base.singleton_class.prepend(self)
25
34
  end
26
35
  end
@@ -0,0 +1,114 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ begin
5
+ require "kredis"
6
+ rescue LoadError
7
+ return
8
+ end
9
+
10
+ module Tapioca
11
+ module Dsl
12
+ module Compilers
13
+ module Extensions
14
+ module Kredis
15
+ attr_reader :__tapioca_kredis_types
16
+
17
+ def kredis_proxy(name, key: nil, config: :shared, after_change: nil)
18
+ collect_kredis_type(name, "Kredis::Types::Proxy")
19
+ super
20
+ end
21
+
22
+ def kredis_string(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
23
+ collect_kredis_type(name, "Kredis::Types::Scalar")
24
+ super
25
+ end
26
+
27
+ def kredis_integer(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
28
+ collect_kredis_type(name, "Kredis::Types::Scalar")
29
+ super
30
+ end
31
+
32
+ def kredis_decimal(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
33
+ collect_kredis_type(name, "Kredis::Types::Scalar")
34
+ super
35
+ end
36
+
37
+ def kredis_datetime(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
38
+ collect_kredis_type(name, "Kredis::Types::Scalar")
39
+ super
40
+ end
41
+
42
+ def kredis_flag(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
43
+ collect_kredis_type(name, "Kredis::Types::Flag")
44
+ super
45
+ end
46
+
47
+ def kredis_float(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
48
+ collect_kredis_type(name, "Kredis::Types::Scalar")
49
+ super
50
+ end
51
+
52
+ def kredis_enum(name, key: nil, values:, default:, config: :shared, after_change: nil)
53
+ collect_kredis_type(name, "Kredis::Types::Enum", values: values)
54
+ super
55
+ end
56
+
57
+ def kredis_json(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
58
+ collect_kredis_type(name, "Kredis::Types::Scalar")
59
+ super
60
+ end
61
+
62
+ def kredis_list(name, key: nil, typed: :string, config: :shared, after_change: nil)
63
+ collect_kredis_type(name, "Kredis::Types::List")
64
+ super
65
+ end
66
+
67
+ def kredis_unique_list(name, limit: nil, key: nil, typed: :string, config: :shared, after_change: nil)
68
+ collect_kredis_type(name, "Kredis::Types::UniqueList")
69
+ super
70
+ end
71
+
72
+ def kredis_set(name, key: nil, typed: :string, config: :shared, after_change: nil)
73
+ collect_kredis_type(name, "Kredis::Types::Set")
74
+ super
75
+ end
76
+
77
+ def kredis_slot(name, key: nil, config: :shared, after_change: nil)
78
+ collect_kredis_type(name, "Kredis::Types::Slots")
79
+ super
80
+ end
81
+
82
+ def kredis_slots(name, available:, key: nil, config: :shared, after_change: nil)
83
+ collect_kredis_type(name, "Kredis::Types::Slots")
84
+ super
85
+ end
86
+
87
+ def kredis_counter(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
88
+ collect_kredis_type(name, "Kredis::Types::Counter")
89
+ super
90
+ end
91
+
92
+ def kredis_hash(name, key: nil, typed: :string, config: :shared, after_change: nil)
93
+ collect_kredis_type(name, "Kredis::Types::Hash")
94
+ super
95
+ end
96
+
97
+ def kredis_boolean(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
98
+ collect_kredis_type(name, "Kredis::Types::Scalar")
99
+ super
100
+ end
101
+
102
+ private
103
+
104
+ def collect_kredis_type(method, type, values: nil)
105
+ @__tapioca_kredis_types ||= {}
106
+ @__tapioca_kredis_types[method.to_s] = { type: type, values: values }
107
+ end
108
+
109
+ ::Kredis::Attributes::ClassMethods.prepend(self)
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -14,6 +14,7 @@ module Tapioca
14
14
  AttributeMethodsModuleName = T.let("GeneratedAttributeMethods", String)
15
15
  AssociationMethodsModuleName = T.let("GeneratedAssociationMethods", String)
16
16
  DelegatedTypesModuleName = T.let("GeneratedDelegatedTypeMethods", String)
17
+ SecureTokensModuleName = T.let("GeneratedSecureTokenMethods", String)
17
18
 
18
19
  RelationMethodsModuleName = T.let("GeneratedRelationMethods", String)
19
20
  AssociationRelationMethodsModuleName = T.let("GeneratedAssociationRelationMethods", String)
@@ -12,6 +12,9 @@ module Tapioca
12
12
  sig { returns(T::Array[Module]) }
13
13
  attr_reader :requested_constants
14
14
 
15
+ sig { returns(T::Array[Pathname]) }
16
+ attr_reader :requested_paths
17
+
15
18
  sig { returns(T.proc.params(error: String).void) }
16
19
  attr_reader :error_handler
17
20
 
@@ -21,6 +24,7 @@ module Tapioca
21
24
  sig do
22
25
  params(
23
26
  requested_constants: T::Array[Module],
27
+ requested_paths: T::Array[Pathname],
24
28
  requested_compilers: T::Array[T.class_of(Compiler)],
25
29
  excluded_compilers: T::Array[T.class_of(Compiler)],
26
30
  error_handler: T.proc.params(error: String).void,
@@ -29,6 +33,7 @@ module Tapioca
29
33
  end
30
34
  def initialize(
31
35
  requested_constants:,
36
+ requested_paths: [],
32
37
  requested_compilers: [],
33
38
  excluded_compilers: [],
34
39
  error_handler: $stderr.method(:puts).to_proc,
@@ -39,6 +44,7 @@ module Tapioca
39
44
  T::Enumerable[T.class_of(Compiler)],
40
45
  )
41
46
  @requested_constants = requested_constants
47
+ @requested_paths = requested_paths
42
48
  @error_handler = error_handler
43
49
  @number_of_workers = number_of_workers
44
50
  @errors = T.let([], T::Array[String])
@@ -50,11 +56,12 @@ module Tapioca
50
56
  ).returns(T::Array[T.type_parameter(:T)])
51
57
  end
52
58
  def run(&blk)
53
- constants_to_process = gather_constants(requested_constants)
59
+ constants_to_process = gather_constants(requested_constants, requested_paths)
54
60
  .select { |c| Module === c } # Filter value constants out
55
61
  .sort_by! { |c| T.must(Runtime::Reflection.name_of(c)) }
56
62
 
57
- if constants_to_process.empty?
63
+ # It's OK if there are no constants to process if we received a valid file/path.
64
+ if constants_to_process.empty? && requested_paths.select { |p| File.exist?(p) }.empty?
58
65
  report_error(<<~ERROR)
59
66
  No classes/modules can be matched for RBI generation.
60
67
  Please check that the requested classes/modules include processable DSL methods.
@@ -115,12 +122,12 @@ module Tapioca
115
122
  active_compilers
116
123
  end
117
124
 
118
- sig { params(requested_constants: T::Array[Module]).returns(T::Set[Module]) }
119
- def gather_constants(requested_constants)
125
+ sig { params(requested_constants: T::Array[Module], requested_paths: T::Array[Pathname]).returns(T::Set[Module]) }
126
+ def gather_constants(requested_constants, requested_paths)
120
127
  constants = active_compilers.map(&:processable_constants).reduce(Set.new, :union)
121
128
  constants = filter_anonymous_and_reloaded_constants(constants)
122
129
 
123
- constants &= requested_constants unless requested_constants.empty?
130
+ constants &= requested_constants unless requested_constants.empty? && requested_paths.empty?
124
131
  constants
125
132
  end
126
133
 
@@ -12,7 +12,7 @@ module Tapioca
12
12
  sig { override.params(event: ScopeNodeAdded).void }
13
13
  def on_scope(event)
14
14
  constant = event.constant
15
- return unless T::Enum > event.constant
15
+ return unless T::Enum > event.constant # rubocop:disable Style/InvertibleUnlessCondition
16
16
 
17
17
  enums = T.unsafe(constant).values.map do |enum_type|
18
18
  enum_type.instance_variable_get(:@const_name).to_s
@@ -106,6 +106,18 @@ module Tapioca
106
106
  @payload_symbols.include?(symbol_name)
107
107
  end
108
108
 
109
+ sig { params(name: T.any(String, Symbol)).returns(T::Boolean) }
110
+ def constant_in_gem?(name)
111
+ return true unless Object.respond_to?(:const_source_location)
112
+
113
+ source_location, _ = Object.const_source_location(name)
114
+ return true unless source_location
115
+ # If the source location of the constant is "(eval)", all bets are off.
116
+ return true if source_location == "(eval)"
117
+
118
+ gem.contains_path?(source_location)
119
+ end
120
+
109
121
  sig { params(method: UnboundMethod).returns(T::Boolean) }
110
122
  def method_in_gem?(method)
111
123
  source_location = method.source_location&.first
@@ -216,6 +228,7 @@ module Tapioca
216
228
  mark_seen(name)
217
229
 
218
230
  return if symbol_in_payload?(name)
231
+ return unless constant_in_gem?(name)
219
232
 
220
233
  target = name_of(constant)
221
234
  # If target has no name, let's make it an anonymous class or module with `Class.new` or `Module.new`
@@ -237,6 +250,7 @@ module Tapioca
237
250
  mark_seen(name)
238
251
 
239
252
  return if symbol_in_payload?(name)
253
+ return unless constant_in_gem?(name)
240
254
 
241
255
  klass = class_of(value)
242
256
 
@@ -58,36 +58,102 @@ module Tapioca
58
58
 
59
59
  sig { void }
60
60
  def load_rails_engines
61
- rails_engines.each do |engine|
62
- errored_files = []
61
+ return if engines.empty?
63
62
 
63
+ with_rails_application do
64
+ run_initializers
65
+
66
+ if zeitwerk_mode?
67
+ load_engines_in_zeitwerk_mode
68
+ else
69
+ load_engines_in_classic_mode
70
+ end
71
+ end
72
+ end
73
+
74
+ def run_initializers
75
+ engines.each do |engine|
76
+ engine.instance.initializers.tsort_each do |initializer|
77
+ initializer.run(Rails.application)
78
+ rescue ScriptError, StandardError
79
+ nil
80
+ end
81
+ end
82
+ end
83
+
84
+ sig { void }
85
+ def load_engines_in_zeitwerk_mode
86
+ # Collect all the directories that are already managed by all existing Zeitwerk loaders.
87
+ managed_dirs = Zeitwerk::Registry.loaders.flat_map(&:dirs).to_set
88
+ # We use a fresh loader to load the engine directories, so that we don't interfere with
89
+ # any of the existing loaders.
90
+ autoloader = Zeitwerk::Loader.new
91
+
92
+ engines.each do |engine|
93
+ engine.config.eager_load_paths.each do |path|
94
+ # Zeitwerk only accepts existing directories in `push_dir`.
95
+ next unless File.directory?(path)
96
+ # We should not add directories that are already managed by a Zeitwerk loader.
97
+ next if managed_dirs.member?(path)
98
+
99
+ autoloader.push_dir(path)
100
+ end
101
+ end
102
+
103
+ autoloader.setup
104
+ end
105
+
106
+ sig { void }
107
+ def load_engines_in_classic_mode
108
+ # This is code adapted from `Rails::Engine#eager_load!` in
109
+ # https://github.com/rails/rails/blob/d9e188dbab81b412f73dfb7763318d52f360af49/railties/lib/rails/engine.rb#L489-L495
110
+ #
111
+ # We can't use `Rails::Engine#eager_load!` directly because it will raise as soon as it encounters
112
+ # an error, which is not what we want. We want to try to load as much as we can.
113
+ engines.each do |engine|
64
114
  engine.config.eager_load_paths.each do |load_path|
65
115
  Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
66
- require(file)
67
- rescue LoadError, StandardError
68
- errored_files << file
116
+ require_dependency file
69
117
  end
70
- end
71
-
72
- # Try files that have errored one more time
73
- # It might have been a load order problem
74
- errored_files.each do |file|
75
- require(file)
76
- rescue LoadError, StandardError
118
+ rescue ScriptError, StandardError
77
119
  nil
78
120
  end
79
121
  end
80
122
  end
81
123
 
82
- sig { returns(T::Array[T.untyped]) }
83
- def rails_engines
84
- return [] unless Object.const_defined?("Rails::Engine")
124
+ sig { returns(T::Boolean) }
125
+ def zeitwerk_mode?
126
+ Rails.respond_to?(:autoloaders) &&
127
+ Rails.autoloaders.respond_to?(:zeitwerk_enabled?) &&
128
+ Rails.autoloaders.zeitwerk_enabled?
129
+ end
130
+
131
+ sig { params(blk: T.proc.void).void }
132
+ def with_rails_application(&blk)
133
+ # Store the current Rails.application object so that we can restore it
134
+ rails_application = T.unsafe(Rails.application)
135
+
136
+ # Create a new Rails::Application object, so that we can load the engines.
137
+ # Some engines and the `Rails.autoloaders` call might expect `Rails.application`
138
+ # to be set, so we need to create one here.
139
+ unless rails_application
140
+ Rails.application = Class.new(Rails::Application)
141
+ end
142
+
143
+ blk.call
144
+ ensure
145
+ Rails.app_class = Rails.application = rails_application
146
+ end
147
+
148
+ T::Sig::WithoutRuntime.sig { returns(T::Array[T.class_of(Rails::Engine)]) }
149
+ def engines
150
+ return [] unless defined?(Rails::Engine)
85
151
 
86
152
  safe_require("active_support/core_ext/class/subclasses")
87
153
 
88
154
  project_path = Bundler.default_gemfile.parent.expand_path
89
155
  # We can use `Class#descendants` here, since we know Rails is loaded
90
- Object.const_get("Rails::Engine")
156
+ Rails::Engine
91
157
  .descendants
92
158
  .reject(&:abstract_railtie?)
93
159
  .reject { |engine| gem_in_app_dir?(project_path, engine.config.root.to_path) }
@@ -103,30 +169,25 @@ module Tapioca
103
169
  sig { void }
104
170
  def silence_deprecations
105
171
  # Stop any ActiveSupport Deprecations from being reported
106
- Object.const_get("ActiveSupport::Deprecation").silenced = true
107
- rescue NameError
108
- nil
172
+ if defined?(ActiveSupport::Deprecation)
173
+ ActiveSupport::Deprecation.silenced = true
174
+ end
109
175
  end
110
176
 
111
177
  sig { void }
112
178
  def eager_load_rails_app
113
- rails = Object.const_get("Rails")
114
- application = rails.application
115
-
116
- if Object.const_defined?("ActiveSupport")
117
- Object.const_get("ActiveSupport").run_load_hooks(
118
- :before_eager_load,
119
- application,
120
- )
179
+ application = Rails.application
180
+
181
+ if defined?(ActiveSupport)
182
+ ActiveSupport.run_load_hooks(:before_eager_load, application)
121
183
  end
122
184
 
123
- if Object.const_defined?("Zeitwerk::Loader")
124
- zeitwerk_loader = Object.const_get("Zeitwerk::Loader")
125
- zeitwerk_loader.eager_load_all
185
+ if defined?(Zeitwerk::Loader)
186
+ Zeitwerk::Loader.eager_load_all
126
187
  end
127
188
 
128
- if rails.respond_to?(:autoloaders) && rails.autoloaders.zeitwerk_enabled?
129
- rails.autoloaders.each(&:eager_load)
189
+ if Rails.respond_to?(:autoloaders)
190
+ Rails.autoloaders.each(&:eager_load)
130
191
  end
131
192
 
132
193
  if application.config.respond_to?(:eager_load_namespaces)
@@ -5,7 +5,7 @@ module RBI
5
5
  class Tree
6
6
  extend T::Sig
7
7
 
8
- sig { params(constant: ::Module, block: T.nilable(T.proc.params(scope: Scope).void)).void }
8
+ sig { params(constant: ::Module, block: T.nilable(T.proc.params(scope: Scope).void)).returns(Scope) }
9
9
  def create_path(constant, &block)
10
10
  constant_name = Tapioca::Runtime::Reflection.name_of(constant)
11
11
  raise "given constant does not have a name" unless constant_name
@@ -0,0 +1,20 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Tapioca
5
+ module Runtime
6
+ # This module should only be included when running Ruby version 3.2
7
+ # or newer. It relies on the Class#attached_object method, which was
8
+ # added in Ruby 3.2 and fetches the attached object of a singleton
9
+ # class without having to iterate through all of ObjectSpace.
10
+ module AttachedClassOf
11
+ extend T::Sig
12
+
13
+ sig { params(singleton_class: Class).returns(T.nilable(Module)) }
14
+ def attached_class_of(singleton_class)
15
+ result = singleton_class.attached_object
16
+ Module === result ? result : nil
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Tapioca
5
+ module Runtime
6
+ # This module should only be included when running versions of Ruby
7
+ # older than 3.2. Because the Class#attached_object method is not
8
+ # available, it implements finding the attached class of a singleton
9
+ # class by iterating through ObjectSpace.
10
+ module AttachedClassOf
11
+ extend T::Sig
12
+ extend T::Helpers
13
+
14
+ requires_ancestor { Tapioca::Runtime::Reflection }
15
+
16
+ sig { params(singleton_class: Class).returns(T.nilable(Module)) }
17
+ def attached_class_of(singleton_class)
18
+ # https://stackoverflow.com/a/36622320/98634
19
+ result = ObjectSpace.each_object(singleton_class).find do |klass|
20
+ singleton_class_of(T.cast(klass, Module)) == singleton_class
21
+ end
22
+
23
+ T.cast(result, T.nilable(Module))
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,9 +1,20 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ # On Ruby 3.2 or newer, Class defines an attached_object method that returns the
5
+ # attached class of a singleton class without iterating ObjectSpace. On older
6
+ # versions of Ruby, we fall back to iterating ObjectSpace.
7
+ if Class.method_defined?(:attached_object)
8
+ require "tapioca/runtime/attached_class_of_32"
9
+ else
10
+ require "tapioca/runtime/attached_class_of_legacy"
11
+ end
12
+
4
13
  module Tapioca
5
14
  module Runtime
6
15
  module Reflection
16
+ include AttachedClassOf
17
+
7
18
  extend T::Sig
8
19
  extend self
9
20
 
@@ -174,16 +185,6 @@ module Tapioca
174
185
  resolved_loc.absolute_path || ""
175
186
  end
176
187
 
177
- sig { params(singleton_class: Module).returns(T.nilable(Module)) }
178
- def attached_class_of(singleton_class)
179
- # https://stackoverflow.com/a/36622320/98634
180
- result = ObjectSpace.each_object(singleton_class).find do |klass|
181
- singleton_class_of(T.cast(klass, Module)) == singleton_class
182
- end
183
-
184
- T.cast(result, Module)
185
- end
186
-
187
188
  sig { params(constant: Module).returns(T::Set[String]) }
188
189
  def file_candidates_for(constant)
189
190
  relevant_methods_for(constant).filter_map do |method|
@@ -41,6 +41,20 @@ module Tapioca
41
41
  symbols_from_paths(gem.files)
42
42
  end
43
43
 
44
+ sig { params(paths: T::Array[Pathname]).returns(T::Set[String]) }
45
+ def symbols_from_paths(paths)
46
+ output = Tempfile.create("sorbet") do |file|
47
+ file.write(Array(paths).join("\n"))
48
+ file.flush
49
+
50
+ symbol_table_json_from("@#{file.path.shellescape}")
51
+ end
52
+
53
+ return Set.new if output.empty?
54
+
55
+ SymbolTableParser.parse_json(output)
56
+ end
57
+
44
58
  private
45
59
 
46
60
  sig { returns(T::Array[T.class_of(Rails::Engine)]) }
@@ -59,20 +73,6 @@ module Tapioca
59
73
  def symbol_table_json_from(input, table_type: "symbol-table-json")
60
74
  sorbet("--no-config", "--quiet", "--print=#{table_type}", input).out
61
75
  end
62
-
63
- sig { params(paths: T::Array[Pathname]).returns(T::Set[String]) }
64
- def symbols_from_paths(paths)
65
- output = Tempfile.create("sorbet") do |file|
66
- file.write(Array(paths).join("\n"))
67
- file.flush
68
-
69
- symbol_table_json_from("@#{file.path.shellescape}")
70
- end
71
-
72
- return Set.new if output.empty?
73
-
74
- SymbolTableParser.parse_json(output)
75
- end
76
76
  end
77
77
  end
78
78
  end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Tapioca
5
- VERSION = "0.10.5"
5
+ VERSION = "0.11.0"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tapioca
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.5
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ufuk Kayserilioglu
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2023-01-04 00:00:00.000000000 Z
14
+ date: 2023-02-21 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -176,6 +176,7 @@ files:
176
176
  - lib/tapioca/dsl/compilers/active_record_fixtures.rb
177
177
  - lib/tapioca/dsl/compilers/active_record_relations.rb
178
178
  - lib/tapioca/dsl/compilers/active_record_scope.rb
179
+ - lib/tapioca/dsl/compilers/active_record_secure_token.rb
179
180
  - lib/tapioca/dsl/compilers/active_record_typed_store.rb
180
181
  - lib/tapioca/dsl/compilers/active_resource.rb
181
182
  - lib/tapioca/dsl/compilers/active_storage.rb
@@ -186,6 +187,7 @@ files:
186
187
  - lib/tapioca/dsl/compilers/graphql_input_object.rb
187
188
  - lib/tapioca/dsl/compilers/graphql_mutation.rb
188
189
  - lib/tapioca/dsl/compilers/identity_cache.rb
190
+ - lib/tapioca/dsl/compilers/kredis.rb
189
191
  - lib/tapioca/dsl/compilers/mixed_in_class_attributes.rb
190
192
  - lib/tapioca/dsl/compilers/protobuf.rb
191
193
  - lib/tapioca/dsl/compilers/rails_generators.rb
@@ -195,6 +197,7 @@ files:
195
197
  - lib/tapioca/dsl/compilers/url_helpers.rb
196
198
  - lib/tapioca/dsl/extensions/active_record.rb
197
199
  - lib/tapioca/dsl/extensions/frozen_record.rb
200
+ - lib/tapioca/dsl/extensions/kredis.rb
198
201
  - lib/tapioca/dsl/helpers/active_record_column_type_helper.rb
199
202
  - lib/tapioca/dsl/helpers/active_record_constants_helper.rb
200
203
  - lib/tapioca/dsl/helpers/graphql_type_helper.rb
@@ -239,6 +242,8 @@ files:
239
242
  - lib/tapioca/rbi_ext/model.rb
240
243
  - lib/tapioca/rbi_formatter.rb
241
244
  - lib/tapioca/repo_index.rb
245
+ - lib/tapioca/runtime/attached_class_of_32.rb
246
+ - lib/tapioca/runtime/attached_class_of_legacy.rb
242
247
  - lib/tapioca/runtime/dynamic_mixin_compiler.rb
243
248
  - lib/tapioca/runtime/generic_type_registry.rb
244
249
  - lib/tapioca/runtime/reflection.rb