tapioca 0.7.0 → 0.8.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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/README.md +491 -73
  4. data/lib/tapioca/cli.rb +40 -3
  5. data/lib/tapioca/commands/annotations.rb +154 -0
  6. data/lib/tapioca/commands/dsl.rb +20 -1
  7. data/lib/tapioca/commands/gem.rb +17 -57
  8. data/lib/tapioca/commands/init.rb +1 -0
  9. data/lib/tapioca/commands/todo.rb +4 -2
  10. data/lib/tapioca/commands.rb +1 -0
  11. data/lib/tapioca/dsl/compiler.rb +2 -2
  12. data/lib/tapioca/dsl/compilers/aasm.rb +1 -1
  13. data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +1 -1
  14. data/lib/tapioca/dsl/compilers/action_mailer.rb +1 -1
  15. data/lib/tapioca/dsl/compilers/active_job.rb +1 -1
  16. data/lib/tapioca/dsl/compilers/active_model_attributes.rb +1 -1
  17. data/lib/tapioca/dsl/compilers/active_model_secure_password.rb +1 -1
  18. data/lib/tapioca/dsl/compilers/active_record_associations.rb +1 -1
  19. data/lib/tapioca/dsl/compilers/active_record_columns.rb +1 -1
  20. data/lib/tapioca/dsl/compilers/active_record_enum.rb +1 -1
  21. data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +3 -1
  22. data/lib/tapioca/dsl/compilers/active_record_relations.rb +8 -8
  23. data/lib/tapioca/dsl/compilers/active_record_scope.rb +1 -1
  24. data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +1 -1
  25. data/lib/tapioca/dsl/compilers/active_resource.rb +1 -1
  26. data/lib/tapioca/dsl/compilers/active_storage.rb +6 -2
  27. data/lib/tapioca/dsl/compilers/active_support_concern.rb +1 -1
  28. data/lib/tapioca/dsl/compilers/active_support_current_attributes.rb +1 -1
  29. data/lib/tapioca/dsl/compilers/config.rb +2 -2
  30. data/lib/tapioca/dsl/compilers/frozen_record.rb +1 -1
  31. data/lib/tapioca/dsl/compilers/identity_cache.rb +1 -1
  32. data/lib/tapioca/dsl/compilers/mixed_in_class_attributes.rb +1 -1
  33. data/lib/tapioca/dsl/compilers/protobuf.rb +27 -3
  34. data/lib/tapioca/dsl/compilers/rails_generators.rb +1 -1
  35. data/lib/tapioca/dsl/compilers/sidekiq_worker.rb +1 -1
  36. data/lib/tapioca/dsl/compilers/smart_properties.rb +1 -1
  37. data/lib/tapioca/dsl/compilers/state_machines.rb +1 -1
  38. data/lib/tapioca/dsl/compilers/url_helpers.rb +5 -2
  39. data/lib/tapioca/dsl/helpers/param_helper.rb +4 -1
  40. data/lib/tapioca/dsl/pipeline.rb +32 -1
  41. data/lib/tapioca/dsl.rb +6 -0
  42. data/lib/tapioca/executor.rb +4 -46
  43. data/lib/tapioca/gem/listeners/methods.rb +26 -1
  44. data/lib/tapioca/gem/listeners/sorbet_props.rb +1 -1
  45. data/lib/tapioca/gem/listeners/sorbet_required_ancestors.rb +1 -0
  46. data/lib/tapioca/gem/listeners/sorbet_signatures.rb +1 -1
  47. data/lib/tapioca/gem/pipeline.rb +5 -1
  48. data/lib/tapioca/gemfile.rb +50 -3
  49. data/lib/tapioca/helpers/config_helper.rb +13 -0
  50. data/lib/tapioca/helpers/rbi_helper.rb +114 -7
  51. data/lib/tapioca/helpers/shims_helper.rb +36 -8
  52. data/lib/tapioca/helpers/signatures_helper.rb +17 -0
  53. data/lib/tapioca/helpers/sorbet_helper.rb +5 -11
  54. data/lib/tapioca/helpers/test/content.rb +1 -0
  55. data/lib/tapioca/helpers/test/dsl_compiler.rb +1 -0
  56. data/lib/tapioca/helpers/test/template.rb +1 -0
  57. data/lib/tapioca/helpers/type_variable_helper.rb +43 -0
  58. data/lib/tapioca/internal.rb +4 -1
  59. data/lib/tapioca/rbi_ext/model.rb +14 -2
  60. data/lib/tapioca/repo_index.rb +41 -0
  61. data/lib/tapioca/runtime/generic_type_registry.rb +4 -2
  62. data/lib/tapioca/runtime/loader.rb +3 -0
  63. data/lib/tapioca/runtime/reflection.rb +17 -13
  64. data/lib/tapioca/sorbet_ext/generic_name_patch.rb +38 -21
  65. data/lib/tapioca/static/symbol_table_parser.rb +2 -0
  66. data/lib/tapioca/version.rb +1 -1
  67. data/lib/tapioca.rb +5 -0
  68. metadata +26 -21
data/lib/tapioca/cli.rb CHANGED
@@ -5,6 +5,7 @@ module Tapioca
5
5
  class Cli < Thor
6
6
  include CliHelper
7
7
  include ConfigHelper
8
+ include SorbetHelper
8
9
  include ShimsHelper
9
10
 
10
11
  FILE_HEADER_OPTION_DESC = "Add a \"This file is generated\" header on top of each generated RBI file"
@@ -89,7 +90,7 @@ module Tapioca
89
90
  option :quiet,
90
91
  aliases: ["-q"],
91
92
  type: :boolean,
92
- desc: "Supresses file creation output",
93
+ desc: "Suppresses file creation output",
93
94
  default: false
94
95
  option :workers,
95
96
  aliases: ["-w"],
@@ -171,7 +172,7 @@ module Tapioca
171
172
  option :doc,
172
173
  type: :boolean,
173
174
  desc: "Include YARD documentation from sources when generating RBIs. Warning: this might be slow",
174
- default: false
175
+ default: true
175
176
  option :exported_gem_rbis,
176
177
  type: :boolean,
177
178
  desc: "Include RBIs found in the `rbi/` directory of the gem",
@@ -242,6 +243,7 @@ module Tapioca
242
243
  option :gem_rbi_dir, type: :string, desc: "Path to gem RBIs", default: DEFAULT_GEM_DIR
243
244
  option :dsl_rbi_dir, type: :string, desc: "Path to DSL RBIs", default: DEFAULT_DSL_DIR
244
245
  option :shim_rbi_dir, type: :string, desc: "Path to shim RBIs", default: DEFAULT_SHIM_DIR
246
+ option :payload, type: :boolean, desc: "Check shims against Sorbet's payload", default: true
245
247
  def check_shims
246
248
  index = RBI::Index.new
247
249
 
@@ -251,6 +253,30 @@ module Tapioca
251
253
  exit(0)
252
254
  end
253
255
 
256
+ payload_path = T.let(nil, T.nilable(String))
257
+
258
+ if options[:payload]
259
+ if sorbet_supports?(:print_payload_sources)
260
+ Dir.mktmpdir do |dir|
261
+ payload_path = dir
262
+ result = sorbet("--no-config --print=payload-sources:#{payload_path}")
263
+
264
+ unless result.status
265
+ say_error("Sorbet failed to dump payload")
266
+ say_error(result.err)
267
+ exit(1)
268
+ end
269
+
270
+ index_payload(index, payload_path)
271
+ end
272
+ else
273
+ say_error("The version of Sorbet used in your Gemfile.lock does not support `--print=payload-sources`")
274
+ say_error("Current: v#{SORBET_GEM_SPEC.version}")
275
+ say_error("Required: #{FEATURE_REQUIREMENTS[:print_payload_sources]}")
276
+ exit(1)
277
+ end
278
+ end
279
+
254
280
  index_rbis(index, "shim", shim_rbi_dir)
255
281
  index_rbis(index, "gem", options[:gem_rbi_dir])
256
282
  index_rbis(index, "dsl", options[:dsl_rbi_dir])
@@ -260,7 +286,11 @@ module Tapioca
260
286
  duplicates.each do |key, nodes|
261
287
  say_error("\nDuplicated RBI for #{key}:", :red)
262
288
  nodes.each do |node|
263
- say_error(" * #{node.loc}", :red)
289
+ node_loc = node.loc
290
+ next unless node_loc
291
+
292
+ loc_string = location_to_payload_url(node_loc, path_prefix: payload_path)
293
+ say_error(" * #{loc_string}", :red)
264
294
  end
265
295
  end
266
296
  say_error("\nPlease remove the duplicated definitions from the #{shim_rbi_dir} directory.", :red)
@@ -271,6 +301,13 @@ module Tapioca
271
301
  exit(0)
272
302
  end
273
303
 
304
+ desc "annotations", "Pull gem annotations from a central RBI repository"
305
+ option :repo_uri, type: :string, desc: "Repository URI to pull annotations from", default: CENTRAL_REPO_ROOT_URI
306
+ def annotations
307
+ command = Commands::Annotations.new(central_repo_root_uri: options[:repo_uri])
308
+ command.execute
309
+ end
310
+
274
311
  map ["--version", "-v"] => :__print_version
275
312
 
276
313
  desc "--version, -v", "show version"
@@ -0,0 +1,154 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "net/http"
5
+
6
+ module Tapioca
7
+ module Commands
8
+ class Annotations < Command
9
+ extend T::Sig
10
+
11
+ sig do
12
+ params(
13
+ central_repo_root_uri: String,
14
+ central_repo_index_path: String
15
+ ).void
16
+ end
17
+ def initialize(central_repo_root_uri:, central_repo_index_path: CENTRAL_REPO_INDEX_PATH)
18
+ super()
19
+ @central_repo_root_uri = central_repo_root_uri
20
+ @index = T.let(fetch_index, RepoIndex)
21
+ end
22
+
23
+ sig { override.void }
24
+ def execute
25
+ project_gems = list_gemfile_gems
26
+ remove_expired_annotations(project_gems)
27
+ fetch_annotations(project_gems)
28
+ end
29
+
30
+ private
31
+
32
+ sig { returns(T::Array[String]) }
33
+ def list_gemfile_gems
34
+ say("Listing gems from Gemfile.lock... ", [:blue, :bold])
35
+ gemfile = Bundler.read_file("Gemfile.lock")
36
+ parser = Bundler::LockfileParser.new(gemfile)
37
+ gem_names = parser.specs.map(&:name)
38
+ say("Done", :green)
39
+ gem_names
40
+ end
41
+
42
+ sig { params(project_gems: T::Array[String]).void }
43
+ def remove_expired_annotations(project_gems)
44
+ say("Removing annotations for gems that have been removed... ", [:blue, :bold])
45
+
46
+ annotations = Pathname.glob("#{DEFAULT_ANNOTATIONS_DIR}/*.rbi").map { |f| f.basename(".*").to_s }
47
+ expired = annotations - project_gems
48
+
49
+ if expired.empty?
50
+ say(" Nothing to do")
51
+ return
52
+ end
53
+
54
+ say("\n")
55
+ expired.each do |gem_name|
56
+ say("\n")
57
+ path = "#{DEFAULT_ANNOTATIONS_DIR}/#{gem_name}.rbi"
58
+ remove_file(path)
59
+ end
60
+ say("\nDone\n\n", :green)
61
+ end
62
+
63
+ sig { returns(RepoIndex) }
64
+ def fetch_index
65
+ say("Retrieving index from central repository... ", [:blue, :bold])
66
+ content = fetch_file(CENTRAL_REPO_INDEX_PATH)
67
+ exit(1) unless content
68
+
69
+ index = RepoIndex.from_json(content)
70
+ say("Done", :green)
71
+ index
72
+ end
73
+
74
+ sig { params(gem_names: T::Array[String]).returns(T::Array[String]) }
75
+ def fetch_annotations(gem_names)
76
+ say("Fetching gem annotations from central repository... ", [:blue, :bold])
77
+ fetchable_gems = gem_names.select { |gem_name| @index.has_gem?(gem_name) }
78
+
79
+ if fetchable_gems.empty?
80
+ say(" Nothing to do")
81
+ exit(0)
82
+ end
83
+
84
+ say("\n")
85
+ fetched_gems = fetchable_gems.select { |name| fetch_annotation(name) }
86
+ say("\nDone", :green)
87
+ fetched_gems
88
+ end
89
+
90
+ sig { params(gem_name: String).void }
91
+ def fetch_annotation(gem_name)
92
+ content = fetch_file("#{CENTRAL_REPO_ANNOTATIONS_DIR}/#{gem_name}.rbi")
93
+ return unless content
94
+
95
+ content = add_header(gem_name, content)
96
+
97
+ dir = DEFAULT_ANNOTATIONS_DIR
98
+ FileUtils.mkdir_p(dir)
99
+ say("\n Fetched #{set_color(gem_name, :yellow, :bold)}", :green)
100
+ create_file("#{dir}/#{gem_name}.rbi", content)
101
+ end
102
+
103
+ sig { params(path: String).returns(T.nilable(String)) }
104
+ def fetch_file(path)
105
+ if @central_repo_root_uri.start_with?(%r{https?://})
106
+ fetch_http_file(path)
107
+ else
108
+ fetch_local_file(path)
109
+ end
110
+ end
111
+
112
+ sig { params(path: String).returns(T.nilable(String)) }
113
+ def fetch_local_file(path)
114
+ File.read("#{@central_repo_root_uri}/#{path}")
115
+ rescue => e
116
+ say_error("\nCan't fetch file `#{path}` (#{e.message})", :bold, :red)
117
+ nil
118
+ end
119
+
120
+ sig { params(path: String).returns(T.nilable(String)) }
121
+ def fetch_http_file(path)
122
+ uri = URI("#{@central_repo_root_uri}/#{path}")
123
+ response = Net::HTTP.get_response(uri)
124
+ case response
125
+ when Net::HTTPSuccess
126
+ response.body
127
+ else
128
+ say_error("\nCan't fetch file `#{path}` from #{@central_repo_root_uri} (#{response.class})", :bold, :red)
129
+ nil
130
+ end
131
+ rescue SocketError, Errno::ECONNREFUSED => e
132
+ say_error("\nCan't fetch file `#{path}` from #{@central_repo_root_uri} (#{e.message})", :bold, :red)
133
+ nil
134
+ end
135
+
136
+ sig { params(name: String, content: String).returns(String) }
137
+ def add_header(name, content)
138
+ header = <<~COMMENT
139
+ # DO NOT EDIT MANUALLY
140
+ # This file was pulled from #{@central_repo_root_uri}.
141
+ # Please run `#{default_command(:annotations)}` to update it.
142
+ COMMENT
143
+
144
+ contents = content.split("\n")
145
+ if contents[0]&.start_with?("# typed:") && contents[1]&.empty?
146
+ contents.insert(2, header).join("\n")
147
+ else
148
+ say_error("Couldn't insert file header for content: #{content} due to unexpected file format")
149
+ content
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
@@ -4,6 +4,9 @@
4
4
  module Tapioca
5
5
  module Commands
6
6
  class Dsl < Command
7
+ include SorbetHelper
8
+ include RBIHelper
9
+
7
10
  sig do
8
11
  params(
9
12
  requested_constants: T::Array[String],
@@ -17,6 +20,8 @@ module Tapioca
17
20
  quiet: T::Boolean,
18
21
  verbose: T::Boolean,
19
22
  number_of_workers: T.nilable(Integer),
23
+ auto_strictness: T::Boolean,
24
+ gem_dir: String,
20
25
  rbi_formatter: RBIFormatter
21
26
  ).void
22
27
  end
@@ -32,6 +37,8 @@ module Tapioca
32
37
  quiet: false,
33
38
  verbose: false,
34
39
  number_of_workers: nil,
40
+ auto_strictness: true,
41
+ gem_dir: DEFAULT_GEM_DIR,
35
42
  rbi_formatter: DEFAULT_RBI_FORMATTER
36
43
  )
37
44
  @requested_constants = requested_constants
@@ -45,6 +52,8 @@ module Tapioca
45
52
  @quiet = quiet
46
53
  @verbose = verbose
47
54
  @number_of_workers = number_of_workers
55
+ @auto_strictness = auto_strictness
56
+ @gem_dir = gem_dir
48
57
  @rbi_formatter = rbi_formatter
49
58
 
50
59
  super()
@@ -102,9 +111,19 @@ module Tapioca
102
111
  perform_dsl_verification(outpath)
103
112
  else
104
113
  purge_stale_dsl_rbi_files(rbi_files_to_purge)
105
-
106
114
  say("Done", :green)
107
115
 
116
+ if @auto_strictness
117
+ say("")
118
+ validate_rbi_files(
119
+ command: default_command(:dsl, @requested_constants.join(" ")),
120
+ gem_dir: @gem_dir,
121
+ dsl_dir: @outpath.to_s,
122
+ auto_strictness: @auto_strictness,
123
+ compilers: pipeline.compilers
124
+ )
125
+ end
126
+
108
127
  say("All operations performed in working directory.", [:green, :bold])
109
128
  say("Please review changes and commit them.", [:green, :bold])
110
129
  end
@@ -5,6 +5,7 @@ module Tapioca
5
5
  module Commands
6
6
  class Gem < Command
7
7
  include SorbetHelper
8
+ include RBIHelper
8
9
 
9
10
  sig do
10
11
  params(
@@ -78,7 +79,13 @@ module Tapioca
78
79
  end
79
80
 
80
81
  if anything_done
81
- update_strictnesses(gem_queue.map(&:name), gem_dir: @outpath.to_s, dsl_dir: @dsl_dir) if @auto_strictness
82
+ validate_rbi_files(
83
+ command: default_command(:gem, @gem_names.join(" ")),
84
+ gem_dir: @outpath.to_s,
85
+ dsl_dir: @dsl_dir,
86
+ auto_strictness: @auto_strictness,
87
+ gems: bundle.dependencies
88
+ )
82
89
 
83
90
  say("All operations performed in working directory.", [:green, :bold])
84
91
  say("Please review changes and commit them.", [:green, :bold])
@@ -102,7 +109,13 @@ module Tapioca
102
109
  ].any?
103
110
 
104
111
  if anything_done
105
- update_strictnesses([], gem_dir: @outpath.to_s, dsl_dir: @dsl_dir) if @auto_strictness
112
+ validate_rbi_files(
113
+ command: default_command(:gem),
114
+ gem_dir: @outpath.to_s,
115
+ dsl_dir: @dsl_dir,
116
+ auto_strictness: @auto_strictness,
117
+ gems: bundle.dependencies
118
+ )
106
119
 
107
120
  say("All operations performed in working directory.", [:green, :bold])
108
121
  say("Please review changes and commit them.", [:green, :bold])
@@ -122,7 +135,7 @@ module Tapioca
122
135
 
123
136
  sig { returns(Gemfile) }
124
137
  def bundle
125
- @bundle ||= Gemfile.new
138
+ @bundle ||= Gemfile.new(@exclude)
126
139
  end
127
140
 
128
141
  sig { void }
@@ -359,6 +372,7 @@ module Tapioca
359
372
  sig { params(gem: Gemfile::GemSpec, file: RBI::File).void }
360
373
  def merge_with_exported_rbi(gem, file)
361
374
  return file unless gem.export_rbi_files?
375
+
362
376
  tree = gem.exported_rbi_tree
363
377
 
364
378
  unless tree.conflicts.empty?
@@ -379,60 +393,6 @@ module Tapioca
379
393
  say_error("\n\n RBIs exported by `#{gem.name}` contain errors and can't be used:", :yellow)
380
394
  say_error("Cause: #{e.message} (#{e.location})")
381
395
  end
382
-
383
- sig { params(gem_names: T::Array[String], gem_dir: String, dsl_dir: String).void }
384
- def update_strictnesses(gem_names, gem_dir: DEFAULT_GEM_DIR, dsl_dir: DEFAULT_DSL_DIR)
385
- return unless File.directory?(dsl_dir)
386
-
387
- error_url_base = Spoom::Sorbet::Errors::DEFAULT_ERROR_URL_BASE
388
-
389
- say("Typechecking RBI files... ")
390
- res = sorbet(
391
- "--no-config",
392
- "--error-url-base=#{error_url_base}",
393
- "--isolate-error-code 4010",
394
- dsl_dir,
395
- gem_dir
396
- )
397
- say(" Done", :green)
398
-
399
- errors = Spoom::Sorbet::Errors::Parser.parse_string(res.err)
400
-
401
- if errors.empty?
402
- say("No error found", [:green, :bold])
403
- return
404
- end
405
-
406
- files = []
407
-
408
- errors.each do |error|
409
- # Collect the file with error
410
- files << error.file
411
- error.more.each do |line|
412
- # Also collect the conflicting definition file paths
413
- next unless line.include?("Previous definition")
414
- files << line.split(":").first&.strip
415
- end
416
- end
417
-
418
- files
419
- .uniq
420
- .sort
421
- .select do |file|
422
- name = gem_name_from_rbi_path(file)
423
- file.start_with?(gem_dir) && (gem_names.empty? || gem_names.include?(name))
424
- end.each do |file|
425
- Spoom::Sorbet::Sigils.change_sigil_in_file(file, "false")
426
- say("\n Changed strictness of #{file} to `typed: false` (conflicting with DSL files)", [:yellow, :bold])
427
- end
428
-
429
- say("\n")
430
- end
431
-
432
- sig { params(path: String).returns(String) }
433
- def gem_name_from_rbi_path(path)
434
- T.must(File.basename(path, ".rbi").split("@").first)
435
- end
436
396
  end
437
397
  end
438
398
  end
@@ -41,6 +41,7 @@ module Tapioca
41
41
  create_file(@sorbet_config, <<~CONTENT, skip: true, force: false)
42
42
  --dir
43
43
  .
44
+ --ignore=vendor/
44
45
  CONTENT
45
46
  end
46
47
 
@@ -74,10 +74,12 @@ module Tapioca
74
74
  .each_line
75
75
  .map do |line|
76
76
  next if line.include?("<")
77
- next if line.include?("class_of")
78
- line.strip.gsub("T.untyped::", "")
77
+
78
+ line.strip
79
+ .gsub(/T\.class_of\(([:\w]+)\)/, '\1') # Turn T.class_of(Foo)::Bar into Foo::Bar
79
80
  end
80
81
  .compact
82
+ .sort
81
83
  end
82
84
  end
83
85
  end
@@ -4,6 +4,7 @@
4
4
  module Tapioca
5
5
  module Commands
6
6
  autoload :Command, "tapioca/commands/command"
7
+ autoload :Annotations, "tapioca/commands/annotations"
7
8
  autoload :Dsl, "tapioca/commands/dsl"
8
9
  autoload :Init, "tapioca/commands/init"
9
10
  autoload :Gem, "tapioca/commands/gem"
@@ -17,7 +17,7 @@ module Tapioca
17
17
  include Runtime::Reflection
18
18
  extend Runtime::Reflection
19
19
 
20
- ConstantType = type_member(upper: Module)
20
+ ConstantType = type_member { { upper: Module } }
21
21
 
22
22
  abstract!
23
23
 
@@ -54,7 +54,7 @@ module Tapioca
54
54
  sig { returns(T::Set[Module]) }
55
55
  def self.processable_constants
56
56
  @processable_constants ||= T.let(
57
- Set.new(gather_constants).tap(&:compare_by_identity),
57
+ T::Set[Module].new(gather_constants).compare_by_identity,
58
58
  T.nilable(T::Set[Module])
59
59
  )
60
60
  T.must(@processable_constants)
@@ -49,7 +49,7 @@ module Tapioca
49
49
  T::Array[String]
50
50
  )
51
51
 
52
- ConstantType = type_member(fixed: T.all(::AASM::ClassMethods, Class))
52
+ ConstantType = type_member { { fixed: T.all(::AASM::ClassMethods, Class) } }
53
53
 
54
54
  sig { override.void }
55
55
  def decorate
@@ -68,7 +68,7 @@ module Tapioca
68
68
  class ActionControllerHelpers < Compiler
69
69
  extend T::Sig
70
70
 
71
- ConstantType = type_member(fixed: T.class_of(::ActionController::Base))
71
+ ConstantType = type_member { { fixed: T.class_of(::ActionController::Base) } }
72
72
 
73
73
  sig { override.void }
74
74
  def decorate
@@ -36,7 +36,7 @@ module Tapioca
36
36
  class ActionMailer < Compiler
37
37
  extend T::Sig
38
38
 
39
- ConstantType = type_member(fixed: T.class_of(::ActionMailer::Base))
39
+ ConstantType = type_member { { fixed: T.class_of(::ActionMailer::Base) } }
40
40
 
41
41
  sig { override.void }
42
42
  def decorate
@@ -40,7 +40,7 @@ module Tapioca
40
40
  class ActiveJob < Compiler
41
41
  extend T::Sig
42
42
 
43
- ConstantType = type_member(fixed: T.class_of(::ActiveJob::Base))
43
+ ConstantType = type_member { { fixed: T.class_of(::ActiveJob::Base) } }
44
44
 
45
45
  sig { override.void }
46
46
  def decorate
@@ -39,7 +39,7 @@ module Tapioca
39
39
  class ActiveModelAttributes < Compiler
40
40
  extend T::Sig
41
41
 
42
- ConstantType = type_member(fixed: T.all(Class, ::ActiveModel::Attributes::ClassMethods))
42
+ ConstantType = type_member { { fixed: T.all(Class, ::ActiveModel::Attributes::ClassMethods) } }
43
43
 
44
44
  sig { override.void }
45
45
  def decorate
@@ -60,7 +60,7 @@ module Tapioca
60
60
  class ActiveModelSecurePassword < Compiler
61
61
  extend T::Sig
62
62
 
63
- ConstantType = type_member(fixed: T.all(Class, ::ActiveModel::SecurePassword::ClassMethods))
63
+ ConstantType = type_member { { fixed: T.all(Class, ::ActiveModel::SecurePassword::ClassMethods) } }
64
64
 
65
65
  sig { override.void }
66
66
  def decorate
@@ -119,7 +119,7 @@ module Tapioca
119
119
  end
120
120
  end
121
121
 
122
- ConstantType = type_member(fixed: T.class_of(ActiveRecord::Base))
122
+ ConstantType = type_member { { fixed: T.class_of(ActiveRecord::Base) } }
123
123
 
124
124
  sig { override.void }
125
125
  def decorate
@@ -101,7 +101,7 @@ module Tapioca
101
101
  extend T::Sig
102
102
  include Helpers::ActiveRecordConstantsHelper
103
103
 
104
- ConstantType = type_member(fixed: T.class_of(ActiveRecord::Base))
104
+ ConstantType = type_member { { fixed: T.class_of(ActiveRecord::Base) } }
105
105
 
106
106
  sig { override.void }
107
107
  def decorate
@@ -58,7 +58,7 @@ module Tapioca
58
58
  class ActiveRecordEnum < Compiler
59
59
  extend T::Sig
60
60
 
61
- ConstantType = type_member(fixed: T.class_of(::ActiveRecord::Base))
61
+ ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
62
62
 
63
63
  sig { override.void }
64
64
  def decorate
@@ -38,7 +38,7 @@ module Tapioca
38
38
  class ActiveRecordFixtures < Compiler
39
39
  extend T::Sig
40
40
 
41
- ConstantType = type_member(fixed: T.class_of(ActiveSupport::TestCase))
41
+ ConstantType = type_member { { fixed: T.class_of(ActiveSupport::TestCase) } }
42
42
 
43
43
  sig { override.void }
44
44
  def decorate
@@ -60,6 +60,8 @@ module Tapioca
60
60
 
61
61
  sig { override.returns(T::Enumerable[Module]) }
62
62
  def self.gather_constants
63
+ return [] unless Rails.application
64
+
63
65
  [ActiveSupport::TestCase]
64
66
  end
65
67
 
@@ -118,7 +118,7 @@ module Tapioca
118
118
  # sig { returns(T::Array[::Post]) }
119
119
  # def to_ary; end
120
120
  #
121
- # Elem = type_member(fixed: ::Post)
121
+ # Elem = type_member { { fixed: ::Post } }
122
122
  # end
123
123
  #
124
124
  # class PrivateCollectionProxy < ::ActiveRecord::Associations::CollectionProxy
@@ -141,7 +141,7 @@ module Tapioca
141
141
  # sig { returns(T::Array[::Post]) }
142
142
  # def to_ary; end
143
143
  #
144
- # Elem = type_member(fixed: ::Post)
144
+ # Elem = type_member { { fixed: ::Post } }
145
145
  # end
146
146
  # end
147
147
  # ~~~
@@ -150,7 +150,7 @@ module Tapioca
150
150
  include Helpers::ActiveRecordConstantsHelper
151
151
  include SorbetHelper
152
152
 
153
- ConstantType = type_member(fixed: T.class_of(::ActiveRecord::Base))
153
+ ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
154
154
 
155
155
  sig { override.void }
156
156
  def decorate
@@ -253,7 +253,7 @@ module Tapioca
253
253
  model.create_class(RelationClassName, superclass_name: superclass) do |klass|
254
254
  klass.create_include(CommonRelationMethodsModuleName)
255
255
  klass.create_include(RelationMethodsModuleName)
256
- klass.create_constant("Elem", value: "type_member(fixed: #{constant_name})")
256
+ klass.create_type_variable("Elem", type: "type_member", fixed: constant_name)
257
257
 
258
258
  klass.create_method("to_ary", return_type: "T::Array[#{constant_name}]")
259
259
  end
@@ -269,7 +269,7 @@ module Tapioca
269
269
  model.create_class(AssociationRelationClassName, superclass_name: superclass) do |klass|
270
270
  klass.create_include(CommonRelationMethodsModuleName)
271
271
  klass.create_include(AssociationRelationMethodsModuleName)
272
- klass.create_constant("Elem", value: "type_member(fixed: #{constant_name})")
272
+ klass.create_type_variable("Elem", type: "type_member", fixed: constant_name)
273
273
 
274
274
  klass.create_method("to_ary", return_type: "T::Array[#{constant_name}]")
275
275
  end
@@ -281,7 +281,7 @@ module Tapioca
281
281
  def create_relation_where_chain_class(model)
282
282
  model.create_class(RelationWhereChainClassName, superclass_name: RelationClassName) do |klass|
283
283
  create_where_chain_methods(klass, RelationClassName)
284
- klass.create_constant("Elem", value: "type_member(fixed: #{constant_name})")
284
+ klass.create_type_variable("Elem", type: "type_member", fixed: constant_name)
285
285
  end
286
286
  end
287
287
 
@@ -292,7 +292,7 @@ module Tapioca
292
292
  superclass_name: AssociationRelationClassName
293
293
  ) do |klass|
294
294
  create_where_chain_methods(klass, AssociationRelationClassName)
295
- klass.create_constant("Elem", value: "type_member(fixed: #{constant_name})")
295
+ klass.create_type_variable("Elem", type: "type_member", fixed: constant_name)
296
296
  end
297
297
  end
298
298
 
@@ -329,7 +329,7 @@ module Tapioca
329
329
  model.create_class(AssociationsCollectionProxyClassName, superclass_name: superclass) do |klass|
330
330
  klass.create_include(CommonRelationMethodsModuleName)
331
331
  klass.create_include(AssociationRelationMethodsModuleName)
332
- klass.create_constant("Elem", value: "type_member(fixed: #{constant_name})")
332
+ klass.create_type_variable("Elem", type: "type_member", fixed: constant_name)
333
333
 
334
334
  klass.create_method("to_ary", return_type: "T::Array[#{constant_name}]")
335
335
  create_collection_proxy_methods(klass)
@@ -46,7 +46,7 @@ module Tapioca
46
46
  extend T::Sig
47
47
  include Helpers::ActiveRecordConstantsHelper
48
48
 
49
- ConstantType = type_member(fixed: T.class_of(::ActiveRecord::Base))
49
+ ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
50
50
 
51
51
  sig { override.void }
52
52
  def decorate
@@ -90,7 +90,7 @@ module Tapioca
90
90
  class ActiveRecordTypedStore < Compiler
91
91
  extend T::Sig
92
92
 
93
- ConstantType = type_member(fixed: T.class_of(::ActiveRecord::Base))
93
+ ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
94
94
 
95
95
  sig { override.void }
96
96
  def decorate
@@ -61,7 +61,7 @@ module Tapioca
61
61
  class ActiveResource < Compiler
62
62
  extend T::Sig
63
63
 
64
- ConstantType = type_member(fixed: T.class_of(::ActiveResource::Base))
64
+ ConstantType = type_member { { fixed: T.class_of(::ActiveResource::Base) } }
65
65
 
66
66
  sig { override.void }
67
67
  def decorate