tapioca 0.11.6 → 0.11.7
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/README.md +62 -56
- data/lib/tapioca/bundler_ext/auto_require_hook.rb +69 -0
- data/lib/tapioca/cli.rb +10 -0
- data/lib/tapioca/commands/dsl.rb +6 -1
- data/lib/tapioca/commands/gem.rb +6 -1
- data/lib/tapioca/dsl/compiler.rb +3 -3
- data/lib/tapioca/dsl/compilers/aasm.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_model_attributes.rb +3 -1
- data/lib/tapioca/dsl/compilers/active_model_secure_password.rb +3 -1
- data/lib/tapioca/dsl/compilers/active_record_delegated_types.rb +2 -1
- data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +16 -7
- data/lib/tapioca/dsl/compilers/kredis.rb +3 -1
- data/lib/tapioca/dsl/compilers/protobuf.rb +17 -7
- data/lib/tapioca/gem/listeners/methods.rb +23 -2
- data/lib/tapioca/gem/listeners/sorbet_helpers.rb +3 -4
- data/lib/tapioca/gem/listeners/sorbet_type_variables.rb +20 -7
- data/lib/tapioca/gem/pipeline.rb +2 -2
- data/lib/tapioca/gemfile.rb +10 -48
- data/lib/tapioca/helpers/rbi_files_helper.rb +1 -1
- data/lib/tapioca/helpers/sorbet_helper.rb +1 -0
- data/lib/tapioca/internal.rb +1 -0
- data/lib/tapioca/loaders/dsl.rb +16 -5
- data/lib/tapioca/loaders/gem.rb +7 -3
- data/lib/tapioca/loaders/loader.rb +22 -6
- data/lib/tapioca/runtime/generic_type_registry.rb +1 -1
- data/lib/tapioca/runtime/reflection.rb +21 -5
- data/lib/tapioca/sorbet_ext/backcompat_patches.rb +24 -0
- data/lib/tapioca/sorbet_ext/generic_name_patch.rb +19 -0
- data/lib/tapioca/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 68b1a51d995ed5925df2983b0fdc55ef14bdfb828780077035048f1a6305ad74
|
|
4
|
+
data.tar.gz: 9689fa2965d90459e47618b2d41df0e24acdb9599d3552205ed973fa37126c9b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 78cfdeb935bd82157c0f98344af6e131f5c5d0b256076ac69b1518f044f08ace764cfe7efe153928c7209a451ce194ae7d2ac82cebf68c1aed937b3016ba6cb3
|
|
7
|
+
data.tar.gz: d51e8ca0aafb1764efa553387d2569aec765c0eb6d5ac8344843b131d75fa6b2daa5bca6daa4304229eb6313ef244752fb1ec66c2c10d5868ee8983174bf5f3e
|
data/README.md
CHANGED
|
@@ -163,36 +163,38 @@ Usage:
|
|
|
163
163
|
tapioca gem [gem...]
|
|
164
164
|
|
|
165
165
|
Options:
|
|
166
|
-
--out, -o,
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
--pre, -b,
|
|
172
|
-
--post, -a,
|
|
173
|
-
|
|
174
|
-
-x,
|
|
175
|
-
--typed, -t, [--typed-overrides=gem:level [gem:level ...]]
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
-w,
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
--dsl-dir,
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
-e,
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
-
|
|
166
|
+
--out, -o, [--outdir=directory] # The output directory for generated gem RBI files
|
|
167
|
+
# Default: sorbet/rbi/gems
|
|
168
|
+
[--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
|
|
169
|
+
# Default: true
|
|
170
|
+
[--all], [--no-all] # Regenerate RBI files for all gems
|
|
171
|
+
--pre, -b, [--prerequire=file] # A file to be required before Bundler.require is called
|
|
172
|
+
--post, -a, [--postrequire=file] # A file to be required after Bundler.require is called
|
|
173
|
+
# Default: sorbet/tapioca/require.rb
|
|
174
|
+
-x, [--exclude=gem [gem ...]] # Exclude the given gem(s) from RBI generation
|
|
175
|
+
--typed, -t, [--typed-overrides=gem:level [gem:level ...]] # Override for typed sigils for generated gem RBIs
|
|
176
|
+
# Default: {"activesupport"=>"false"}
|
|
177
|
+
[--verify], [--no-verify] # Verify RBIs are up-to-date
|
|
178
|
+
[--doc], [--no-doc] # Include YARD documentation from sources when generating RBIs. Warning: this might be slow
|
|
179
|
+
# Default: true
|
|
180
|
+
[--loc], [--no-loc] # Include comments with source location when generating RBIs
|
|
181
|
+
# Default: true
|
|
182
|
+
[--exported-gem-rbis], [--no-exported-gem-rbis] # Include RBIs found in the `rbi/` directory of the gem
|
|
183
|
+
# Default: true
|
|
184
|
+
-w, [--workers=N] # Number of parallel workers to use when generating RBIs (default: auto)
|
|
185
|
+
[--auto-strictness], [--no-auto-strictness] # Autocorrect strictness in gem RBIs in case of conflict with the DSL RBIs
|
|
186
|
+
# Default: true
|
|
187
|
+
--dsl-dir, [--dsl-dir=directory] # The DSL directory used to correct gems strictnesses
|
|
188
|
+
# Default: sorbet/rbi/dsl
|
|
189
|
+
[--rbi-max-line-length=N] # Set the max line length of generated RBIs. Signatures longer than the max line length will be wrapped
|
|
190
|
+
# Default: 120
|
|
191
|
+
-e, [--environment=ENVIRONMENT] # The Rack/Rails environment to use when generating RBIs
|
|
192
|
+
# Default: development
|
|
193
|
+
[--halt-upon-load-error], [--no-halt-upon-load-error] # Halt upon a load error while loading the Rails application
|
|
194
|
+
# Default: true
|
|
195
|
+
-c, [--config=<config file path>] # Path to the Tapioca configuration file
|
|
196
|
+
# Default: sorbet/tapioca/config.yml
|
|
197
|
+
-V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
|
|
196
198
|
|
|
197
199
|
generate RBIs from gems
|
|
198
200
|
```
|
|
@@ -347,16 +349,16 @@ Usage:
|
|
|
347
349
|
tapioca annotations
|
|
348
350
|
|
|
349
351
|
Options:
|
|
350
|
-
|
|
352
|
+
[--sources=one two three] # URIs of the sources to pull gem RBI annotations from
|
|
351
353
|
# Default: ["https://raw.githubusercontent.com/Shopify/rbi-central/main"]
|
|
352
|
-
|
|
354
|
+
[--netrc], [--no-netrc] # Use .netrc to authenticate to private sources
|
|
353
355
|
# Default: true
|
|
354
|
-
|
|
355
|
-
|
|
356
|
+
[--netrc-file=NETRC_FILE] # Path to .netrc file
|
|
357
|
+
[--auth=AUTH] # HTTP authorization header for private sources
|
|
356
358
|
--typed, -t, [--typed-overrides=gem:level [gem:level ...]] # Override for typed sigils for pulled annotations
|
|
357
|
-
-c,
|
|
359
|
+
-c, [--config=<config file path>] # Path to the Tapioca configuration file
|
|
358
360
|
# Default: sorbet/tapioca/config.yml
|
|
359
|
-
-V,
|
|
361
|
+
-V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
|
|
360
362
|
|
|
361
363
|
Pull gem RBI annotations from remote sources
|
|
362
364
|
```
|
|
@@ -458,26 +460,28 @@ Usage:
|
|
|
458
460
|
tapioca dsl [constant...]
|
|
459
461
|
|
|
460
462
|
Options:
|
|
461
|
-
--out, -o, [--outdir=directory]
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
-q,
|
|
469
|
-
-w,
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
-e,
|
|
474
|
-
|
|
475
|
-
-l,
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
-
|
|
463
|
+
--out, -o, [--outdir=directory] # The output directory for generated DSL RBI files
|
|
464
|
+
# Default: sorbet/rbi/dsl
|
|
465
|
+
[--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
|
|
466
|
+
# Default: true
|
|
467
|
+
[--only=compiler [compiler ...]] # Only run supplied DSL compiler(s)
|
|
468
|
+
[--exclude=compiler [compiler ...]] # Exclude supplied DSL compiler(s)
|
|
469
|
+
[--verify], [--no-verify] # Verifies RBIs are up-to-date
|
|
470
|
+
-q, [--quiet], [--no-quiet] # Suppresses file creation output
|
|
471
|
+
-w, [--workers=N] # Number of parallel workers to use when generating RBIs (default: 2)
|
|
472
|
+
# Default: 2
|
|
473
|
+
[--rbi-max-line-length=N] # Set the max line length of generated RBIs. Signatures longer than the max line length will be wrapped
|
|
474
|
+
# Default: 120
|
|
475
|
+
-e, [--environment=ENVIRONMENT] # The Rack/Rails environment to use when generating RBIs
|
|
476
|
+
# Default: development
|
|
477
|
+
-l, [--list-compilers], [--no-list-compilers] # List all loaded compilers
|
|
478
|
+
[--app-root=APP_ROOT] # The path to the Rails application
|
|
479
|
+
# Default: .
|
|
480
|
+
[--halt-upon-load-error], [--no-halt-upon-load-error] # Halt upon a load error while loading the Rails application
|
|
481
|
+
# Default: true
|
|
482
|
+
-c, [--config=<config file path>] # Path to the Tapioca configuration file
|
|
483
|
+
# Default: sorbet/tapioca/config.yml
|
|
484
|
+
-V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
|
|
481
485
|
|
|
482
486
|
generate RBIs for dynamic methods
|
|
483
487
|
```
|
|
@@ -827,6 +831,7 @@ dsl:
|
|
|
827
831
|
environment: development
|
|
828
832
|
list_compilers: false
|
|
829
833
|
app_root: "."
|
|
834
|
+
halt_upon_load_error: true
|
|
830
835
|
gem:
|
|
831
836
|
outdir: sorbet/rbi/gems
|
|
832
837
|
file_header: true
|
|
@@ -845,6 +850,7 @@ gem:
|
|
|
845
850
|
dsl_dir: sorbet/rbi/dsl
|
|
846
851
|
rbi_max_line_length: 120
|
|
847
852
|
environment: development
|
|
853
|
+
halt_upon_load_error: true
|
|
848
854
|
check_shims:
|
|
849
855
|
gem_rbi_dir: sorbet/rbi/gems
|
|
850
856
|
dsl_rbi_dir: sorbet/rbi/dsl
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Tapioca
|
|
5
|
+
module BundlerExt
|
|
6
|
+
# This is a module that gets prepended to `Bundler::Dependency` and
|
|
7
|
+
# makes sure even gems marked as `require: false` are required during
|
|
8
|
+
# `Bundler.require`.
|
|
9
|
+
module AutoRequireHook
|
|
10
|
+
extend T::Sig
|
|
11
|
+
extend T::Helpers
|
|
12
|
+
|
|
13
|
+
requires_ancestor { ::Bundler::Dependency }
|
|
14
|
+
|
|
15
|
+
@exclude = T.let([], T::Array[String])
|
|
16
|
+
@enabled = T.let(false, T::Boolean)
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
extend T::Sig
|
|
20
|
+
|
|
21
|
+
sig { params(name: T.untyped).returns(T::Boolean) }
|
|
22
|
+
def excluded?(name)
|
|
23
|
+
@exclude.include?(name)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def enabled?
|
|
27
|
+
@enabled
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
sig do
|
|
31
|
+
type_parameters(:Result).params(
|
|
32
|
+
exclude: T::Array[String],
|
|
33
|
+
blk: T.proc.returns(T.type_parameter(:Result)),
|
|
34
|
+
).returns(T.type_parameter(:Result))
|
|
35
|
+
end
|
|
36
|
+
def override_require_false(exclude:, &blk)
|
|
37
|
+
@enabled = true
|
|
38
|
+
@exclude = exclude
|
|
39
|
+
blk.call
|
|
40
|
+
ensure
|
|
41
|
+
@enabled = false
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
sig { returns(T.untyped).checked(:never) }
|
|
46
|
+
def autorequire
|
|
47
|
+
value = super
|
|
48
|
+
|
|
49
|
+
# If autorequire is not enabled, we don't want to force require gems
|
|
50
|
+
return value unless AutoRequireHook.enabled?
|
|
51
|
+
|
|
52
|
+
# If the gem is excluded, we don't want to force require it, in case
|
|
53
|
+
# it has side-effects users don't want. For example, `fakefs` gem, if
|
|
54
|
+
# loaded, takes over filesystem operations.
|
|
55
|
+
return value if AutoRequireHook.excluded?(name)
|
|
56
|
+
|
|
57
|
+
# If a gem is marked as `require: false`, then its `autorequire`
|
|
58
|
+
# value will be `[]`. But, we want those gems to be loaded for our
|
|
59
|
+
# purposes as well, so we return `nil` in those cases, instead, which
|
|
60
|
+
# means `require: true`.
|
|
61
|
+
return nil if value == []
|
|
62
|
+
|
|
63
|
+
value
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
::Bundler::Dependency.prepend(self)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
data/lib/tapioca/cli.rb
CHANGED
|
@@ -130,6 +130,10 @@ module Tapioca
|
|
|
130
130
|
type: :string,
|
|
131
131
|
desc: "The path to the Rails application",
|
|
132
132
|
default: "."
|
|
133
|
+
option :halt_upon_load_error,
|
|
134
|
+
type: :boolean,
|
|
135
|
+
desc: "Halt upon a load error while loading the Rails application",
|
|
136
|
+
default: true
|
|
133
137
|
def dsl(*constant_or_paths)
|
|
134
138
|
set_environment(options)
|
|
135
139
|
|
|
@@ -150,6 +154,7 @@ module Tapioca
|
|
|
150
154
|
number_of_workers: options[:workers],
|
|
151
155
|
rbi_formatter: rbi_formatter(options),
|
|
152
156
|
app_root: options[:app_root],
|
|
157
|
+
halt_upon_load_error: options[:halt_upon_load_error],
|
|
153
158
|
)
|
|
154
159
|
|
|
155
160
|
Tapioca.silence_warnings do
|
|
@@ -235,6 +240,10 @@ module Tapioca
|
|
|
235
240
|
type: :string,
|
|
236
241
|
desc: "The Rack/Rails environment to use when generating RBIs",
|
|
237
242
|
default: DEFAULT_ENVIRONMENT
|
|
243
|
+
option :halt_upon_load_error,
|
|
244
|
+
type: :boolean,
|
|
245
|
+
desc: "Halt upon a load error while loading the Rails application",
|
|
246
|
+
default: true
|
|
238
247
|
def gem(*gems)
|
|
239
248
|
Tapioca.silence_warnings do
|
|
240
249
|
set_environment(options)
|
|
@@ -257,6 +266,7 @@ module Tapioca
|
|
|
257
266
|
auto_strictness: options[:auto_strictness],
|
|
258
267
|
dsl_dir: options[:dsl_dir],
|
|
259
268
|
rbi_formatter: rbi_formatter(options),
|
|
269
|
+
halt_upon_load_error: options[:halt_upon_load_error],
|
|
260
270
|
)
|
|
261
271
|
|
|
262
272
|
raise MalformattedArgumentError, "Options '--all' and '--verify' are mutually exclusive" if all && verify
|
data/lib/tapioca/commands/dsl.rb
CHANGED
|
@@ -24,6 +24,7 @@ module Tapioca
|
|
|
24
24
|
gem_dir: String,
|
|
25
25
|
rbi_formatter: RBIFormatter,
|
|
26
26
|
app_root: String,
|
|
27
|
+
halt_upon_load_error: T::Boolean,
|
|
27
28
|
).void
|
|
28
29
|
end
|
|
29
30
|
def initialize(
|
|
@@ -41,7 +42,8 @@ module Tapioca
|
|
|
41
42
|
auto_strictness: true,
|
|
42
43
|
gem_dir: DEFAULT_GEM_DIR,
|
|
43
44
|
rbi_formatter: DEFAULT_RBI_FORMATTER,
|
|
44
|
-
app_root: "."
|
|
45
|
+
app_root: ".",
|
|
46
|
+
halt_upon_load_error: true
|
|
45
47
|
)
|
|
46
48
|
@requested_constants = requested_constants
|
|
47
49
|
@requested_paths = requested_paths
|
|
@@ -58,6 +60,7 @@ module Tapioca
|
|
|
58
60
|
@gem_dir = gem_dir
|
|
59
61
|
@rbi_formatter = rbi_formatter
|
|
60
62
|
@app_root = app_root
|
|
63
|
+
@halt_upon_load_error = halt_upon_load_error
|
|
61
64
|
|
|
62
65
|
super()
|
|
63
66
|
end
|
|
@@ -68,6 +71,7 @@ module Tapioca
|
|
|
68
71
|
tapioca_path: @tapioca_path,
|
|
69
72
|
eager_load: @requested_constants.empty? && @requested_paths.empty?,
|
|
70
73
|
app_root: @app_root,
|
|
74
|
+
halt_upon_load_error: @halt_upon_load_error,
|
|
71
75
|
)
|
|
72
76
|
|
|
73
77
|
pipeline = create_pipeline
|
|
@@ -95,6 +99,7 @@ module Tapioca
|
|
|
95
99
|
tapioca_path: @tapioca_path,
|
|
96
100
|
eager_load: @requested_constants.empty? && @requested_paths.empty?,
|
|
97
101
|
app_root: @app_root,
|
|
102
|
+
halt_upon_load_error: @halt_upon_load_error,
|
|
98
103
|
)
|
|
99
104
|
|
|
100
105
|
if @should_verify
|
data/lib/tapioca/commands/gem.rb
CHANGED
|
@@ -23,6 +23,7 @@ module Tapioca
|
|
|
23
23
|
auto_strictness: T::Boolean,
|
|
24
24
|
dsl_dir: String,
|
|
25
25
|
rbi_formatter: RBIFormatter,
|
|
26
|
+
halt_upon_load_error: T::Boolean,
|
|
26
27
|
).void
|
|
27
28
|
end
|
|
28
29
|
def initialize(
|
|
@@ -39,7 +40,8 @@ module Tapioca
|
|
|
39
40
|
number_of_workers: nil,
|
|
40
41
|
auto_strictness: true,
|
|
41
42
|
dsl_dir: DEFAULT_DSL_DIR,
|
|
42
|
-
rbi_formatter: DEFAULT_RBI_FORMATTER
|
|
43
|
+
rbi_formatter: DEFAULT_RBI_FORMATTER,
|
|
44
|
+
halt_upon_load_error: true
|
|
43
45
|
)
|
|
44
46
|
@gem_names = gem_names
|
|
45
47
|
@exclude = exclude
|
|
@@ -61,6 +63,7 @@ module Tapioca
|
|
|
61
63
|
@include_doc = T.let(include_doc, T::Boolean)
|
|
62
64
|
@include_loc = T.let(include_loc, T::Boolean)
|
|
63
65
|
@include_exported_rbis = include_exported_rbis
|
|
66
|
+
@halt_upon_load_error = halt_upon_load_error
|
|
64
67
|
end
|
|
65
68
|
|
|
66
69
|
sig { override.void }
|
|
@@ -70,6 +73,7 @@ module Tapioca
|
|
|
70
73
|
prerequire: @prerequire,
|
|
71
74
|
postrequire: @postrequire,
|
|
72
75
|
default_command: default_command(:require),
|
|
76
|
+
halt_upon_load_error: @halt_upon_load_error,
|
|
73
77
|
)
|
|
74
78
|
|
|
75
79
|
gem_queue = gems_to_generate(@gem_names).reject { |gem| @exclude.include?(gem.name) }
|
|
@@ -245,6 +249,7 @@ module Tapioca
|
|
|
245
249
|
prerequire: @prerequire,
|
|
246
250
|
postrequire: @postrequire,
|
|
247
251
|
default_command: default_command(:require),
|
|
252
|
+
halt_upon_load_error: @halt_upon_load_error,
|
|
248
253
|
)
|
|
249
254
|
|
|
250
255
|
Executor.new(gems, number_of_workers: @number_of_workers).run_in_parallel do |gem_name|
|
data/lib/tapioca/dsl/compiler.rb
CHANGED
|
@@ -43,10 +43,10 @@ module Tapioca
|
|
|
43
43
|
|
|
44
44
|
private
|
|
45
45
|
|
|
46
|
-
sig { returns(T::Enumerable[Class]) }
|
|
46
|
+
sig { returns(T::Enumerable[T::Class[T.anything]]) }
|
|
47
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
|
|
48
|
+
@all_classes = T.let(@all_classes, T.nilable(T::Enumerable[T::Class[T.anything]]))
|
|
49
|
+
@all_classes ||= T.cast(ObjectSpace.each_object(Class), T::Enumerable[T::Class[T.anything]]).each
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
sig { returns(T::Enumerable[Module]) }
|
|
@@ -39,7 +39,9 @@ module Tapioca
|
|
|
39
39
|
class ActiveModelAttributes < Compiler
|
|
40
40
|
extend T::Sig
|
|
41
41
|
|
|
42
|
-
ConstantType = type_member
|
|
42
|
+
ConstantType = type_member do
|
|
43
|
+
{ fixed: T.all(T::Class[::ActiveModel::Attributes], ::ActiveModel::Attributes::ClassMethods) }
|
|
44
|
+
end
|
|
43
45
|
|
|
44
46
|
sig { override.void }
|
|
45
47
|
def decorate
|
|
@@ -60,7 +60,9 @@ module Tapioca
|
|
|
60
60
|
class ActiveModelSecurePassword < Compiler
|
|
61
61
|
extend T::Sig
|
|
62
62
|
|
|
63
|
-
ConstantType = type_member
|
|
63
|
+
ConstantType = type_member do
|
|
64
|
+
{ fixed: T.all(T::Class[::ActiveModel::SecurePassword], ::ActiveModel::SecurePassword::ClassMethods) }
|
|
65
|
+
end
|
|
64
66
|
|
|
65
67
|
sig { override.void }
|
|
66
68
|
def decorate
|
|
@@ -110,10 +110,11 @@ module Tapioca
|
|
|
110
110
|
return_type: "ActiveSupport::StringInquirer",
|
|
111
111
|
)
|
|
112
112
|
|
|
113
|
+
return_type = sorbet_supports?(:generic_class) ? "T::Class[T.anything]" : "Class"
|
|
113
114
|
mod.create_method(
|
|
114
115
|
"#{role}_class",
|
|
115
116
|
parameters: [],
|
|
116
|
-
return_type:
|
|
117
|
+
return_type: return_type,
|
|
117
118
|
)
|
|
118
119
|
|
|
119
120
|
mod.create_method(
|
|
@@ -70,15 +70,24 @@ module Tapioca
|
|
|
70
70
|
|
|
71
71
|
private
|
|
72
72
|
|
|
73
|
-
sig { returns(Class) }
|
|
73
|
+
sig { returns(T::Class[ActiveRecord::TestFixtures]) }
|
|
74
74
|
def fixture_loader
|
|
75
75
|
@fixture_loader ||= T.let(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
T.cast(
|
|
77
|
+
Class.new do
|
|
78
|
+
T.unsafe(self).include(ActiveRecord::TestFixtures)
|
|
79
|
+
|
|
80
|
+
T.unsafe(self).fixture_path = Rails.root.join("test", "fixtures")
|
|
81
|
+
# https://github.com/rails/rails/blob/7c70791470fc517deb7c640bead9f1b47efb5539/activerecord/lib/active_record/test_fixtures.rb#L46
|
|
82
|
+
singleton_class.define_method(:file_fixture_path) do
|
|
83
|
+
Rails.root.join("test", "fixtures", "files")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
T.unsafe(self).fixtures(:all)
|
|
87
|
+
end,
|
|
88
|
+
T::Class[ActiveRecord::TestFixtures],
|
|
89
|
+
),
|
|
90
|
+
T.nilable(T::Class[ActiveRecord::TestFixtures]),
|
|
82
91
|
)
|
|
83
92
|
end
|
|
84
93
|
|
|
@@ -70,7 +70,9 @@ module Tapioca
|
|
|
70
70
|
class Kredis < Compiler
|
|
71
71
|
extend T::Sig
|
|
72
72
|
|
|
73
|
-
ConstantType = type_member
|
|
73
|
+
ConstantType = type_member do
|
|
74
|
+
{ fixed: T.all(T::Class[::Kredis::Attributes], ::Kredis::Attributes::ClassMethods, Extensions::Kredis) }
|
|
75
|
+
end
|
|
74
76
|
|
|
75
77
|
sig { override.void }
|
|
76
78
|
def decorate
|
|
@@ -78,7 +78,7 @@ module Tapioca
|
|
|
78
78
|
|
|
79
79
|
extend T::Sig
|
|
80
80
|
|
|
81
|
-
ConstantType = type_member { { fixed:
|
|
81
|
+
ConstantType = type_member { { fixed: T::Class[T.anything] } }
|
|
82
82
|
|
|
83
83
|
FIELD_RE = /^[a-z_][a-zA-Z0-9_]*$/
|
|
84
84
|
|
|
@@ -206,7 +206,7 @@ module Tapioca
|
|
|
206
206
|
# > field, even if it was not defined in the enum.
|
|
207
207
|
"T.any(Symbol, Integer)"
|
|
208
208
|
when :message
|
|
209
|
-
descriptor.subtype.msgclass.name
|
|
209
|
+
descriptor.subtype.msgclass.name || "T.untyped"
|
|
210
210
|
when :int32, :int64, :uint32, :uint64
|
|
211
211
|
"Integer"
|
|
212
212
|
when :double, :float
|
|
@@ -225,14 +225,24 @@ module Tapioca
|
|
|
225
225
|
descriptor.label == :optional && descriptor.type == :message
|
|
226
226
|
end
|
|
227
227
|
|
|
228
|
+
sig { params(descriptor: Google::Protobuf::FieldDescriptor).returns(T::Boolean) }
|
|
229
|
+
def map_type?(descriptor)
|
|
230
|
+
# Defensively make sure that we are dealing with a repeated field
|
|
231
|
+
return false unless descriptor.label == :repeated
|
|
232
|
+
|
|
233
|
+
# Try to create a new instance with the field that maps to the descriptor name
|
|
234
|
+
# being assinged a hash value. If this goes through, then it's a map type.
|
|
235
|
+
constant.new(**{ descriptor.name => {} })
|
|
236
|
+
true
|
|
237
|
+
rescue ArgumentError
|
|
238
|
+
# This means the descriptor is not a map type
|
|
239
|
+
false
|
|
240
|
+
end
|
|
241
|
+
|
|
228
242
|
sig { params(descriptor: Google::Protobuf::FieldDescriptor).returns(Field) }
|
|
229
243
|
def field_of(descriptor)
|
|
230
244
|
if descriptor.label == :repeated
|
|
231
|
-
|
|
232
|
-
# how Google names map entries.
|
|
233
|
-
# https://github.com/protocolbuffers/protobuf/blob/f82e26/ruby/ext/google/protobuf_c/defs.c#L1963-L1966
|
|
234
|
-
if descriptor.submsg_name.to_s.end_with?("_MapEntry_#{descriptor.name}") ||
|
|
235
|
-
descriptor.submsg_name.to_s.end_with?("FieldsEntry")
|
|
245
|
+
if map_type?(descriptor)
|
|
236
246
|
key = descriptor.subtype.lookup("key")
|
|
237
247
|
value = descriptor.subtype.lookup("value")
|
|
238
248
|
|
|
@@ -20,7 +20,7 @@ module Tapioca
|
|
|
20
20
|
|
|
21
21
|
compile_method(node, symbol, constant, initialize_method_for(constant))
|
|
22
22
|
compile_directly_owned_methods(node, symbol, constant)
|
|
23
|
-
compile_directly_owned_methods(node, symbol, singleton_class_of(constant))
|
|
23
|
+
compile_directly_owned_methods(node, symbol, singleton_class_of(constant), attached_class: constant)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
sig do
|
|
@@ -29,14 +29,22 @@ module Tapioca
|
|
|
29
29
|
module_name: String,
|
|
30
30
|
mod: Module,
|
|
31
31
|
for_visibility: T::Array[Symbol],
|
|
32
|
+
attached_class: T.nilable(Module),
|
|
32
33
|
).void
|
|
33
34
|
end
|
|
34
|
-
def compile_directly_owned_methods(
|
|
35
|
+
def compile_directly_owned_methods(
|
|
36
|
+
tree,
|
|
37
|
+
module_name,
|
|
38
|
+
mod,
|
|
39
|
+
for_visibility = [:public, :protected, :private],
|
|
40
|
+
attached_class: nil
|
|
41
|
+
)
|
|
35
42
|
method_names_by_visibility(mod)
|
|
36
43
|
.delete_if { |visibility, _method_list| !for_visibility.include?(visibility) }
|
|
37
44
|
.each do |visibility, method_list|
|
|
38
45
|
method_list.sort!.map do |name|
|
|
39
46
|
next if name == :initialize
|
|
47
|
+
next if method_new_in_abstract_class?(attached_class, name)
|
|
40
48
|
|
|
41
49
|
vis = case visibility
|
|
42
50
|
when :protected
|
|
@@ -180,6 +188,19 @@ module Tapioca
|
|
|
180
188
|
.include?(method_name.gsub(/=$/, "").to_sym)
|
|
181
189
|
end
|
|
182
190
|
|
|
191
|
+
sig do
|
|
192
|
+
params(
|
|
193
|
+
attached_class: T.nilable(Module),
|
|
194
|
+
method_name: Symbol,
|
|
195
|
+
).returns(T.nilable(T::Boolean))
|
|
196
|
+
end
|
|
197
|
+
def method_new_in_abstract_class?(attached_class, method_name)
|
|
198
|
+
attached_class &&
|
|
199
|
+
method_name == :new &&
|
|
200
|
+
!!abstract_type_of(attached_class) &&
|
|
201
|
+
Class === attached_class.singleton_class
|
|
202
|
+
end
|
|
203
|
+
|
|
183
204
|
sig { params(constant: Module).returns(T.nilable(UnboundMethod)) }
|
|
184
205
|
def initialize_method_for(constant)
|
|
185
206
|
constant.instance_method(:initialize)
|
|
@@ -16,12 +16,11 @@ module Tapioca
|
|
|
16
16
|
constant = event.constant
|
|
17
17
|
node = event.node
|
|
18
18
|
|
|
19
|
-
abstract_type =
|
|
20
|
-
T::Private::Abstract::Data.get(singleton_class_of(constant), :abstract_type)
|
|
19
|
+
abstract_type = abstract_type_of(constant)
|
|
21
20
|
|
|
22
21
|
node << RBI::Helper.new(abstract_type.to_s) if abstract_type
|
|
23
|
-
node << RBI::Helper.new("final") if
|
|
24
|
-
node << RBI::Helper.new("sealed") if
|
|
22
|
+
node << RBI::Helper.new("final") if final_module?(constant)
|
|
23
|
+
node << RBI::Helper.new("sealed") if sealed_module?(constant)
|
|
25
24
|
end
|
|
26
25
|
|
|
27
26
|
sig { override.params(event: NodeAdded).returns(T::Boolean) }
|
|
@@ -31,14 +31,14 @@ module Tapioca
|
|
|
31
31
|
|
|
32
32
|
# Map each type variable to its string representation.
|
|
33
33
|
#
|
|
34
|
-
# Each entry of `type_variables` maps a Module to a String,
|
|
35
|
-
#
|
|
36
|
-
# defined in the source code.
|
|
37
|
-
type_variable_declarations = type_variables.
|
|
38
|
-
|
|
39
|
-
next unless
|
|
34
|
+
# Each entry of `type_variables` maps a Module to a String, or
|
|
35
|
+
# is a `has_attached_class!` declaration, and the order they are inserted
|
|
36
|
+
# into the hash is the order they should be defined in the source code.
|
|
37
|
+
type_variable_declarations = type_variables.filter_map do |type_variable|
|
|
38
|
+
node = node_from_type_variable(type_variable)
|
|
39
|
+
next unless node
|
|
40
40
|
|
|
41
|
-
tree <<
|
|
41
|
+
tree << node
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
return if type_variable_declarations.empty?
|
|
@@ -46,6 +46,19 @@ module Tapioca
|
|
|
46
46
|
tree << RBI::Extend.new("T::Generic")
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
+
sig { params(type_variable: Tapioca::TypeVariableModule).returns(T.nilable(RBI::Node)) }
|
|
50
|
+
def node_from_type_variable(type_variable)
|
|
51
|
+
case type_variable.type
|
|
52
|
+
when Tapioca::TypeVariableModule::Type::HasAttachedClass
|
|
53
|
+
RBI::Send.new(type_variable.serialize)
|
|
54
|
+
else
|
|
55
|
+
type_variable_name = type_variable.name
|
|
56
|
+
return unless type_variable_name
|
|
57
|
+
|
|
58
|
+
RBI::TypeMember.new(type_variable_name, type_variable.serialize)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
49
62
|
sig { override.params(event: NodeAdded).returns(T::Boolean) }
|
|
50
63
|
def ignore?(event)
|
|
51
64
|
event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
|
data/lib/tapioca/gem/pipeline.rb
CHANGED
|
@@ -304,9 +304,9 @@ module Tapioca
|
|
|
304
304
|
@root << scope
|
|
305
305
|
end
|
|
306
306
|
|
|
307
|
-
sig { params(constant: Class).returns(T.nilable(String)) }
|
|
307
|
+
sig { params(constant: T::Class[T.anything]).returns(T.nilable(String)) }
|
|
308
308
|
def compile_superclass(constant)
|
|
309
|
-
superclass = T.let(nil, T.nilable(Class)) # rubocop:disable Lint/UselessAssignment
|
|
309
|
+
superclass = T.let(nil, T.nilable(T::Class[T.anything])) # rubocop:disable Lint/UselessAssignment
|
|
310
310
|
|
|
311
311
|
while (superclass = superclass_of(constant))
|
|
312
312
|
constant_name = name_of(constant)
|
data/lib/tapioca/gemfile.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
require "tapioca/bundler_ext/auto_require_hook"
|
|
5
|
+
|
|
4
6
|
module Tapioca
|
|
5
7
|
class Gemfile
|
|
6
8
|
extend(T::Sig)
|
|
@@ -12,50 +14,6 @@ module Tapioca
|
|
|
12
14
|
)
|
|
13
15
|
end
|
|
14
16
|
|
|
15
|
-
# This is a module that gets prepended to `Bundler::Dependency` and
|
|
16
|
-
# makes sure even gems marked as `require: false` are required during
|
|
17
|
-
# `Bundler.require`.
|
|
18
|
-
module AutoRequireHook
|
|
19
|
-
extend T::Sig
|
|
20
|
-
extend T::Helpers
|
|
21
|
-
|
|
22
|
-
requires_ancestor { ::Bundler::Dependency }
|
|
23
|
-
|
|
24
|
-
@exclude = T.let([], T::Array[String])
|
|
25
|
-
|
|
26
|
-
class << self
|
|
27
|
-
extend T::Sig
|
|
28
|
-
|
|
29
|
-
sig { params(exclude: T::Array[String]).returns(T::Array[String]) }
|
|
30
|
-
attr_writer :exclude
|
|
31
|
-
|
|
32
|
-
sig { params(name: T.untyped).returns(T::Boolean) }
|
|
33
|
-
def excluded?(name)
|
|
34
|
-
@exclude.include?(name)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
sig { returns(T.untyped).checked(:never) }
|
|
39
|
-
def autorequire
|
|
40
|
-
value = super
|
|
41
|
-
|
|
42
|
-
# If the gem is excluded, we don't want to force require it, in case
|
|
43
|
-
# it has side-effects users don't want. For example, `fakefs` gem, if
|
|
44
|
-
# loaded, takes over filesystem operations.
|
|
45
|
-
return value if AutoRequireHook.excluded?(name)
|
|
46
|
-
|
|
47
|
-
# If a gem is marked as `require: false`, then its `autorequire`
|
|
48
|
-
# value will be `[]`. But, we want those gems to be loaded for our
|
|
49
|
-
# purposes as well, so we return `nil` in those cases, instead, which
|
|
50
|
-
# means `require: true`.
|
|
51
|
-
return nil if value == []
|
|
52
|
-
|
|
53
|
-
value
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
::Bundler::Dependency.prepend(self)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
17
|
sig { returns(Bundler::Definition) }
|
|
60
18
|
attr_reader(:definition)
|
|
61
19
|
|
|
@@ -65,13 +23,15 @@ module Tapioca
|
|
|
65
23
|
sig { returns(T::Array[String]) }
|
|
66
24
|
attr_reader(:missing_specs)
|
|
67
25
|
|
|
68
|
-
sig { params(
|
|
69
|
-
def initialize(
|
|
70
|
-
AutoRequireHook.exclude = exclude
|
|
26
|
+
sig { params(excluded_gems: T::Array[String]).void }
|
|
27
|
+
def initialize(excluded_gems)
|
|
71
28
|
@gemfile = T.let(File.new(Bundler.default_gemfile), File)
|
|
72
29
|
@lockfile = T.let(File.new(Bundler.default_lockfile), File)
|
|
73
30
|
@definition = T.let(Bundler::Dsl.evaluate(gemfile, lockfile, {}), Bundler::Definition)
|
|
31
|
+
@excluded_gems = excluded_gems
|
|
32
|
+
|
|
74
33
|
dependencies, missing_specs = load_dependencies
|
|
34
|
+
|
|
75
35
|
@dependencies = T.let(dependencies, T::Array[GemSpec])
|
|
76
36
|
@missing_specs = T.let(missing_specs, T::Array[String])
|
|
77
37
|
end
|
|
@@ -83,7 +43,9 @@ module Tapioca
|
|
|
83
43
|
|
|
84
44
|
sig { void }
|
|
85
45
|
def require_bundle
|
|
86
|
-
|
|
46
|
+
BundlerExt::AutoRequireHook.override_require_false(exclude: @excluded_gems) do
|
|
47
|
+
T.unsafe(runtime).require(*groups)
|
|
48
|
+
end
|
|
87
49
|
end
|
|
88
50
|
|
|
89
51
|
private
|
|
@@ -80,7 +80,7 @@ module Tapioca
|
|
|
80
80
|
dsl_dir: String,
|
|
81
81
|
auto_strictness: T::Boolean,
|
|
82
82
|
gems: T::Array[Gemfile::GemSpec],
|
|
83
|
-
compilers: T::Enumerable[
|
|
83
|
+
compilers: T::Enumerable[T.class_of(Dsl::Compiler)],
|
|
84
84
|
).void
|
|
85
85
|
end
|
|
86
86
|
def validate_rbi_files(command:, gem_dir:, dsl_dir:, auto_strictness:, gems: [], compilers: [])
|
|
@@ -25,6 +25,7 @@ module Tapioca
|
|
|
25
25
|
{
|
|
26
26
|
# feature_name: ::Gem::Requirement.new(">= ___"), # https://github.com/sorbet/sorbet/pull/___
|
|
27
27
|
non_generic_weak_map: ::Gem::Requirement.new(">= 0.5.10587"), # https://github.com/sorbet/sorbet/pull/6610
|
|
28
|
+
generic_class: ::Gem::Requirement.new(">= 0.5.10820"), # https://github.com/sorbet/sorbet/pull/6781
|
|
28
29
|
}.freeze,
|
|
29
30
|
T::Hash[Symbol, ::Gem::Requirement],
|
|
30
31
|
)
|
data/lib/tapioca/internal.rb
CHANGED
|
@@ -30,6 +30,7 @@ require "tapioca/helpers/gem_helper"
|
|
|
30
30
|
|
|
31
31
|
require "tapioca/helpers/sorbet_helper"
|
|
32
32
|
require "tapioca/helpers/rbi_helper"
|
|
33
|
+
require "tapioca/sorbet_ext/backcompat_patches"
|
|
33
34
|
require "tapioca/sorbet_ext/fixed_hash_patch"
|
|
34
35
|
require "tapioca/sorbet_ext/name_patch"
|
|
35
36
|
require "tapioca/sorbet_ext/generic_name_patch"
|
data/lib/tapioca/loaders/dsl.rb
CHANGED
|
@@ -9,9 +9,16 @@ module Tapioca
|
|
|
9
9
|
class << self
|
|
10
10
|
extend T::Sig
|
|
11
11
|
|
|
12
|
-
sig
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
sig do
|
|
13
|
+
params(tapioca_path: String, eager_load: T::Boolean, app_root: String, halt_upon_load_error: T::Boolean).void
|
|
14
|
+
end
|
|
15
|
+
def load_application(tapioca_path:, eager_load: true, app_root: ".", halt_upon_load_error: true)
|
|
16
|
+
loader = new(
|
|
17
|
+
tapioca_path: tapioca_path,
|
|
18
|
+
eager_load: eager_load,
|
|
19
|
+
app_root: app_root,
|
|
20
|
+
halt_upon_load_error: halt_upon_load_error,
|
|
21
|
+
)
|
|
15
22
|
loader.load
|
|
16
23
|
end
|
|
17
24
|
end
|
|
@@ -25,13 +32,16 @@ module Tapioca
|
|
|
25
32
|
|
|
26
33
|
protected
|
|
27
34
|
|
|
28
|
-
sig
|
|
29
|
-
|
|
35
|
+
sig do
|
|
36
|
+
params(tapioca_path: String, eager_load: T::Boolean, app_root: String, halt_upon_load_error: T::Boolean).void
|
|
37
|
+
end
|
|
38
|
+
def initialize(tapioca_path:, eager_load: true, app_root: ".", halt_upon_load_error: true)
|
|
30
39
|
super()
|
|
31
40
|
|
|
32
41
|
@tapioca_path = tapioca_path
|
|
33
42
|
@eager_load = eager_load
|
|
34
43
|
@app_root = app_root
|
|
44
|
+
@halt_upon_load_error = halt_upon_load_error
|
|
35
45
|
end
|
|
36
46
|
|
|
37
47
|
sig { void }
|
|
@@ -65,6 +75,7 @@ module Tapioca
|
|
|
65
75
|
environment_load: true,
|
|
66
76
|
eager_load: @eager_load,
|
|
67
77
|
app_root: @app_root,
|
|
78
|
+
halt_upon_load_error: @halt_upon_load_error,
|
|
68
79
|
)
|
|
69
80
|
|
|
70
81
|
say("Done", :green)
|
data/lib/tapioca/loaders/gem.rb
CHANGED
|
@@ -15,14 +15,16 @@ module Tapioca
|
|
|
15
15
|
prerequire: T.nilable(String),
|
|
16
16
|
postrequire: String,
|
|
17
17
|
default_command: String,
|
|
18
|
+
halt_upon_load_error: T::Boolean,
|
|
18
19
|
).void
|
|
19
20
|
end
|
|
20
|
-
def load_application(bundle:, prerequire:, postrequire:, default_command:)
|
|
21
|
+
def load_application(bundle:, prerequire:, postrequire:, default_command:, halt_upon_load_error:)
|
|
21
22
|
loader = new(
|
|
22
23
|
bundle: bundle,
|
|
23
24
|
prerequire: prerequire,
|
|
24
25
|
postrequire: postrequire,
|
|
25
26
|
default_command: default_command,
|
|
27
|
+
halt_upon_load_error: halt_upon_load_error,
|
|
26
28
|
)
|
|
27
29
|
loader.load
|
|
28
30
|
end
|
|
@@ -41,22 +43,24 @@ module Tapioca
|
|
|
41
43
|
prerequire: T.nilable(String),
|
|
42
44
|
postrequire: String,
|
|
43
45
|
default_command: String,
|
|
46
|
+
halt_upon_load_error: T::Boolean,
|
|
44
47
|
).void
|
|
45
48
|
end
|
|
46
|
-
def initialize(bundle:, prerequire:, postrequire:, default_command:)
|
|
49
|
+
def initialize(bundle:, prerequire:, postrequire:, default_command:, halt_upon_load_error:)
|
|
47
50
|
super()
|
|
48
51
|
|
|
49
52
|
@bundle = bundle
|
|
50
53
|
@prerequire = prerequire
|
|
51
54
|
@postrequire = postrequire
|
|
52
55
|
@default_command = default_command
|
|
56
|
+
@halt_upon_load_error = halt_upon_load_error
|
|
53
57
|
end
|
|
54
58
|
|
|
55
59
|
sig { void }
|
|
56
60
|
def require_gem_file
|
|
57
61
|
say("Requiring all gems to prepare for compiling... ")
|
|
58
62
|
begin
|
|
59
|
-
load_bundle(@bundle, @prerequire, @postrequire)
|
|
63
|
+
load_bundle(@bundle, @prerequire, @postrequire, @halt_upon_load_error)
|
|
60
64
|
rescue LoadError => e
|
|
61
65
|
explain_failed_require(@postrequire, e)
|
|
62
66
|
exit(1)
|
|
@@ -19,12 +19,17 @@ module Tapioca
|
|
|
19
19
|
private
|
|
20
20
|
|
|
21
21
|
sig do
|
|
22
|
-
params(
|
|
22
|
+
params(
|
|
23
|
+
gemfile: Tapioca::Gemfile,
|
|
24
|
+
initialize_file: T.nilable(String),
|
|
25
|
+
require_file: T.nilable(String),
|
|
26
|
+
halt_upon_load_error: T::Boolean,
|
|
27
|
+
).void
|
|
23
28
|
end
|
|
24
|
-
def load_bundle(gemfile, initialize_file, require_file)
|
|
29
|
+
def load_bundle(gemfile, initialize_file, require_file, halt_upon_load_error)
|
|
25
30
|
require_helper(initialize_file)
|
|
26
31
|
|
|
27
|
-
load_rails_application
|
|
32
|
+
load_rails_application(halt_upon_load_error: halt_upon_load_error)
|
|
28
33
|
|
|
29
34
|
gemfile.require_bundle
|
|
30
35
|
|
|
@@ -33,8 +38,15 @@ module Tapioca
|
|
|
33
38
|
load_rails_engines
|
|
34
39
|
end
|
|
35
40
|
|
|
36
|
-
sig
|
|
37
|
-
|
|
41
|
+
sig do
|
|
42
|
+
params(
|
|
43
|
+
environment_load: T::Boolean,
|
|
44
|
+
eager_load: T::Boolean,
|
|
45
|
+
app_root: String,
|
|
46
|
+
halt_upon_load_error: T::Boolean,
|
|
47
|
+
).void
|
|
48
|
+
end
|
|
49
|
+
def load_rails_application(environment_load: false, eager_load: false, app_root: ".", halt_upon_load_error: true)
|
|
38
50
|
return unless File.exist?("#{app_root}/config/application.rb")
|
|
39
51
|
|
|
40
52
|
silence_deprecations
|
|
@@ -50,9 +62,13 @@ module Tapioca
|
|
|
50
62
|
say(
|
|
51
63
|
"\nTapioca attempted to load the Rails application after encountering a `config/application.rb` file, " \
|
|
52
64
|
"but it failed. If your application uses Rails please ensure it can be loaded correctly before " \
|
|
53
|
-
"generating RBIs
|
|
65
|
+
"generating RBIs. If your application does not use Rails and you wish to continue RBI generation " \
|
|
66
|
+
"please pass `--no-halt-upon-load-error` to the tapioca command in sorbet/tapioca/config.yml or in CLI." \
|
|
67
|
+
"\n#{e}",
|
|
54
68
|
:yellow,
|
|
55
69
|
)
|
|
70
|
+
raise e if halt_upon_load_error
|
|
71
|
+
|
|
56
72
|
if e.backtrace
|
|
57
73
|
backtrace = T.must(e.backtrace).join("\n")
|
|
58
74
|
say(backtrace, :cyan) # TODO: Check verbose flag to print backtrace.
|
|
@@ -151,7 +151,7 @@ module Tapioca
|
|
|
151
151
|
generic_type
|
|
152
152
|
end
|
|
153
153
|
|
|
154
|
-
sig { params(constant: Class).returns(Class) }
|
|
154
|
+
sig { params(constant: T::Class[T.anything]).returns(T::Class[T.anything]) }
|
|
155
155
|
def create_safe_subclass(constant)
|
|
156
156
|
# Lookup the "inherited" class method
|
|
157
157
|
inherited_method = constant.method(:inherited)
|
|
@@ -52,7 +52,7 @@ module Tapioca
|
|
|
52
52
|
UNDEFINED_CONSTANT
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
sig { params(object: BasicObject).returns(Class).checked(:never) }
|
|
55
|
+
sig { params(object: BasicObject).returns(T::Class[T.anything]).checked(:never) }
|
|
56
56
|
def class_of(object)
|
|
57
57
|
CLASS_METHOD.bind_call(object)
|
|
58
58
|
end
|
|
@@ -68,7 +68,7 @@ module Tapioca
|
|
|
68
68
|
name&.start_with?("#<") ? nil : name
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
sig { params(constant: Module).returns(Class) }
|
|
71
|
+
sig { params(constant: Module).returns(T::Class[T.anything]) }
|
|
72
72
|
def singleton_class_of(constant)
|
|
73
73
|
SINGLETON_CLASS_METHOD.bind_call(constant)
|
|
74
74
|
end
|
|
@@ -78,7 +78,7 @@ module Tapioca
|
|
|
78
78
|
ANCESTORS_METHOD.bind_call(constant)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
sig { params(constant: Class).returns(T.nilable(Class)) }
|
|
81
|
+
sig { params(constant: T::Class[T.anything]).returns(T.nilable(T::Class[T.anything])) }
|
|
82
82
|
def superclass_of(constant)
|
|
83
83
|
SUPERCLASS_METHOD.bind_call(constant)
|
|
84
84
|
end
|
|
@@ -113,7 +113,7 @@ module Tapioca
|
|
|
113
113
|
if Class === constant
|
|
114
114
|
ancestors_of(superclass_of(constant) || Object)
|
|
115
115
|
else
|
|
116
|
-
Module.ancestors
|
|
116
|
+
Module.new.ancestors
|
|
117
117
|
end
|
|
118
118
|
end
|
|
119
119
|
|
|
@@ -161,7 +161,7 @@ module Tapioca
|
|
|
161
161
|
# descendants_of(C) # => [B, A, D]
|
|
162
162
|
sig do
|
|
163
163
|
type_parameters(:U)
|
|
164
|
-
.params(klass: T.all(Class, T.type_parameter(:U)))
|
|
164
|
+
.params(klass: T.all(T::Class[T.anything], T.type_parameter(:U)))
|
|
165
165
|
.returns(T::Array[T.type_parameter(:U)])
|
|
166
166
|
end
|
|
167
167
|
def descendants_of(klass)
|
|
@@ -192,6 +192,22 @@ module Tapioca
|
|
|
192
192
|
end.to_set
|
|
193
193
|
end
|
|
194
194
|
|
|
195
|
+
sig { params(constant: Module).returns(T.untyped) }
|
|
196
|
+
def abstract_type_of(constant)
|
|
197
|
+
T::Private::Abstract::Data.get(constant, :abstract_type) ||
|
|
198
|
+
T::Private::Abstract::Data.get(singleton_class_of(constant), :abstract_type)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
sig { params(constant: Module).returns(T::Boolean) }
|
|
202
|
+
def final_module?(constant)
|
|
203
|
+
T::Private::Final.final_module?(constant)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
sig { params(constant: Module).returns(T::Boolean) }
|
|
207
|
+
def sealed_module?(constant)
|
|
208
|
+
T::Private::Sealed.sealed_module?(constant)
|
|
209
|
+
end
|
|
210
|
+
|
|
195
211
|
private
|
|
196
212
|
|
|
197
213
|
sig { params(constant: Module).returns(T::Array[UnboundMethod]) }
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
unless defined?(T.anything)
|
|
5
|
+
module T
|
|
6
|
+
class << self
|
|
7
|
+
def anything
|
|
8
|
+
T.untyped
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
unless defined?(T::Class)
|
|
15
|
+
module T
|
|
16
|
+
module Class
|
|
17
|
+
class << self
|
|
18
|
+
def [](type)
|
|
19
|
+
T.untyped
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -49,6 +49,21 @@ module T
|
|
|
49
49
|
Tapioca::Runtime::GenericTypeRegistry.register_type_variable(self, type_variable)
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
|
+
|
|
53
|
+
def has_attached_class!(variance = :invariant, &bounds_proc)
|
|
54
|
+
Tapioca::Runtime::GenericTypeRegistry.register_type_variable(
|
|
55
|
+
self,
|
|
56
|
+
Tapioca::TypeVariableModule.new(
|
|
57
|
+
T.cast(self, Module),
|
|
58
|
+
Tapioca::TypeVariableModule::Type::HasAttachedClass,
|
|
59
|
+
variance,
|
|
60
|
+
nil,
|
|
61
|
+
nil,
|
|
62
|
+
nil,
|
|
63
|
+
bounds_proc,
|
|
64
|
+
),
|
|
65
|
+
)
|
|
66
|
+
end
|
|
52
67
|
end
|
|
53
68
|
|
|
54
69
|
prepend TypeStoragePatch
|
|
@@ -140,9 +155,13 @@ module Tapioca
|
|
|
140
155
|
enums do
|
|
141
156
|
Member = new("type_member")
|
|
142
157
|
Template = new("type_template")
|
|
158
|
+
HasAttachedClass = new("has_attached_class!")
|
|
143
159
|
end
|
|
144
160
|
end
|
|
145
161
|
|
|
162
|
+
sig { returns(Type) }
|
|
163
|
+
attr_reader :type
|
|
164
|
+
|
|
146
165
|
# rubocop:disable Metrics/ParameterLists
|
|
147
166
|
sig do
|
|
148
167
|
params(
|
data/lib/tapioca/version.rb
CHANGED
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.11.
|
|
4
|
+
version: 0.11.7
|
|
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-
|
|
14
|
+
date: 2023-06-23 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: bundler
|
|
@@ -149,6 +149,7 @@ files:
|
|
|
149
149
|
- README.md
|
|
150
150
|
- exe/tapioca
|
|
151
151
|
- lib/tapioca.rb
|
|
152
|
+
- lib/tapioca/bundler_ext/auto_require_hook.rb
|
|
152
153
|
- lib/tapioca/cli.rb
|
|
153
154
|
- lib/tapioca/commands.rb
|
|
154
155
|
- lib/tapioca/commands/annotations.rb
|
|
@@ -253,6 +254,7 @@ files:
|
|
|
253
254
|
- lib/tapioca/runtime/trackers/mixin.rb
|
|
254
255
|
- lib/tapioca/runtime/trackers/required_ancestor.rb
|
|
255
256
|
- lib/tapioca/runtime/trackers/tracker.rb
|
|
257
|
+
- lib/tapioca/sorbet_ext/backcompat_patches.rb
|
|
256
258
|
- lib/tapioca/sorbet_ext/fixed_hash_patch.rb
|
|
257
259
|
- lib/tapioca/sorbet_ext/generic_name_patch.rb
|
|
258
260
|
- lib/tapioca/sorbet_ext/name_patch.rb
|
|
@@ -281,7 +283,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
281
283
|
- !ruby/object:Gem::Version
|
|
282
284
|
version: '0'
|
|
283
285
|
requirements: []
|
|
284
|
-
rubygems_version: 3.4.
|
|
286
|
+
rubygems_version: 3.4.14
|
|
285
287
|
signing_key:
|
|
286
288
|
specification_version: 4
|
|
287
289
|
summary: A Ruby Interface file generator for gems, core types and the Ruby standard
|