tapioca 0.7.0 → 0.7.3
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/lib/tapioca/commands/todo.rb +4 -2
- 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 +13 -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 +28 -1
- data/lib/tapioca/gem/listeners/sorbet_signatures.rb +1 -1
- data/lib/tapioca/gem/pipeline.rb +1 -1
- data/lib/tapioca/helpers/{rbi_helper.rb → signatures_helper.rb} +1 -1
- data/lib/tapioca/helpers/sorbet_helper.rb +2 -2
- data/lib/tapioca/helpers/type_variable_helper.rb +43 -0
- data/lib/tapioca/internal.rb +3 -2
- data/lib/tapioca/rbi_ext/model.rb +12 -2
- data/lib/tapioca/runtime/generic_type_registry.rb +4 -2
- data/lib/tapioca/runtime/reflection.rb +5 -1
- data/lib/tapioca/sorbet_ext/generic_name_patch.rb +50 -20
- data/lib/tapioca/version.rb +1 -1
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b06e8ec67c72db19639c21a8a123ecbe7c3c58ad27eb8956d6e3772cb68dc1e
|
4
|
+
data.tar.gz: e8c0bb1073cc08c2fc9d7eea7b523ebe1bc87e7f162c0413e2f0f29be67481c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd44669e05b95b61ea62c3c5e7a640bc664a036418d66fad6734065caadaa52ec545408376d4e9ada732d2a976dc599b92fc374ec53ad2a1ffa247adee989acd
|
7
|
+
data.tar.gz: 8f6e3a4223c42f9271321b31c8f26199a9b371865041f3455b3e3350e356adaf0eca2c5d83bcec9e0247f76ed0434c1b93627e19f8c3d10893e084e5c88f7d3e
|
@@ -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/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
|
@@ -46,8 +46,12 @@ module Tapioca
|
|
46
46
|
class ActiveStorage < Compiler
|
47
47
|
extend T::Sig
|
48
48
|
|
49
|
-
ConstantType = type_member
|
50
|
-
|
49
|
+
ConstantType = type_member do
|
50
|
+
{
|
51
|
+
fixed: T.all(Module,
|
52
|
+
::ActiveStorage::Reflection::ActiveRecordExtensions::ClassMethods),
|
53
|
+
}
|
54
|
+
end
|
51
55
|
|
52
56
|
sig { override.void }
|
53
57
|
def decorate
|
@@ -62,7 +62,7 @@ module Tapioca
|
|
62
62
|
class ActiveSupportCurrentAttributes < Compiler
|
63
63
|
extend T::Sig
|
64
64
|
|
65
|
-
ConstantType = type_member
|
65
|
+
ConstantType = type_member { { fixed: T.class_of(::ActiveSupport::CurrentAttributes) } }
|
66
66
|
|
67
67
|
sig { override.void }
|
68
68
|
def decorate
|
@@ -49,7 +49,7 @@ module Tapioca
|
|
49
49
|
|
50
50
|
CONFIG_OPTIONS_SUFFIX = "ConfigOptions"
|
51
51
|
|
52
|
-
ConstantType = type_member
|
52
|
+
ConstantType = type_member { { fixed: Module } }
|
53
53
|
|
54
54
|
sig { override.void }
|
55
55
|
def decorate
|
@@ -77,7 +77,7 @@ module Tapioca
|
|
77
77
|
# enumerates the entries, we don't make any assumptions about their
|
78
78
|
# types.
|
79
79
|
mod.create_extend("T::Generic")
|
80
|
-
mod.
|
80
|
+
mod.create_type_variable("Elem", type: "type_member", fixed: "T.untyped")
|
81
81
|
|
82
82
|
method_names.each do |method_name|
|
83
83
|
# Create getter method
|
@@ -65,7 +65,7 @@ module Tapioca
|
|
65
65
|
class FrozenRecord < Compiler
|
66
66
|
extend T::Sig
|
67
67
|
|
68
|
-
ConstantType = type_member
|
68
|
+
ConstantType = type_member { { fixed: T.class_of(::FrozenRecord::Base) } }
|
69
69
|
|
70
70
|
sig { override.void }
|
71
71
|
def decorate
|
@@ -69,7 +69,7 @@ module Tapioca
|
|
69
69
|
T.proc.params(type: T.any(Module, String)).returns(String)
|
70
70
|
)
|
71
71
|
|
72
|
-
ConstantType = type_member
|
72
|
+
ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
|
73
73
|
|
74
74
|
sig { override.void }
|
75
75
|
def decorate
|
@@ -70,7 +70,9 @@ module Tapioca
|
|
70
70
|
|
71
71
|
extend T::Sig
|
72
72
|
|
73
|
-
ConstantType = type_member
|
73
|
+
ConstantType = type_member { { fixed: Module } }
|
74
|
+
|
75
|
+
FIELD_RE = /^[a-z_][a-zA-Z0-9_]*$/
|
74
76
|
|
75
77
|
sig { override.void }
|
76
78
|
def decorate
|
@@ -88,7 +90,15 @@ module Tapioca
|
|
88
90
|
create_kw_opt_param(field.name, type: field.init_type, default: field.default)
|
89
91
|
end
|
90
92
|
|
91
|
-
|
93
|
+
if fields.all? { |field| FIELD_RE.match?(field.name) }
|
94
|
+
klass.create_method("initialize", parameters: parameters, return_type: "void")
|
95
|
+
else
|
96
|
+
# One of the fields has an incorrect name for a named parameter so creating the default initialize for
|
97
|
+
# it would create a RBI with a syntax error.
|
98
|
+
# The workaround is to create an initialize that takes a **kwargs instead.
|
99
|
+
kwargs_parameter = create_kw_rest_param("fields", type: "T.untyped")
|
100
|
+
klass.create_method("initialize", parameters: [kwargs_parameter], return_type: "void")
|
101
|
+
end
|
92
102
|
end
|
93
103
|
end
|
94
104
|
end
|
@@ -107,7 +117,7 @@ module Tapioca
|
|
107
117
|
klass.create_extend("T::Generic")
|
108
118
|
|
109
119
|
names.each do |name|
|
110
|
-
klass.
|
120
|
+
klass.create_type_variable(name, type: "type_member")
|
111
121
|
end
|
112
122
|
end
|
113
123
|
|
@@ -118,7 +118,7 @@ module Tapioca
|
|
118
118
|
class StateMachines < Compiler
|
119
119
|
extend T::Sig
|
120
120
|
|
121
|
-
ConstantType = type_member
|
121
|
+
ConstantType = type_member { { fixed: T.all(Module, ::StateMachines::ClassMethods) } }
|
122
122
|
|
123
123
|
sig { override.void }
|
124
124
|
def decorate
|
@@ -87,7 +87,7 @@ module Tapioca
|
|
87
87
|
class UrlHelpers < Compiler
|
88
88
|
extend T::Sig
|
89
89
|
|
90
|
-
ConstantType = type_member
|
90
|
+
ConstantType = type_member { { fixed: Module } }
|
91
91
|
|
92
92
|
sig { override.void }
|
93
93
|
def decorate
|
@@ -109,6 +109,8 @@ module Tapioca
|
|
109
109
|
|
110
110
|
sig { override.returns(T::Enumerable[Module]) }
|
111
111
|
def self.gather_constants
|
112
|
+
return [] unless Rails.application
|
113
|
+
|
112
114
|
Object.const_set(:GeneratedUrlHelpersModule, Rails.application.routes.named_routes.url_helpers_module)
|
113
115
|
Object.const_set(:GeneratedPathHelpersModule, Rails.application.routes.named_routes.path_helpers_module)
|
114
116
|
|
@@ -160,7 +162,8 @@ module Tapioca
|
|
160
162
|
superclass_ancestors = ancestors_of(superclass) if superclass
|
161
163
|
end
|
162
164
|
|
163
|
-
(ancestors_of(mod)
|
165
|
+
ancestors = Set.new.compare_by_identity.merge(ancestors_of(mod)).subtract(superclass_ancestors)
|
166
|
+
ancestors.any? { |ancestor| helper == ancestor }
|
164
167
|
end
|
165
168
|
end
|
166
169
|
end
|
@@ -1,11 +1,14 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "tapioca/helpers/signatures_helper"
|
5
|
+
|
4
6
|
module Tapioca
|
5
7
|
module Dsl
|
6
8
|
module Helpers
|
7
9
|
module ParamHelper
|
8
10
|
extend T::Sig
|
11
|
+
include SignaturesHelper
|
9
12
|
|
10
13
|
sig { params(name: String, type: String).returns(RBI::TypedParam) }
|
11
14
|
def create_param(name, type:)
|
@@ -44,7 +47,7 @@ module Tapioca
|
|
44
47
|
|
45
48
|
sig { params(param: RBI::Param, type: String).returns(RBI::TypedParam) }
|
46
49
|
def create_typed_param(param, type)
|
47
|
-
RBI::TypedParam.new(param: param, type: type)
|
50
|
+
RBI::TypedParam.new(param: param, type: sanitize_signature_types(type))
|
48
51
|
end
|
49
52
|
end
|
50
53
|
end
|
data/lib/tapioca/dsl/pipeline.rb
CHANGED
@@ -53,7 +53,7 @@ module Tapioca
|
|
53
53
|
end
|
54
54
|
def run(&blk)
|
55
55
|
constants_to_process = gather_constants(requested_constants)
|
56
|
-
.select { |c|
|
56
|
+
.select { |c| Module === c } # Filter value constants out
|
57
57
|
.sort_by! { |c| T.must(Runtime::Reflection.name_of(c)) }
|
58
58
|
|
59
59
|
if constants_to_process.empty?
|
@@ -112,10 +112,37 @@ module Tapioca
|
|
112
112
|
sig { params(requested_constants: T::Array[Module]).returns(T::Set[Module]) }
|
113
113
|
def gather_constants(requested_constants)
|
114
114
|
constants = compilers.map(&:processable_constants).reduce(Set.new, :union)
|
115
|
+
constants = filter_anonymous_and_reloaded_constants(constants)
|
116
|
+
|
115
117
|
constants &= requested_constants unless requested_constants.empty?
|
116
118
|
constants
|
117
119
|
end
|
118
120
|
|
121
|
+
sig { params(constants: T::Set[Module]).returns(T::Set[Module]) }
|
122
|
+
def filter_anonymous_and_reloaded_constants(constants)
|
123
|
+
# Group constants by their names
|
124
|
+
constants_by_name = constants
|
125
|
+
.group_by { |c| T.must(Runtime::Reflection.name_of(c)) }
|
126
|
+
.select { |name, _| !name.nil? }
|
127
|
+
|
128
|
+
# Find the constants that have been reloaded
|
129
|
+
reloaded_constants = constants_by_name.select { |_, constants| constants.size > 1 }.keys
|
130
|
+
|
131
|
+
unless reloaded_constants.empty?
|
132
|
+
reloaded_constant_names = reloaded_constants.map { |name| "`#{name}`" }.join(", ")
|
133
|
+
|
134
|
+
$stderr.puts("WARNING: Multiple constants with the same name: #{reloaded_constant_names}")
|
135
|
+
$stderr.puts("Make sure some object is not holding onto these constants during an app reload.")
|
136
|
+
end
|
137
|
+
|
138
|
+
# Look up all the constants back from their names. The resulting constant set will be the
|
139
|
+
# set of constants that are actually in memory with those names.
|
140
|
+
constants_by_name
|
141
|
+
.keys
|
142
|
+
.map { |name| T.cast(Runtime::Reflection.constantize(name), Module) }
|
143
|
+
.to_set
|
144
|
+
end
|
145
|
+
|
119
146
|
sig { params(constant: Module).returns(T.nilable(RBI::File)) }
|
120
147
|
def rbi_for_constant(constant)
|
121
148
|
file = RBI::File.new(strictness: "true")
|
data/lib/tapioca/gem/pipeline.rb
CHANGED
@@ -21,8 +21,8 @@ module Tapioca
|
|
21
21
|
SORBET_EXE_PATH_ENV_VAR = "TAPIOCA_SORBET_EXE"
|
22
22
|
|
23
23
|
FEATURE_REQUIREMENTS = T.let({
|
24
|
-
|
25
|
-
|
24
|
+
to_ary_nil_support: ::Gem::Requirement.new(">= 0.5.9220"), # https://github.com/sorbet/sorbet/pull/4706
|
25
|
+
type_variable_block_syntax: ::Gem::Requirement.new(">= 0.5.9892"), # https://github.com/sorbet/sorbet/pull/5639
|
26
26
|
}.freeze, T::Hash[Symbol, ::Gem::Requirement])
|
27
27
|
|
28
28
|
class CmdResult < T::Struct
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Tapioca
|
5
|
+
module TypeVariableHelper
|
6
|
+
extend T::Sig
|
7
|
+
extend SorbetHelper
|
8
|
+
|
9
|
+
sig do
|
10
|
+
params(
|
11
|
+
type: String,
|
12
|
+
variance: Symbol,
|
13
|
+
fixed: T.nilable(String),
|
14
|
+
upper: T.nilable(String),
|
15
|
+
lower: T.nilable(String)
|
16
|
+
).returns(String)
|
17
|
+
end
|
18
|
+
def self.serialize_type_variable(type, variance, fixed, upper, lower)
|
19
|
+
variance = nil if variance == :invariant
|
20
|
+
|
21
|
+
bounds = []
|
22
|
+
bounds << "fixed: #{fixed}" if fixed
|
23
|
+
bounds << "lower: #{lower}" if lower
|
24
|
+
bounds << "upper: #{upper}" if upper
|
25
|
+
|
26
|
+
parameters = []
|
27
|
+
block = []
|
28
|
+
|
29
|
+
parameters << ":#{variance}" if variance
|
30
|
+
|
31
|
+
if sorbet_supports?(:type_variable_block_syntax)
|
32
|
+
block = bounds
|
33
|
+
else
|
34
|
+
parameters.concat(bounds)
|
35
|
+
end
|
36
|
+
|
37
|
+
serialized = type.dup
|
38
|
+
serialized << "(#{parameters.join(", ")})" unless parameters.empty?
|
39
|
+
serialized << " { { #{block.join(", ")} } }" unless block.empty?
|
40
|
+
serialized
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/tapioca/internal.rb
CHANGED
@@ -6,14 +6,15 @@ require "tapioca/runtime/reflection"
|
|
6
6
|
require "tapioca/runtime/trackers"
|
7
7
|
require "tapioca/runtime/dynamic_mixin_compiler"
|
8
8
|
require "tapioca/runtime/loader"
|
9
|
+
require "tapioca/helpers/sorbet_helper"
|
10
|
+
require "tapioca/helpers/type_variable_helper"
|
9
11
|
require "tapioca/sorbet_ext/generic_name_patch"
|
10
12
|
require "tapioca/sorbet_ext/fixed_hash_patch"
|
11
13
|
require "tapioca/runtime/generic_type_registry"
|
12
14
|
require "tapioca/helpers/cli_helper"
|
13
15
|
require "tapioca/helpers/config_helper"
|
14
|
-
require "tapioca/helpers/
|
16
|
+
require "tapioca/helpers/signatures_helper"
|
15
17
|
require "tapioca/helpers/shims_helper"
|
16
|
-
require "tapioca/helpers/sorbet_helper"
|
17
18
|
require "tapioca/commands"
|
18
19
|
require "tapioca/cli"
|
19
20
|
require "tapioca/gemfile"
|
@@ -61,8 +61,18 @@ module RBI
|
|
61
61
|
create_node(RBI::MixesInClassMethods.new(name))
|
62
62
|
end
|
63
63
|
|
64
|
-
sig
|
65
|
-
|
64
|
+
sig do
|
65
|
+
params(
|
66
|
+
name: String,
|
67
|
+
type: String,
|
68
|
+
variance: Symbol,
|
69
|
+
fixed: T.nilable(String),
|
70
|
+
upper: T.nilable(String),
|
71
|
+
lower: T.nilable(String)
|
72
|
+
).void
|
73
|
+
end
|
74
|
+
def create_type_variable(name, type:, variance: :invariant, fixed: nil, upper: nil, lower: nil)
|
75
|
+
value = Tapioca::TypeVariableHelper.serialize_type_variable(type, variance, fixed, upper, lower)
|
66
76
|
create_node(RBI::TypeMember.new(name, value))
|
67
77
|
end
|
68
78
|
|
@@ -111,8 +111,10 @@ module Tapioca
|
|
111
111
|
constant.clone
|
112
112
|
end
|
113
113
|
|
114
|
-
# Let's set the `name`
|
115
|
-
|
114
|
+
# Let's set the `name` and `to_s` methods to return the proper generic name
|
115
|
+
name_proc = -> { name }
|
116
|
+
generic_type.define_singleton_method(:name, name_proc)
|
117
|
+
generic_type.define_singleton_method(:to_s, name_proc)
|
116
118
|
|
117
119
|
# We need to define a `<=` method on the cloned constant, so that Sorbet
|
118
120
|
# can do covariance/contravariance checks on the type variables.
|
@@ -140,7 +140,11 @@ module Tapioca
|
|
140
140
|
#
|
141
141
|
# class D < C; end
|
142
142
|
# descendants_of(C) # => [B, A, D]
|
143
|
-
sig
|
143
|
+
sig do
|
144
|
+
type_parameters(:U)
|
145
|
+
.params(klass: T.all(Class, T.type_parameter(:U)))
|
146
|
+
.returns(T::Array[T.type_parameter(:U)])
|
147
|
+
end
|
144
148
|
def descendants_of(klass)
|
145
149
|
result = ObjectSpace.each_object(klass.singleton_class).reject do |k|
|
146
150
|
T.cast(k, Module).singleton_class? || T.unsafe(k) == klass
|
@@ -2,6 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "tapioca/sorbet_ext/name_patch"
|
5
|
+
require "tapioca/helpers/sorbet_helper"
|
5
6
|
|
6
7
|
module T
|
7
8
|
module Generic
|
@@ -20,7 +21,7 @@ module T
|
|
20
21
|
Tapioca::Runtime::GenericTypeRegistry.register_type(constant, types)
|
21
22
|
end
|
22
23
|
|
23
|
-
def type_member(variance = :invariant, fixed: nil, lower:
|
24
|
+
def type_member(variance = :invariant, fixed: nil, lower: nil, upper: nil, &bounds_proc)
|
24
25
|
# `T::Generic#type_member` just instantiates a `T::Type::TypeMember` instance and returns it.
|
25
26
|
# We use that when registering the type member and then later return it from this method.
|
26
27
|
Tapioca::TypeVariableModule.new(
|
@@ -29,13 +30,14 @@ module T
|
|
29
30
|
variance,
|
30
31
|
fixed,
|
31
32
|
lower,
|
32
|
-
upper
|
33
|
+
upper,
|
34
|
+
bounds_proc
|
33
35
|
).tap do |type_variable|
|
34
36
|
Tapioca::Runtime::GenericTypeRegistry.register_type_variable(self, type_variable)
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
38
|
-
def type_template(variance = :invariant, fixed: nil, lower:
|
40
|
+
def type_template(variance = :invariant, fixed: nil, lower: nil, upper: nil, &bounds_proc)
|
39
41
|
# `T::Generic#type_template` just instantiates a `T::Type::TypeTemplate` instance and returns it.
|
40
42
|
# We use that when registering the type template and then later return it from this method.
|
41
43
|
Tapioca::TypeVariableModule.new(
|
@@ -44,7 +46,8 @@ module T
|
|
44
46
|
variance,
|
45
47
|
fixed,
|
46
48
|
lower,
|
47
|
-
upper
|
49
|
+
upper,
|
50
|
+
bounds_proc
|
48
51
|
).tap do |type_variable|
|
49
52
|
Tapioca::Runtime::GenericTypeRegistry.register_type_variable(self, type_variable)
|
50
53
|
end
|
@@ -119,18 +122,31 @@ module Tapioca
|
|
119
122
|
end
|
120
123
|
end
|
121
124
|
|
125
|
+
# rubocop:disable Metrics/ParameterLists
|
122
126
|
sig do
|
123
|
-
params(
|
127
|
+
params(
|
128
|
+
context: Module,
|
129
|
+
type: Type,
|
130
|
+
variance: Symbol,
|
131
|
+
fixed: T.untyped,
|
132
|
+
lower: T.untyped,
|
133
|
+
upper: T.untyped,
|
134
|
+
bounds_proc: T.nilable(T.proc.returns(T::Hash[Symbol, T.untyped]))
|
135
|
+
).void
|
124
136
|
end
|
125
|
-
def initialize(context, type, variance, fixed, lower, upper)
|
137
|
+
def initialize(context, type, variance, fixed, lower, upper, bounds_proc)
|
126
138
|
@context = context
|
127
139
|
@type = type
|
128
140
|
@variance = variance
|
129
|
-
@
|
130
|
-
|
131
|
-
|
141
|
+
@bounds_proc = if bounds_proc
|
142
|
+
bounds_proc
|
143
|
+
else
|
144
|
+
build_bounds_proc(fixed, lower, upper)
|
145
|
+
end
|
146
|
+
|
132
147
|
super()
|
133
148
|
end
|
149
|
+
# rubocop:enable Metrics/ParameterLists
|
134
150
|
|
135
151
|
sig { returns(T.nilable(String)) }
|
136
152
|
def name
|
@@ -153,17 +169,18 @@ module Tapioca
|
|
153
169
|
|
154
170
|
sig { returns(String) }
|
155
171
|
def serialize
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
172
|
+
bounds = @bounds_proc.call
|
173
|
+
fixed = bounds[:fixed].to_s if bounds.key?(:fixed)
|
174
|
+
lower = bounds[:lower].to_s if bounds.key?(:lower)
|
175
|
+
upper = bounds[:upper].to_s if bounds.key?(:upper)
|
176
|
+
|
177
|
+
TypeVariableHelper.serialize_type_variable(
|
178
|
+
@type.serialize,
|
179
|
+
@variance,
|
180
|
+
fixed,
|
181
|
+
upper,
|
182
|
+
lower
|
183
|
+
)
|
167
184
|
end
|
168
185
|
|
169
186
|
sig { returns(Tapioca::TypeVariable) }
|
@@ -173,6 +190,19 @@ module Tapioca
|
|
173
190
|
|
174
191
|
private
|
175
192
|
|
193
|
+
sig do
|
194
|
+
params(fixed: T.untyped, lower: T.untyped, upper: T.untyped)
|
195
|
+
.returns(T.proc.returns(T::Hash[Symbol, T.untyped]))
|
196
|
+
end
|
197
|
+
def build_bounds_proc(fixed, lower, upper)
|
198
|
+
bounds = {}
|
199
|
+
bounds[:fixed] = fixed unless fixed.nil?
|
200
|
+
bounds[:lower] = lower unless lower.nil?
|
201
|
+
bounds[:upper] = upper unless upper.nil?
|
202
|
+
|
203
|
+
-> { bounds }
|
204
|
+
end
|
205
|
+
|
176
206
|
sig do
|
177
207
|
type_parameters(:Result)
|
178
208
|
.params(block: T.proc.returns(T.type_parameter(:Result)))
|
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.7.
|
4
|
+
version: 0.7.3
|
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: 2022-
|
14
|
+
date: 2022-05-30 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
version: 0.0.0
|
51
51
|
- - ">="
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 0.0.
|
53
|
+
version: 0.0.14
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -60,7 +60,7 @@ dependencies:
|
|
60
60
|
version: 0.0.0
|
61
61
|
- - ">="
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: 0.0.
|
63
|
+
version: 0.0.14
|
64
64
|
- !ruby/object:Gem::Dependency
|
65
65
|
name: sorbet-runtime
|
66
66
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,7 +98,7 @@ dependencies:
|
|
98
98
|
version: 1.1.0
|
99
99
|
- - ">="
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version: 1.1.
|
101
|
+
version: 1.1.11
|
102
102
|
type: :runtime
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -108,7 +108,7 @@ dependencies:
|
|
108
108
|
version: 1.1.0
|
109
109
|
- - ">="
|
110
110
|
- !ruby/object:Gem::Version
|
111
|
-
version: 1.1.
|
111
|
+
version: 1.1.11
|
112
112
|
- !ruby/object:Gem::Dependency
|
113
113
|
name: thor
|
114
114
|
requirement: !ruby/object:Gem::Requirement
|
@@ -212,13 +212,14 @@ files:
|
|
212
212
|
- lib/tapioca/gemfile.rb
|
213
213
|
- lib/tapioca/helpers/cli_helper.rb
|
214
214
|
- lib/tapioca/helpers/config_helper.rb
|
215
|
-
- lib/tapioca/helpers/rbi_helper.rb
|
216
215
|
- lib/tapioca/helpers/shims_helper.rb
|
216
|
+
- lib/tapioca/helpers/signatures_helper.rb
|
217
217
|
- lib/tapioca/helpers/sorbet_helper.rb
|
218
218
|
- lib/tapioca/helpers/test/content.rb
|
219
219
|
- lib/tapioca/helpers/test/dsl_compiler.rb
|
220
220
|
- lib/tapioca/helpers/test/isolation.rb
|
221
221
|
- lib/tapioca/helpers/test/template.rb
|
222
|
+
- lib/tapioca/helpers/type_variable_helper.rb
|
222
223
|
- lib/tapioca/internal.rb
|
223
224
|
- lib/tapioca/rbi_ext/model.rb
|
224
225
|
- lib/tapioca/rbi_formatter.rb
|