tapioca 0.19.1 → 0.20.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/README.md +84 -0
- data/lib/ruby_lsp/tapioca/run_gem_rbi_check.rb +1 -1
- data/lib/tapioca/cli.rb +9 -0
- data/lib/tapioca/commands/abstract_dsl.rb +76 -20
- data/lib/tapioca/commands/abstract_gem.rb +1 -0
- data/lib/tapioca/commands/annotations.rb +1 -1
- data/lib/tapioca/commands/gem_generate.rb +20 -4
- data/lib/tapioca/dsl/compiler.rb +24 -10
- data/lib/tapioca/dsl/compilers/aasm.rb +24 -17
- 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_record_delegated_types.rb +64 -16
- data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +17 -11
- data/lib/tapioca/dsl/compilers/active_record_relations.rb +2 -2
- data/lib/tapioca/dsl/compilers/config.rb +1 -1
- data/lib/tapioca/dsl/compilers/json_api_client_resource.rb +1 -1
- data/lib/tapioca/dsl/compilers/sidekiq_worker.rb +1 -1
- data/lib/tapioca/dsl/compilers/url_helpers.rb +312 -8
- data/lib/tapioca/dsl/compilers.rb +1 -1
- data/lib/tapioca/dsl/helpers/graphql_type_helper.rb +10 -3
- data/lib/tapioca/dsl/pipeline.rb +6 -27
- data/lib/tapioca/gem/events.rb +1 -1
- data/lib/tapioca/gem/listeners/documentation.rb +13 -8
- data/lib/tapioca/gem/listeners/methods.rb +79 -13
- data/lib/tapioca/gem/listeners/sorbet_enums.rb +1 -1
- data/lib/tapioca/gem/pipeline.rb +3 -3
- data/lib/tapioca/gemfile.rb +13 -0
- data/lib/tapioca/helpers/env_helper.rb +1 -1
- data/lib/tapioca/helpers/file_helper.rb +42 -0
- data/lib/tapioca/helpers/rbi_files_helper.rb +96 -5
- data/lib/tapioca/helpers/rbi_helper.rb +17 -3
- data/lib/tapioca/helpers/sorbet_helper.rb +1 -1
- data/lib/tapioca/internal.rb +2 -0
- data/lib/tapioca/loaders/gem.rb +33 -0
- data/lib/tapioca/loaders/loader.rb +0 -13
- data/lib/tapioca/rbi_ext/model.rb +16 -2
- data/lib/tapioca/rbs/bootsnap_cache.rb +52 -0
- data/lib/tapioca/rbs/rewriter.rb +91 -25
- data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +1 -2
- data/lib/tapioca/runtime/generic_type_registry.rb +38 -14
- data/lib/tapioca/runtime/reflection.rb +18 -1
- data/lib/tapioca/sorbet_ext/generic_name_patch.rb +0 -20
- data/lib/tapioca/sorbet_ext/generic_type_patch.rb +48 -0
- data/lib/tapioca/version.rb +1 -1
- data/lib/tapioca.rb +11 -10
- metadata +9 -6
|
@@ -76,11 +76,10 @@ module RBI
|
|
|
76
76
|
if !block || !parameters.empty? || return_type
|
|
77
77
|
# If there is no block, and the params and return type have not been supplied, then
|
|
78
78
|
# we create a single signature with the given parameters and return type
|
|
79
|
-
params = parameters.map { |param| RBI::SigParam.new(param.param.name.to_s, param.type) }
|
|
80
79
|
return_type ||= "T.untyped"
|
|
81
80
|
type_params = Tapioca::RBIHelper.extract_type_parameters(parameters.map(&:type).append(return_type))
|
|
82
81
|
|
|
83
|
-
sig = RBI::Sig.new(params:
|
|
82
|
+
sig = RBI::Sig.new(params: parameters.map(&:to_sig_param), return_type: return_type, type_params: type_params)
|
|
84
83
|
sigs << sig
|
|
85
84
|
end
|
|
86
85
|
|
|
@@ -117,5 +116,20 @@ module RBI
|
|
|
117
116
|
class TypedParam < T::Struct
|
|
118
117
|
const :param, RBI::Param
|
|
119
118
|
const :type, String
|
|
119
|
+
|
|
120
|
+
#: -> RBI::SigParam
|
|
121
|
+
def to_sig_param
|
|
122
|
+
name = case param
|
|
123
|
+
when RestParam
|
|
124
|
+
param.anonymous? ? "*".inspect : param.name.to_s
|
|
125
|
+
when KwRestParam
|
|
126
|
+
param.anonymous? ? "**".inspect : param.name.to_s
|
|
127
|
+
when BlockParam
|
|
128
|
+
param.anonymous? ? "&".inspect : param.name.to_s
|
|
129
|
+
else
|
|
130
|
+
param.name.to_s
|
|
131
|
+
end
|
|
132
|
+
RBI::SigParam.new(name, type)
|
|
133
|
+
end
|
|
120
134
|
end
|
|
121
135
|
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "bundler"
|
|
5
|
+
require "digest"
|
|
6
|
+
require "fileutils"
|
|
7
|
+
|
|
8
|
+
module Tapioca
|
|
9
|
+
module RBS
|
|
10
|
+
# Prepares the Bootsnap iseq cache used for RBS rewrite output.
|
|
11
|
+
#
|
|
12
|
+
# RBS rewrite output can change when the lockfile changes, even if the
|
|
13
|
+
# source files are unchanged.
|
|
14
|
+
# To account for this, we store the current Gemfile.lock SHA256 in a
|
|
15
|
+
# `.gemfile-lock-digest` file.
|
|
16
|
+
# A digest mismatch deletes Bootsnap's cache payload and records the new
|
|
17
|
+
# digest, so this run rebuilds the cache from scratch.
|
|
18
|
+
module BootsnapCache
|
|
19
|
+
DIGEST_FILE = ".gemfile-lock-digest" #: String
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
#: (String) -> void
|
|
23
|
+
def prepare_for_setup(cache_dir)
|
|
24
|
+
digest = gemfile_lock_digest
|
|
25
|
+
return if digest_matches?(cache_dir, digest)
|
|
26
|
+
|
|
27
|
+
FileUtils.rm_rf(File.join(cache_dir, "bootsnap"))
|
|
28
|
+
FileUtils.mkdir_p(cache_dir)
|
|
29
|
+
File.write(digest_path(cache_dir), digest)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
#: -> String
|
|
35
|
+
def gemfile_lock_digest
|
|
36
|
+
Digest::SHA256.file(Bundler.default_lockfile).hexdigest
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
#: (String, String) -> bool
|
|
40
|
+
def digest_matches?(cache_dir, digest)
|
|
41
|
+
path = digest_path(cache_dir)
|
|
42
|
+
File.file?(path) && File.read(path).chomp == digest
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
#: (String) -> String
|
|
46
|
+
def digest_path(cache_dir)
|
|
47
|
+
File.join(cache_dir, DIGEST_FILE)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
data/lib/tapioca/rbs/rewriter.rb
CHANGED
|
@@ -1,39 +1,104 @@
|
|
|
1
1
|
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
require "require-hooks/setup"
|
|
5
|
-
|
|
6
4
|
# This code rewrites RBS comments back into Sorbet's signatures as the files are being loaded.
|
|
7
5
|
# This will allow `sorbet-runtime` to wrap the methods as if they were originally written with the `sig{}` blocks.
|
|
8
6
|
# This will in turn allow Tapioca to use this signatures to generate typed RBI files.
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
8
|
+
module Tapioca
|
|
9
|
+
module RBS
|
|
10
|
+
class HostBootsnapSetupError < StandardError; end
|
|
11
|
+
|
|
12
|
+
# Raises when the host calls `Bootsnap.setup` after tapioca's setup. Host's call
|
|
13
|
+
# would overwrite tapioca's cache directory, so rewritten iseqs would end up in
|
|
14
|
+
# the host's regular cache.
|
|
15
|
+
module BootsnapGuard
|
|
16
|
+
extend T::Sig
|
|
17
|
+
|
|
18
|
+
sig { params(_kwargs: T.untyped).void }
|
|
19
|
+
def setup(**_kwargs)
|
|
20
|
+
Kernel.raise HostBootsnapSetupError, <<~MSG
|
|
21
|
+
Bootsnap.setup was called while TAPIOCA_RBS_CACHE=1 is set. Tapioca already
|
|
22
|
+
configured bootsnap with a dedicated cache directory; re-running setup
|
|
23
|
+
would overwrite that config and start writing rewritten iseqs into your
|
|
24
|
+
host's cache.
|
|
25
|
+
|
|
26
|
+
Gate your host's Bootsnap.setup on the env var, e.g. in config/boot.rb:
|
|
27
|
+
|
|
28
|
+
require "bootsnap/setup" unless ENV["TAPIOCA_RBS_CACHE"] == "1"
|
|
29
|
+
MSG
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
module BootsnapIntegration
|
|
34
|
+
class << self
|
|
35
|
+
extend T::Sig
|
|
36
|
+
|
|
37
|
+
sig { void }
|
|
38
|
+
def setup
|
|
39
|
+
require "bootsnap"
|
|
40
|
+
require "tapioca/rbs/bootsnap_cache"
|
|
41
|
+
|
|
42
|
+
cache_dir = ENV.fetch("TAPIOCA_BOOTSNAP_CACHE_DIR", File.join(Dir.pwd, "tmp/cache/bootsnap-tapioca-rbs"))
|
|
43
|
+
Tapioca::RBS::BootsnapCache.prepare_for_setup(cache_dir)
|
|
44
|
+
|
|
45
|
+
Bootsnap.setup(
|
|
46
|
+
cache_dir: cache_dir,
|
|
47
|
+
development_mode: true,
|
|
48
|
+
load_path_cache: true,
|
|
49
|
+
compile_cache_iseq: true,
|
|
50
|
+
compile_cache_yaml: true,
|
|
51
|
+
readonly: false,
|
|
52
|
+
revalidation: true,
|
|
53
|
+
)
|
|
54
|
+
Bootsnap.log_stats!
|
|
55
|
+
|
|
56
|
+
Bootsnap.singleton_class.prepend(Tapioca::RBS::BootsnapGuard)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# When TAPIOCA_RBS_CACHE=1, use a dedicated Bootsnap cache directory for
|
|
64
|
+
# RBS-rewritten iseqs. After setup, BootsnapGuard is prepended so the host
|
|
65
|
+
# application cannot replace Tapioca's cache directory.
|
|
66
|
+
if ENV["TAPIOCA_RBS_CACHE"] == "1"
|
|
67
|
+
begin
|
|
68
|
+
Tapioca::RBS::BootsnapIntegration.setup
|
|
69
|
+
rescue LoadError
|
|
70
|
+
# Bootsnap is not in the bundle, skip iseq caching.
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
require "require-hooks/setup"
|
|
74
|
+
else
|
|
75
|
+
require "require-hooks/setup"
|
|
76
|
+
|
|
77
|
+
begin
|
|
78
|
+
# Disable Bootsnap's iseq cache unless TAPIOCA_RBS_CACHE=1 enabled the separate cache above.
|
|
79
|
+
#
|
|
80
|
+
# This is necessary because host apps can call Bootsnap.setup after tapioca loads this file. When that happens,
|
|
81
|
+
# Bootsnap installs `load_iseq` and serves files from its cache, which bypasses RequireHooks.source_transform.
|
|
82
|
+
# Preloading bootsnap's iseq support lets us override `load_iseq` before setup installs it, preserving the default
|
|
83
|
+
# RBS rewrite behavior at the cost of slower app boot.
|
|
84
|
+
require "bootsnap"
|
|
85
|
+
require "bootsnap/compile_cache/iseq"
|
|
86
|
+
|
|
87
|
+
module Bootsnap
|
|
88
|
+
module CompileCache
|
|
89
|
+
module ISeq
|
|
90
|
+
module InstructionSequenceMixin
|
|
91
|
+
#: (String) -> RubyVM::InstructionSequence
|
|
92
|
+
def load_iseq(path)
|
|
93
|
+
super if defined?(super) # Disable Bootsnap's hook, but trigger any others.
|
|
94
|
+
end
|
|
30
95
|
end
|
|
31
96
|
end
|
|
32
97
|
end
|
|
33
98
|
end
|
|
99
|
+
rescue LoadError
|
|
100
|
+
# Bootsnap is not in the bundle, we don't need to do anything.
|
|
34
101
|
end
|
|
35
|
-
rescue LoadError
|
|
36
|
-
# Bootsnap is not in the bundle, we don't need to do anything.
|
|
37
102
|
end
|
|
38
103
|
|
|
39
104
|
# We need to include `T::Sig` very early to make sure that the `sig` method is available since gems using RBS comments
|
|
@@ -47,7 +112,8 @@ RequireHooks.source_transform(patterns: ["**/*.rb"]) do |path, source|
|
|
|
47
112
|
|
|
48
113
|
# For performance reasons, we only rewrite files that use Sorbet.
|
|
49
114
|
if source =~ /^\s*#\s*typed: (ignore|false|true|strict|strong|__STDLIB_INTERNAL)/
|
|
50
|
-
|
|
115
|
+
# Sorbet runtime only supports one signature per method, so keep the last overload.
|
|
116
|
+
Spoom::Sorbet::Translate.rbs_comments_to_sorbet_sigs(source, file: path, overloads_strategy: :translate_last)
|
|
51
117
|
end
|
|
52
118
|
rescue Spoom::Sorbet::Translate::Error
|
|
53
119
|
# If we can't translate the RBS comments back into Sorbet's signatures, we just skip the file.
|
|
@@ -53,7 +53,7 @@ module Tapioca
|
|
|
53
53
|
mixins_from_modules[mod] = (after - before).reverse!
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
|
-
rescue Exception
|
|
56
|
+
rescue Exception
|
|
57
57
|
# this is a best effort, bail if we can't perform this
|
|
58
58
|
end
|
|
59
59
|
|
|
@@ -85,7 +85,6 @@ module Tapioca
|
|
|
85
85
|
super(*attrs, **kwargs) if defined?(super)
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
-
# rubocop:disable Style/MissingRespondToMissing
|
|
89
88
|
T::Sig::WithoutRuntime.sig { params(symbol: Symbol, args: T.untyped).returns(T.untyped) }
|
|
90
89
|
def method_missing(symbol, *args)
|
|
91
90
|
# We need this here so that we can handle any random instance
|
|
@@ -6,7 +6,7 @@ module Tapioca
|
|
|
6
6
|
# This class is responsible for storing and looking up information related to generic types.
|
|
7
7
|
#
|
|
8
8
|
# The class stores 2 different kinds of data, in two separate lookup tables:
|
|
9
|
-
# 1. a lookup of generic type instances by name: `@generic_instances`
|
|
9
|
+
# 1. a lookup of generic type instances by constant and name: `@generic_instances`
|
|
10
10
|
# 2. a lookup of type variable serializer by constant and type variable
|
|
11
11
|
# instance: `@type_variables`
|
|
12
12
|
#
|
|
@@ -21,15 +21,22 @@ module Tapioca
|
|
|
21
21
|
# variable to type variable serializers. This allows us to associate type variables
|
|
22
22
|
# to the constant names that represent them, easily.
|
|
23
23
|
module GenericTypeRegistry
|
|
24
|
-
@generic_instances = {} #: Hash[String, Module[top]]
|
|
24
|
+
@generic_instances = {}.compare_by_identity #: Hash[Module[top], Hash[String, Module[top]]]
|
|
25
25
|
|
|
26
26
|
@type_variables = {}.compare_by_identity #: Hash[Module[top], Array[TypeVariableModule]]
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
# Subclasses `T::Types::Base` rather than `T::Types::Simple` so that all
|
|
29
|
+
# validation goes through the `valid?` override below. `Simple` fast paths
|
|
30
|
+
# check `raw_type` directly, which for us is the clone, not the underlying type.
|
|
31
|
+
class GenericType < T::Types::Base
|
|
32
|
+
#: Module[top]
|
|
33
|
+
attr_reader :raw_type
|
|
34
|
+
|
|
29
35
|
#: (Module[top] raw_type, Module[top] underlying_type) -> void
|
|
30
36
|
def initialize(raw_type, underlying_type)
|
|
31
|
-
super(
|
|
37
|
+
super()
|
|
32
38
|
|
|
39
|
+
@raw_type = raw_type
|
|
33
40
|
@underlying_type = underlying_type #: Module[top]
|
|
34
41
|
end
|
|
35
42
|
|
|
@@ -38,6 +45,24 @@ module Tapioca
|
|
|
38
45
|
def valid?(obj)
|
|
39
46
|
obj.is_a?(@underlying_type)
|
|
40
47
|
end
|
|
48
|
+
|
|
49
|
+
# @override
|
|
50
|
+
#: -> String
|
|
51
|
+
def name
|
|
52
|
+
T.must(@raw_type.name)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @override
|
|
56
|
+
#: -> nil
|
|
57
|
+
def build_type
|
|
58
|
+
nil
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Matches the always-true `<=` we define on the clone in `create_generic_type`.
|
|
62
|
+
#: (T::Types::Base type) -> bool
|
|
63
|
+
private def subtype_of_single?(type)
|
|
64
|
+
true
|
|
65
|
+
end
|
|
41
66
|
end
|
|
42
67
|
|
|
43
68
|
class << self
|
|
@@ -45,8 +70,9 @@ module Tapioca
|
|
|
45
70
|
# and cloning the given constant so that we can return a type that is the same
|
|
46
71
|
# as the current type but is a different instance and has a different name method.
|
|
47
72
|
#
|
|
48
|
-
# We cache those cloned instances by their
|
|
49
|
-
# we don't keep instantiating a new type every single
|
|
73
|
+
# We cache those cloned instances by their original constant and their name in
|
|
74
|
+
# `@generic_instances`, so that we don't keep instantiating a new type every single
|
|
75
|
+
# time it is referenced.
|
|
50
76
|
# For example, `[Foo[Integer], Foo[Integer], Foo[Integer], Foo[String]]` will only
|
|
51
77
|
# result in 2 clones (1 for `Foo[Integer]` and another for `Foo[String]`) and
|
|
52
78
|
# 2 hash lookups (for the other two `Foo[Integer]`s).
|
|
@@ -64,12 +90,15 @@ module Tapioca
|
|
|
64
90
|
#
|
|
65
91
|
# Also, we try to memoize the generic type based on the name, so that
|
|
66
92
|
# we don't have to keep recreating them all the time.
|
|
67
|
-
@generic_instances[
|
|
93
|
+
generic_instances = @generic_instances[constant] ||= {}
|
|
94
|
+
generic_instances[name] ||= create_generic_type(constant, name)
|
|
68
95
|
end
|
|
69
96
|
|
|
70
97
|
#: (Object instance) -> bool
|
|
71
98
|
def generic_type_instance?(instance)
|
|
72
|
-
@generic_instances.values.any?
|
|
99
|
+
@generic_instances.values.any? do |generic_instances|
|
|
100
|
+
generic_instances.values.any? { |generic_type| generic_type === instance }
|
|
101
|
+
end
|
|
73
102
|
end
|
|
74
103
|
|
|
75
104
|
#: (Module[top] constant) -> Array[TypeVariableModule]?
|
|
@@ -88,7 +117,7 @@ module Tapioca
|
|
|
88
117
|
# can return it from the original methods as well.
|
|
89
118
|
#: (untyped constant, TypeVariableModule type_variable) -> void
|
|
90
119
|
def register_type_variable(constant, type_variable)
|
|
91
|
-
type_variables =
|
|
120
|
+
type_variables = @type_variables[constant] ||= []
|
|
92
121
|
|
|
93
122
|
type_variables << type_variable
|
|
94
123
|
end
|
|
@@ -163,11 +192,6 @@ module Tapioca
|
|
|
163
192
|
owner.send(:define_method, :inherited, inherited_method)
|
|
164
193
|
end
|
|
165
194
|
end
|
|
166
|
-
|
|
167
|
-
#: (Module[top] constant) -> Array[TypeVariableModule]
|
|
168
|
-
def lookup_or_initialize_type_variables(constant)
|
|
169
|
-
@type_variables[constant] ||= []
|
|
170
|
-
end
|
|
171
195
|
end
|
|
172
196
|
end
|
|
173
197
|
end
|
|
@@ -125,7 +125,24 @@ module Tapioca
|
|
|
125
125
|
|
|
126
126
|
#: ((UnboundMethod | Method) method) -> untyped
|
|
127
127
|
def signature_of!(method)
|
|
128
|
-
T::Utils.signature_for_method(method)
|
|
128
|
+
signature = T::Utils.signature_for_method(method)
|
|
129
|
+
return signature if signature
|
|
130
|
+
|
|
131
|
+
# Walk the super method chain to evaluate pending signatures that may have been hidden by `prepend`.
|
|
132
|
+
# During that walk, Sorbet may register a signature on the requested wrapper, so check it again.
|
|
133
|
+
# See https://github.com/Shopify/tapioca/issues/2710 for details.
|
|
134
|
+
current_method = method.super_method #: (UnboundMethod | Method)?
|
|
135
|
+
while current_method
|
|
136
|
+
# force evaluation of the signature
|
|
137
|
+
_ = T::Utils.signature_for_method(current_method)
|
|
138
|
+
|
|
139
|
+
evaluated_signature = T::Utils.signature_for_method(method)
|
|
140
|
+
return evaluated_signature if evaluated_signature
|
|
141
|
+
|
|
142
|
+
current_method = current_method.super_method
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
nil
|
|
129
146
|
rescue LoadError, StandardError
|
|
130
147
|
Kernel.raise SignatureBlockError
|
|
131
148
|
end
|
|
@@ -82,26 +82,6 @@ module T
|
|
|
82
82
|
prepend GenericPatch
|
|
83
83
|
end
|
|
84
84
|
end
|
|
85
|
-
|
|
86
|
-
module Utils
|
|
87
|
-
module Private
|
|
88
|
-
module PrivateCoercePatch
|
|
89
|
-
def coerce_and_check_module_types(val, check_val, check_module_type)
|
|
90
|
-
if val.is_a?(Tapioca::TypeVariableModule)
|
|
91
|
-
val.coerce_to_type_variable
|
|
92
|
-
elsif val.respond_to?(:__tapioca_override_type)
|
|
93
|
-
val.__tapioca_override_type
|
|
94
|
-
else
|
|
95
|
-
super
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
class << self
|
|
101
|
-
prepend(PrivateCoercePatch)
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
85
|
end
|
|
106
86
|
|
|
107
87
|
module Tapioca
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module T
|
|
5
|
+
module Utils
|
|
6
|
+
module Private
|
|
7
|
+
# Preserve Tapioca's generic type variables and instantiated generic
|
|
8
|
+
# names when Sorbet coerces them into runtime types.
|
|
9
|
+
module TapiocaGenericTypeCoercePatch
|
|
10
|
+
def coerce_and_check_module_types(val, check_val, check_module_type)
|
|
11
|
+
if val.is_a?(Tapioca::TypeVariableModule)
|
|
12
|
+
val.coerce_to_type_variable
|
|
13
|
+
elsif val.respond_to?(:__tapioca_override_type)
|
|
14
|
+
val.__tapioca_override_type
|
|
15
|
+
else
|
|
16
|
+
super
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
prepend(TapiocaGenericTypeCoercePatch)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module Private
|
|
28
|
+
module Casts
|
|
29
|
+
module TapiocaGenericTypeCastPatch
|
|
30
|
+
# https://github.com/sorbet/sorbet/commit/b8d64c7fd9a08e2b9159b5d592bc2de6d586b44a
|
|
31
|
+
# inlines the Module fast path in `T.let`, `T.cast`, `T.bind`, and
|
|
32
|
+
# `T.assert_type!`, so generic module clones can reach this cast path
|
|
33
|
+
# without going through `T::Utils::Private::TapiocaGenericTypeCoercePatch`.
|
|
34
|
+
def cast(value, type, cast_method)
|
|
35
|
+
if type.respond_to?(:__tapioca_override_type)
|
|
36
|
+
type = type.__tapioca_override_type
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
super(value, type, cast_method)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class << self
|
|
44
|
+
prepend(TapiocaGenericTypeCastPatch)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/tapioca/version.rb
CHANGED
data/lib/tapioca.rb
CHANGED
|
@@ -11,18 +11,18 @@ module Tapioca
|
|
|
11
11
|
|
|
12
12
|
LIB_ROOT_DIR = T.must(__dir__) #: String
|
|
13
13
|
SORBET_DIR = "sorbet" #: String
|
|
14
|
-
SORBET_CONFIG_FILE = "#{SORBET_DIR}/config" #: String
|
|
15
|
-
TAPIOCA_DIR = "#{SORBET_DIR}/tapioca" #: String
|
|
16
|
-
TAPIOCA_CONFIG_FILE = "#{TAPIOCA_DIR}/config.yml" #: String
|
|
14
|
+
SORBET_CONFIG_FILE = "#{SORBET_DIR}/config".freeze #: String
|
|
15
|
+
TAPIOCA_DIR = "#{SORBET_DIR}/tapioca".freeze #: String
|
|
16
|
+
TAPIOCA_CONFIG_FILE = "#{TAPIOCA_DIR}/config.yml".freeze #: String
|
|
17
17
|
|
|
18
18
|
BINARY_FILE = "bin/tapioca" #: String
|
|
19
|
-
DEFAULT_POSTREQUIRE_FILE = "#{TAPIOCA_DIR}/require.rb" #: String
|
|
20
|
-
DEFAULT_RBI_DIR = "#{SORBET_DIR}/rbi" #: String
|
|
21
|
-
DEFAULT_DSL_DIR = "#{DEFAULT_RBI_DIR}/dsl" #: String
|
|
22
|
-
DEFAULT_GEM_DIR = "#{DEFAULT_RBI_DIR}/gems" #: String
|
|
23
|
-
DEFAULT_SHIM_DIR = "#{DEFAULT_RBI_DIR}/shims" #: String
|
|
24
|
-
DEFAULT_TODO_FILE = "#{DEFAULT_RBI_DIR}/todo.rbi" #: String
|
|
25
|
-
DEFAULT_ANNOTATIONS_DIR = "#{DEFAULT_RBI_DIR}/annotations" #: String
|
|
19
|
+
DEFAULT_POSTREQUIRE_FILE = "#{TAPIOCA_DIR}/require.rb".freeze #: String
|
|
20
|
+
DEFAULT_RBI_DIR = "#{SORBET_DIR}/rbi".freeze #: String
|
|
21
|
+
DEFAULT_DSL_DIR = "#{DEFAULT_RBI_DIR}/dsl".freeze #: String
|
|
22
|
+
DEFAULT_GEM_DIR = "#{DEFAULT_RBI_DIR}/gems".freeze #: String
|
|
23
|
+
DEFAULT_SHIM_DIR = "#{DEFAULT_RBI_DIR}/shims".freeze #: String
|
|
24
|
+
DEFAULT_TODO_FILE = "#{DEFAULT_RBI_DIR}/todo.rbi".freeze #: String
|
|
25
|
+
DEFAULT_ANNOTATIONS_DIR = "#{DEFAULT_RBI_DIR}/annotations".freeze #: String
|
|
26
26
|
|
|
27
27
|
DEFAULT_OVERRIDES = {
|
|
28
28
|
# ActiveSupport overrides some core methods with different signatures
|
|
@@ -32,6 +32,7 @@ module Tapioca
|
|
|
32
32
|
|
|
33
33
|
DEFAULT_RBI_MAX_LINE_LENGTH = 120
|
|
34
34
|
DEFAULT_ENVIRONMENT = "development"
|
|
35
|
+
DEFAULT_MAX_DIFF_LINES = 250
|
|
35
36
|
|
|
36
37
|
CENTRAL_REPO_ROOT_URI = "https://raw.githubusercontent.com/Shopify/rbi-central/main"
|
|
37
38
|
CENTRAL_REPO_INDEX_PATH = "index.json"
|
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.
|
|
4
|
+
version: 0.20.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ufuk Kayserilioglu
|
|
@@ -130,28 +130,28 @@ dependencies:
|
|
|
130
130
|
requirements:
|
|
131
131
|
- - ">="
|
|
132
132
|
- !ruby/object:Gem::Version
|
|
133
|
-
version: 0.
|
|
133
|
+
version: 0.4.1
|
|
134
134
|
type: :runtime
|
|
135
135
|
prerelease: false
|
|
136
136
|
version_requirements: !ruby/object:Gem::Requirement
|
|
137
137
|
requirements:
|
|
138
138
|
- - ">="
|
|
139
139
|
- !ruby/object:Gem::Version
|
|
140
|
-
version: 0.
|
|
140
|
+
version: 0.4.1
|
|
141
141
|
- !ruby/object:Gem::Dependency
|
|
142
142
|
name: spoom
|
|
143
143
|
requirement: !ruby/object:Gem::Requirement
|
|
144
144
|
requirements:
|
|
145
145
|
- - ">="
|
|
146
146
|
- !ruby/object:Gem::Version
|
|
147
|
-
version: 1.7.
|
|
147
|
+
version: 1.7.16
|
|
148
148
|
type: :runtime
|
|
149
149
|
prerelease: false
|
|
150
150
|
version_requirements: !ruby/object:Gem::Requirement
|
|
151
151
|
requirements:
|
|
152
152
|
- - ">="
|
|
153
153
|
- !ruby/object:Gem::Version
|
|
154
|
-
version: 1.7.
|
|
154
|
+
version: 1.7.16
|
|
155
155
|
- !ruby/object:Gem::Dependency
|
|
156
156
|
name: tsort
|
|
157
157
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -273,6 +273,7 @@ files:
|
|
|
273
273
|
- lib/tapioca/helpers/cli_helper.rb
|
|
274
274
|
- lib/tapioca/helpers/config_helper.rb
|
|
275
275
|
- lib/tapioca/helpers/env_helper.rb
|
|
276
|
+
- lib/tapioca/helpers/file_helper.rb
|
|
276
277
|
- lib/tapioca/helpers/gem_helper.rb
|
|
277
278
|
- lib/tapioca/helpers/git_attributes.rb
|
|
278
279
|
- lib/tapioca/helpers/package_url.rb
|
|
@@ -289,6 +290,7 @@ files:
|
|
|
289
290
|
- lib/tapioca/loaders/loader.rb
|
|
290
291
|
- lib/tapioca/rbi_ext/model.rb
|
|
291
292
|
- lib/tapioca/rbi_formatter.rb
|
|
293
|
+
- lib/tapioca/rbs/bootsnap_cache.rb
|
|
292
294
|
- lib/tapioca/rbs/rewriter.rb
|
|
293
295
|
- lib/tapioca/repo_index.rb
|
|
294
296
|
- lib/tapioca/runtime/dynamic_mixin_compiler.rb
|
|
@@ -305,6 +307,7 @@ files:
|
|
|
305
307
|
- lib/tapioca/runtime/trackers/tracker.rb
|
|
306
308
|
- lib/tapioca/sorbet_ext/backcompat_patches.rb
|
|
307
309
|
- lib/tapioca/sorbet_ext/generic_name_patch.rb
|
|
310
|
+
- lib/tapioca/sorbet_ext/generic_type_patch.rb
|
|
308
311
|
- lib/tapioca/sorbet_ext/name_patch.rb
|
|
309
312
|
- lib/tapioca/sorbet_ext/proc_bind_patch.rb
|
|
310
313
|
- lib/tapioca/sorbet_ext/void_patch.rb
|
|
@@ -324,7 +327,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
324
327
|
requirements:
|
|
325
328
|
- - ">="
|
|
326
329
|
- !ruby/object:Gem::Version
|
|
327
|
-
version: '3.
|
|
330
|
+
version: '3.3'
|
|
328
331
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
329
332
|
requirements:
|
|
330
333
|
- - ">="
|