tapioca 0.6.0 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +6 -0
- data/README.md +56 -14
- data/lib/tapioca/cli.rb +1 -0
- data/lib/tapioca/compilers/dsl/active_model_attributes.rb +19 -13
- data/lib/tapioca/compilers/dsl/active_record_associations.rb +1 -1
- data/lib/tapioca/compilers/dsl/active_record_columns.rb +8 -8
- data/lib/tapioca/compilers/dsl/active_record_relations.rb +20 -3
- data/lib/tapioca/compilers/dsl/active_record_typed_store.rb +1 -1
- data/lib/tapioca/compilers/dsl/base.rb +19 -3
- data/lib/tapioca/compilers/dsl/identity_cache.rb +5 -3
- data/lib/tapioca/compilers/dsl/rails_generators.rb +3 -3
- data/lib/tapioca/compilers/dsl/smart_properties.rb +12 -19
- data/lib/tapioca/compilers/dsl/url_helpers.rb +8 -3
- data/lib/tapioca/compilers/dynamic_mixin_compiler.rb +30 -5
- data/lib/tapioca/compilers/requires_compiler.rb +4 -11
- data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +26 -26
- data/lib/tapioca/gemfile.rb +44 -20
- data/lib/tapioca/generators/base.rb +1 -1
- data/lib/tapioca/generic_type_registry.rb +22 -7
- data/lib/tapioca/helpers/active_record_column_type_helper.rb +12 -2
- data/lib/tapioca/helpers/cli_helper.rb +10 -9
- data/lib/tapioca/helpers/config_helper.rb +116 -0
- data/lib/tapioca/sorbet_ext/generic_name_patch.rb +92 -54
- data/lib/tapioca/version.rb +1 -1
- metadata +4 -4
@@ -23,17 +23,31 @@ module T
|
|
23
23
|
def type_member(variance = :invariant, fixed: nil, lower: T.untyped, upper: BasicObject)
|
24
24
|
# `T::Generic#type_member` just instantiates a `T::Type::TypeMember` instance and returns it.
|
25
25
|
# We use that when registering the type member and then later return it from this method.
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
Tapioca::TypeVariableModule.new(
|
27
|
+
T.cast(self, Module),
|
28
|
+
Tapioca::TypeVariableModule::Type::Member,
|
29
|
+
variance,
|
30
|
+
fixed,
|
31
|
+
lower,
|
32
|
+
upper
|
33
|
+
).tap do |type_variable|
|
34
|
+
Tapioca::GenericTypeRegistry.register_type_variable(self, type_variable)
|
35
|
+
end
|
29
36
|
end
|
30
37
|
|
31
38
|
def type_template(variance = :invariant, fixed: nil, lower: T.untyped, upper: BasicObject)
|
32
39
|
# `T::Generic#type_template` just instantiates a `T::Type::TypeTemplate` instance and returns it.
|
33
40
|
# We use that when registering the type template and then later return it from this method.
|
34
|
-
|
35
|
-
|
36
|
-
|
41
|
+
Tapioca::TypeVariableModule.new(
|
42
|
+
T.cast(self, Module),
|
43
|
+
Tapioca::TypeVariableModule::Type::Template,
|
44
|
+
variance,
|
45
|
+
fixed,
|
46
|
+
lower,
|
47
|
+
upper
|
48
|
+
).tap do |type_variable|
|
49
|
+
Tapioca::GenericTypeRegistry.register_type_variable(self, type_variable)
|
50
|
+
end
|
37
51
|
end
|
38
52
|
end
|
39
53
|
|
@@ -42,15 +56,26 @@ module T
|
|
42
56
|
|
43
57
|
module Types
|
44
58
|
class Simple
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
59
|
+
module GenericPatch
|
60
|
+
def valid?(obj)
|
61
|
+
# Since `Tapioca::TypeVariable` is a `Module`, it will be wrapped by a
|
62
|
+
# `Simple` type. We want to always make type variable types valid, so we
|
63
|
+
# need to explicitly check that `raw_type` is a `Tapioca::TypeVariable`
|
64
|
+
# and return `true`
|
65
|
+
if defined?(Tapioca::TypeVariableModule) && Tapioca::TypeVariableModule === @raw_type
|
66
|
+
return true
|
67
|
+
end
|
68
|
+
|
69
|
+
obj.is_a?(@raw_type)
|
70
|
+
end
|
71
|
+
|
72
|
+
# This method intercepts calls to the `name` method for simple types, so that
|
73
|
+
# it can ask the name to the type if the type is generic, since, by this point,
|
74
|
+
# we've created a clone of that type with the `name` method returning the
|
75
|
+
# appropriate name for that specific concrete type.
|
51
76
|
def name
|
52
|
-
if T::Generic === @raw_type
|
53
|
-
# for types that are generic, use the name
|
77
|
+
if T::Generic === @raw_type || Tapioca::TypeVariableModule === @raw_type
|
78
|
+
# for types that are generic or are type variables, use the name
|
54
79
|
# returned by the "name" method of this instance
|
55
80
|
@name ||= T.unsafe(@raw_type).name.freeze
|
56
81
|
else
|
@@ -60,60 +85,57 @@ module T
|
|
60
85
|
end
|
61
86
|
end
|
62
87
|
|
63
|
-
prepend
|
88
|
+
prepend GenericPatch
|
64
89
|
end
|
65
90
|
end
|
66
91
|
end
|
67
92
|
|
68
93
|
module Tapioca
|
69
|
-
|
94
|
+
# This is subclassing from `Module` so that instances of this type will be modules.
|
95
|
+
# The reason why we want that is because that means those instances will automatically
|
96
|
+
# get bound to the constant names they are assigned to by Ruby. As a result, we don't
|
97
|
+
# need to do any matching of constants to type variables to bind their names, Ruby will
|
98
|
+
# do that automatically for us and we get the `name` method for free from `Module`.
|
99
|
+
class TypeVariableModule < Module
|
70
100
|
extend T::Sig
|
71
101
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
102
|
+
class Type < T::Enum
|
103
|
+
enums do
|
104
|
+
Member = new("type_member")
|
105
|
+
Template = new("type_template")
|
106
|
+
end
|
107
|
+
end
|
77
108
|
|
78
|
-
sig
|
79
|
-
|
80
|
-
|
109
|
+
sig do
|
110
|
+
params(context: Module, type: Type, variance: Symbol, fixed: T.untyped, lower: T.untyped, upper: T.untyped).void
|
111
|
+
end
|
112
|
+
def initialize(context, type, variance, fixed, lower, upper) # rubocop:disable Metrics/ParameterLists
|
113
|
+
@context = context
|
114
|
+
@type = type
|
115
|
+
@variance = variance
|
81
116
|
@fixed = fixed
|
82
117
|
@lower = lower
|
83
118
|
@upper = upper
|
119
|
+
super()
|
84
120
|
end
|
85
121
|
|
86
|
-
sig { returns(String) }
|
87
|
-
def serialize
|
88
|
-
parts = []
|
89
|
-
parts << ":#{@variance}" unless @variance == :invariant
|
90
|
-
parts << "fixed: #{@fixed}" if @fixed
|
91
|
-
parts << "lower: #{@lower}" unless @lower == T.untyped
|
92
|
-
parts << "upper: #{@upper}" unless @upper == BasicObject
|
93
|
-
|
94
|
-
parameters = parts.join(", ")
|
95
|
-
|
96
|
-
serialized = +"type_member"
|
97
|
-
serialized << "(#{parameters})" unless parameters.empty?
|
98
|
-
serialized
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
class TypeTemplate < T::Types::TypeTemplate
|
103
|
-
extend T::Sig
|
104
|
-
|
105
122
|
sig { returns(T.nilable(String)) }
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
123
|
+
def name
|
124
|
+
constant_name = super
|
125
|
+
|
126
|
+
# This is a hack to work around modules under anonymous modules not having
|
127
|
+
# names in 2.6 and 2.7: https://bugs.ruby-lang.org/issues/14895
|
128
|
+
#
|
129
|
+
# This happens when a type variable is declared under `class << self`, for
|
130
|
+
# example.
|
131
|
+
#
|
132
|
+
# The workaround is to give the parent context a name, at which point, our
|
133
|
+
# module gets bound to a name under that name, as well.
|
134
|
+
unless constant_name
|
135
|
+
constant_name = with_bound_name_pre_3_0 { super }
|
136
|
+
end
|
110
137
|
|
111
|
-
|
112
|
-
def initialize(variance, fixed, lower, upper)
|
113
|
-
super(variance)
|
114
|
-
@fixed = fixed
|
115
|
-
@lower = lower
|
116
|
-
@upper = upper
|
138
|
+
constant_name&.split("::")&.last
|
117
139
|
end
|
118
140
|
|
119
141
|
sig { returns(String) }
|
@@ -126,9 +148,25 @@ module Tapioca
|
|
126
148
|
|
127
149
|
parameters = parts.join(", ")
|
128
150
|
|
129
|
-
serialized =
|
151
|
+
serialized = @type.serialize.dup
|
130
152
|
serialized << "(#{parameters})" unless parameters.empty?
|
131
153
|
serialized
|
132
154
|
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
sig do
|
159
|
+
type_parameters(:Result)
|
160
|
+
.params(block: T.proc.returns(T.type_parameter(:Result)))
|
161
|
+
.returns(T.type_parameter(:Result))
|
162
|
+
end
|
163
|
+
def with_bound_name_pre_3_0(&block)
|
164
|
+
require "securerandom"
|
165
|
+
temp_name = "TYPE_VARIABLE_TRACKING_#{SecureRandom.hex}"
|
166
|
+
self.class.const_set(temp_name, @context)
|
167
|
+
block.call
|
168
|
+
ensure
|
169
|
+
self.class.send(:remove_const, temp_name) if temp_name
|
170
|
+
end
|
133
171
|
end
|
134
172
|
end
|
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.6.
|
4
|
+
version: 0.6.4
|
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:
|
14
|
+
date: 2022-02-11 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -115,14 +115,14 @@ dependencies:
|
|
115
115
|
requirements:
|
116
116
|
- - ">="
|
117
117
|
- !ruby/object:Gem::Version
|
118
|
-
version:
|
118
|
+
version: 1.2.0
|
119
119
|
type: :runtime
|
120
120
|
prerelease: false
|
121
121
|
version_requirements: !ruby/object:Gem::Requirement
|
122
122
|
requirements:
|
123
123
|
- - ">="
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version:
|
125
|
+
version: 1.2.0
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: yard-sorbet
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|