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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/README.md +491 -73
- data/lib/tapioca/cli.rb +40 -3
- data/lib/tapioca/commands/annotations.rb +154 -0
- data/lib/tapioca/commands/dsl.rb +20 -1
- data/lib/tapioca/commands/gem.rb +17 -57
- data/lib/tapioca/commands/init.rb +1 -0
- data/lib/tapioca/commands/todo.rb +4 -2
- data/lib/tapioca/commands.rb +1 -0
- data/lib/tapioca/dsl/compiler.rb +2 -2
- data/lib/tapioca/dsl/compilers/aasm.rb +1 -1
- data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +1 -1
- data/lib/tapioca/dsl/compilers/action_mailer.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_job.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_model_attributes.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_model_secure_password.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_record_associations.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_record_columns.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_record_enum.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +3 -1
- data/lib/tapioca/dsl/compilers/active_record_relations.rb +8 -8
- data/lib/tapioca/dsl/compilers/active_record_scope.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_resource.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_storage.rb +6 -2
- data/lib/tapioca/dsl/compilers/active_support_concern.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_support_current_attributes.rb +1 -1
- data/lib/tapioca/dsl/compilers/config.rb +2 -2
- data/lib/tapioca/dsl/compilers/frozen_record.rb +1 -1
- data/lib/tapioca/dsl/compilers/identity_cache.rb +1 -1
- data/lib/tapioca/dsl/compilers/mixed_in_class_attributes.rb +1 -1
- data/lib/tapioca/dsl/compilers/protobuf.rb +27 -3
- data/lib/tapioca/dsl/compilers/rails_generators.rb +1 -1
- data/lib/tapioca/dsl/compilers/sidekiq_worker.rb +1 -1
- data/lib/tapioca/dsl/compilers/smart_properties.rb +1 -1
- data/lib/tapioca/dsl/compilers/state_machines.rb +1 -1
- data/lib/tapioca/dsl/compilers/url_helpers.rb +5 -2
- data/lib/tapioca/dsl/helpers/param_helper.rb +4 -1
- data/lib/tapioca/dsl/pipeline.rb +32 -1
- data/lib/tapioca/dsl.rb +6 -0
- data/lib/tapioca/executor.rb +4 -46
- data/lib/tapioca/gem/listeners/methods.rb +26 -1
- data/lib/tapioca/gem/listeners/sorbet_props.rb +1 -1
- data/lib/tapioca/gem/listeners/sorbet_required_ancestors.rb +1 -0
- data/lib/tapioca/gem/listeners/sorbet_signatures.rb +1 -1
- data/lib/tapioca/gem/pipeline.rb +5 -1
- data/lib/tapioca/gemfile.rb +50 -3
- data/lib/tapioca/helpers/config_helper.rb +13 -0
- data/lib/tapioca/helpers/rbi_helper.rb +114 -7
- data/lib/tapioca/helpers/shims_helper.rb +36 -8
- data/lib/tapioca/helpers/signatures_helper.rb +17 -0
- data/lib/tapioca/helpers/sorbet_helper.rb +5 -11
- data/lib/tapioca/helpers/test/content.rb +1 -0
- data/lib/tapioca/helpers/test/dsl_compiler.rb +1 -0
- data/lib/tapioca/helpers/test/template.rb +1 -0
- data/lib/tapioca/helpers/type_variable_helper.rb +43 -0
- data/lib/tapioca/internal.rb +4 -1
- data/lib/tapioca/rbi_ext/model.rb +14 -2
- data/lib/tapioca/repo_index.rb +41 -0
- data/lib/tapioca/runtime/generic_type_registry.rb +4 -2
- data/lib/tapioca/runtime/loader.rb +3 -0
- data/lib/tapioca/runtime/reflection.rb +17 -13
- data/lib/tapioca/sorbet_ext/generic_name_patch.rb +38 -21
- data/lib/tapioca/static/symbol_table_parser.rb +2 -0
- data/lib/tapioca/version.rb +1 -1
- data/lib/tapioca.rb +5 -0
- 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: "
|
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:
|
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
|
-
|
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
|
data/lib/tapioca/commands/dsl.rb
CHANGED
@@ -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
|
data/lib/tapioca/commands/gem.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
@@ -74,10 +74,12 @@ module Tapioca
|
|
74
74
|
.each_line
|
75
75
|
.map do |line|
|
76
76
|
next if line.include?("<")
|
77
|
-
|
78
|
-
line.strip
|
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
|
data/lib/tapioca/commands.rb
CHANGED
data/lib/tapioca/dsl/compiler.rb
CHANGED
@@ -17,7 +17,7 @@ module Tapioca
|
|
17
17
|
include Runtime::Reflection
|
18
18
|
extend Runtime::Reflection
|
19
19
|
|
20
|
-
ConstantType = type_member
|
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).
|
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)
|
@@ -68,7 +68,7 @@ module Tapioca
|
|
68
68
|
class ActionControllerHelpers < Compiler
|
69
69
|
extend T::Sig
|
70
70
|
|
71
|
-
ConstantType = type_member
|
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
|
39
|
+
ConstantType = type_member { { fixed: T.class_of(::ActionMailer::Base) } }
|
40
40
|
|
41
41
|
sig { override.void }
|
42
42
|
def decorate
|
@@ -39,7 +39,7 @@ module Tapioca
|
|
39
39
|
class ActiveModelAttributes < Compiler
|
40
40
|
extend T::Sig
|
41
41
|
|
42
|
-
ConstantType = type_member
|
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
|
63
|
+
ConstantType = type_member { { fixed: T.all(Class, ::ActiveModel::SecurePassword::ClassMethods) } }
|
64
64
|
|
65
65
|
sig { override.void }
|
66
66
|
def decorate
|
@@ -101,7 +101,7 @@ module Tapioca
|
|
101
101
|
extend T::Sig
|
102
102
|
include Helpers::ActiveRecordConstantsHelper
|
103
103
|
|
104
|
-
ConstantType = type_member
|
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
|
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
|
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
|
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
|
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
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|
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
|
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
|
64
|
+
ConstantType = type_member { { fixed: T.class_of(::ActiveResource::Base) } }
|
65
65
|
|
66
66
|
sig { override.void }
|
67
67
|
def decorate
|