tapioca 0.4.17 → 0.4.22
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 +13 -14
- data/README.md +4 -2
- data/exe/tapioca +17 -2
- data/lib/tapioca.rb +1 -27
- data/lib/tapioca/cli.rb +1 -108
- data/lib/tapioca/cli/main.rb +146 -0
- data/lib/tapioca/compilers/dsl/active_job.rb +71 -0
- data/lib/tapioca/compilers/dsl/active_record_columns.rb +4 -4
- data/lib/tapioca/compilers/dsl/active_record_scope.rb +1 -1
- data/lib/tapioca/compilers/dsl/base.rb +1 -1
- data/lib/tapioca/compilers/dsl/protobuf.rb +132 -16
- data/lib/tapioca/compilers/dsl/url_helpers.rb +3 -3
- data/lib/tapioca/compilers/requires_compiler.rb +1 -1
- data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +264 -301
- data/lib/tapioca/config.rb +1 -1
- data/lib/tapioca/config_builder.rb +7 -12
- data/lib/tapioca/core_ext/string.rb +18 -0
- data/lib/tapioca/gemfile.rb +1 -1
- data/lib/tapioca/generator.rb +144 -37
- data/lib/tapioca/generic_type_registry.rb +222 -0
- data/lib/tapioca/internal.rb +28 -0
- data/lib/tapioca/rbi/model.rb +405 -0
- data/lib/tapioca/rbi/printer.rb +410 -0
- data/lib/tapioca/rbi/rewriters/group_nodes.rb +106 -0
- data/lib/tapioca/rbi/rewriters/nest_non_public_methods.rb +65 -0
- data/lib/tapioca/rbi/rewriters/nest_singleton_methods.rb +42 -0
- data/lib/tapioca/rbi/rewriters/sort_nodes.rb +82 -0
- data/lib/tapioca/rbi/visitor.rb +21 -0
- data/lib/tapioca/sorbet_ext/generic_name_patch.rb +66 -0
- data/lib/tapioca/sorbet_ext/name_patch.rb +16 -0
- data/lib/tapioca/version.rb +1 -1
- metadata +17 -3
@@ -371,7 +371,6 @@ module Tapioca
|
|
371
371
|
return unless signature
|
372
372
|
|
373
373
|
return_type = signature.return_type
|
374
|
-
return if T::Types::Simple === return_type && T::Generic === return_type.raw_type
|
375
374
|
return if return_type == T::Private::Types::Void || return_type == T::Private::Types::NotTyped
|
376
375
|
|
377
376
|
return_type.to_s
|
@@ -382,10 +381,11 @@ module Tapioca
|
|
382
381
|
signature = T::Private::Methods.signature_for_method(column_type.method(method))
|
383
382
|
return unless signature
|
384
383
|
|
385
|
-
|
386
|
-
|
384
|
+
# Arg types is an array [name, type] entries, so we desctructure the type of
|
385
|
+
# first argument to get the first argument type
|
386
|
+
_, first_argument_type = signature.arg_types.first
|
387
387
|
|
388
|
-
|
388
|
+
first_argument_type.to_s
|
389
389
|
end
|
390
390
|
|
391
391
|
sig { params(type: String).returns(String) }
|
@@ -123,7 +123,7 @@ module Tapioca
|
|
123
123
|
# Compile a Ruby method return type into a Parlour type
|
124
124
|
sig do
|
125
125
|
params(method_def: T.any(Method, UnboundMethod))
|
126
|
-
.returns(String)
|
126
|
+
.returns(T.nilable(String))
|
127
127
|
end
|
128
128
|
def compile_method_return_type_to_parlour(method_def)
|
129
129
|
signature = T::Private::Methods.signature_for_method(method_def)
|
@@ -62,33 +62,99 @@ module Tapioca
|
|
62
62
|
# end
|
63
63
|
# ~~~
|
64
64
|
class Protobuf < Base
|
65
|
+
# Parlour doesn't support type members out of the box, so adding the
|
66
|
+
# ability to do that here. This should be upstreamed.
|
67
|
+
class TypeMember < Parlour::RbiGenerator::RbiObject
|
68
|
+
extend T::Sig
|
69
|
+
|
70
|
+
sig { params(other: Object).returns(T::Boolean) }
|
71
|
+
def ==(other)
|
72
|
+
TypeMember === other && name == other.name
|
73
|
+
end
|
74
|
+
|
75
|
+
sig do
|
76
|
+
override
|
77
|
+
.params(indent_level: Integer, options: Parlour::RbiGenerator::Options)
|
78
|
+
.returns(T::Array[String])
|
79
|
+
end
|
80
|
+
def generate_rbi(indent_level, options)
|
81
|
+
[options.indented(indent_level, "#{name} = type_member")]
|
82
|
+
end
|
83
|
+
|
84
|
+
sig do
|
85
|
+
override
|
86
|
+
.params(others: T::Array[Parlour::RbiGenerator::RbiObject])
|
87
|
+
.returns(T::Boolean)
|
88
|
+
end
|
89
|
+
def mergeable?(others)
|
90
|
+
others.all? { |other| self == other }
|
91
|
+
end
|
92
|
+
|
93
|
+
sig { override.params(others: T::Array[Parlour::RbiGenerator::RbiObject]).void }
|
94
|
+
def merge_into_self(others); end
|
95
|
+
|
96
|
+
sig { override.returns(String) }
|
97
|
+
def describe
|
98
|
+
"Type Member (#{name})"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class Field < T::Struct
|
103
|
+
prop :name, String
|
104
|
+
prop :type, String
|
105
|
+
prop :init_type, String
|
106
|
+
prop :default, String
|
107
|
+
|
108
|
+
extend T::Sig
|
109
|
+
|
110
|
+
sig { returns(Parlour::RbiGenerator::Parameter) }
|
111
|
+
def to_init
|
112
|
+
Parlour::RbiGenerator::Parameter.new("#{name}:", type: init_type, default: default)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
65
116
|
extend T::Sig
|
66
117
|
|
67
118
|
sig do
|
68
119
|
override.params(
|
69
120
|
root: Parlour::RbiGenerator::Namespace,
|
70
|
-
constant:
|
121
|
+
constant: Module
|
71
122
|
).void
|
72
123
|
end
|
73
124
|
def decorate(root, constant)
|
74
|
-
descriptor = T.let(T.unsafe(constant).descriptor, Google::Protobuf::Descriptor)
|
75
|
-
return unless descriptor.any?
|
76
|
-
|
77
125
|
root.path(constant) do |klass|
|
78
|
-
|
79
|
-
|
126
|
+
if constant == Google::Protobuf::RepeatedField
|
127
|
+
create_type_members(klass, "Elem")
|
128
|
+
elsif constant == Google::Protobuf::Map
|
129
|
+
create_type_members(klass, "Key", "Value")
|
130
|
+
else
|
131
|
+
descriptor = T.let(T.unsafe(constant).descriptor, Google::Protobuf::Descriptor)
|
132
|
+
fields = descriptor.map { |desc| create_descriptor_method(klass, desc) }
|
133
|
+
fields.sort_by!(&:name)
|
134
|
+
|
135
|
+
create_method(klass, "initialize", parameters: fields.map!(&:to_init))
|
80
136
|
end
|
81
137
|
end
|
82
138
|
end
|
83
139
|
|
84
140
|
sig { override.returns(T::Enumerable[Module]) }
|
85
141
|
def gather_constants
|
86
|
-
|
87
|
-
|
142
|
+
marker = Google::Protobuf::MessageExts::ClassMethods
|
143
|
+
results = T.cast(ObjectSpace.each_object(marker).to_a, T::Array[Module])
|
144
|
+
results.any? ? results + [Google::Protobuf::RepeatedField, Google::Protobuf::Map] : []
|
88
145
|
end
|
89
146
|
|
90
147
|
private
|
91
148
|
|
149
|
+
sig { params(klass: Parlour::RbiGenerator::Namespace, names: String).void }
|
150
|
+
def create_type_members(klass, *names)
|
151
|
+
klass.create_extend("T::Generic")
|
152
|
+
|
153
|
+
names.each do |name|
|
154
|
+
klass.children << TypeMember.new(klass.generator, name)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
92
158
|
sig do
|
93
159
|
params(
|
94
160
|
descriptor: Google::Protobuf::FieldDescriptor
|
@@ -113,30 +179,80 @@ module Tapioca
|
|
113
179
|
end
|
114
180
|
end
|
115
181
|
|
182
|
+
sig { params(descriptor: Google::Protobuf::FieldDescriptor).returns(Field) }
|
183
|
+
def field_of(descriptor)
|
184
|
+
if descriptor.label == :repeated
|
185
|
+
# Here we're going to check if the submsg_name is named according to
|
186
|
+
# how Google names map entries.
|
187
|
+
# https://github.com/protocolbuffers/protobuf/blob/f82e26/ruby/ext/google/protobuf_c/defs.c#L1963-L1966
|
188
|
+
if descriptor.submsg_name.to_s.end_with?("_MapEntry_#{descriptor.name}")
|
189
|
+
key = descriptor.subtype.lookup('key')
|
190
|
+
value = descriptor.subtype.lookup('value')
|
191
|
+
|
192
|
+
key_type = type_of(key)
|
193
|
+
value_type = type_of(value)
|
194
|
+
type = "Google::Protobuf::Map[#{key_type}, #{value_type}]"
|
195
|
+
|
196
|
+
default_args = [key.type.inspect, value.type.inspect]
|
197
|
+
default_args << value_type if %i[enum message].include?(value.type)
|
198
|
+
|
199
|
+
Field.new(
|
200
|
+
name: descriptor.name,
|
201
|
+
type: type,
|
202
|
+
init_type: "T.any(#{type}, T::Hash[#{key_type}, #{value_type}])",
|
203
|
+
default: "Google::Protobuf::Map.new(#{default_args.join(', ')})"
|
204
|
+
)
|
205
|
+
else
|
206
|
+
elem_type = type_of(descriptor)
|
207
|
+
type = "Google::Protobuf::RepeatedField[#{elem_type}]"
|
208
|
+
|
209
|
+
default_args = [descriptor.type.inspect]
|
210
|
+
default_args << elem_type if %i[enum message].include?(descriptor.type)
|
211
|
+
|
212
|
+
Field.new(
|
213
|
+
name: descriptor.name,
|
214
|
+
type: type,
|
215
|
+
init_type: "T.any(#{type}, T::Array[#{elem_type}])",
|
216
|
+
default: "Google::Protobuf::RepeatedField.new(#{default_args.join(', ')})"
|
217
|
+
)
|
218
|
+
end
|
219
|
+
else
|
220
|
+
type = type_of(descriptor)
|
221
|
+
|
222
|
+
Field.new(
|
223
|
+
name: descriptor.name,
|
224
|
+
type: type,
|
225
|
+
init_type: type,
|
226
|
+
default: "nil"
|
227
|
+
)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
116
231
|
sig do
|
117
232
|
params(
|
118
233
|
klass: Parlour::RbiGenerator::Namespace,
|
119
234
|
desc: Google::Protobuf::FieldDescriptor,
|
120
|
-
).
|
235
|
+
).returns(Field)
|
121
236
|
end
|
122
237
|
def create_descriptor_method(klass, desc)
|
123
|
-
|
124
|
-
type = type_of(desc)
|
238
|
+
field = field_of(desc)
|
125
239
|
|
126
240
|
create_method(
|
127
241
|
klass,
|
128
|
-
name,
|
129
|
-
return_type: type
|
242
|
+
field.name,
|
243
|
+
return_type: field.type
|
130
244
|
)
|
131
245
|
|
132
246
|
create_method(
|
133
247
|
klass,
|
134
|
-
"#{name}=",
|
248
|
+
"#{field.name}=",
|
135
249
|
parameters: [
|
136
|
-
Parlour::RbiGenerator::Parameter.new("value", type: type),
|
250
|
+
Parlour::RbiGenerator::Parameter.new("value", type: field.type),
|
137
251
|
],
|
138
|
-
return_type: type
|
252
|
+
return_type: field.type
|
139
253
|
)
|
254
|
+
|
255
|
+
field
|
140
256
|
end
|
141
257
|
end
|
142
258
|
end
|
@@ -89,7 +89,7 @@ module Tapioca
|
|
89
89
|
class UrlHelpers < Base
|
90
90
|
extend T::Sig
|
91
91
|
|
92
|
-
sig { override.params(root: Parlour::RbiGenerator::Namespace, constant:
|
92
|
+
sig { override.params(root: Parlour::RbiGenerator::Namespace, constant: Module).void }
|
93
93
|
def decorate(root, constant)
|
94
94
|
case constant
|
95
95
|
when GeneratedPathHelpersModule.singleton_class, GeneratedUrlHelpersModule.singleton_class
|
@@ -127,7 +127,7 @@ module Tapioca
|
|
127
127
|
|
128
128
|
private
|
129
129
|
|
130
|
-
sig { params(root: Parlour::RbiGenerator::Namespace, constant:
|
130
|
+
sig { params(root: Parlour::RbiGenerator::Namespace, constant: Module).void }
|
131
131
|
def generate_module_for(root, constant)
|
132
132
|
root.create_module(T.must(constant.name)) do |mod|
|
133
133
|
mod.create_include("::ActionDispatch::Routing::UrlFor")
|
@@ -143,7 +143,7 @@ module Tapioca
|
|
143
143
|
end
|
144
144
|
end
|
145
145
|
|
146
|
-
sig { params(mod: Parlour::RbiGenerator::Namespace, constant:
|
146
|
+
sig { params(mod: Parlour::RbiGenerator::Namespace, constant: Module, helper_module: Module).void }
|
147
147
|
def create_mixins_for(mod, constant, helper_module)
|
148
148
|
include_helper = constant.ancestors.include?(helper_module) || NON_DISCOVERABLE_INCLUDERS.include?(constant)
|
149
149
|
extend_helper = constant.singleton_class.ancestors.include?(helper_module)
|
@@ -23,24 +23,34 @@ module Tapioca
|
|
23
23
|
@indent = indent
|
24
24
|
@seen = Set.new
|
25
25
|
@alias_namespace ||= Set.new
|
26
|
+
@symbol_queue = T.let(symbols.sort.dup, T::Array[String])
|
26
27
|
end
|
27
28
|
|
28
29
|
sig { returns(String) }
|
29
30
|
def generate
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
rbi = RBI::Tree.new
|
32
|
+
|
33
|
+
generate_from_symbol(rbi, T.must(@symbol_queue.shift)) until @symbol_queue.empty?
|
34
|
+
|
35
|
+
rbi.nest_singleton_methods!
|
36
|
+
rbi.nest_non_public_methods!
|
37
|
+
rbi.group_nodes!
|
38
|
+
rbi.sort_nodes!
|
39
|
+
rbi.string
|
36
40
|
end
|
37
41
|
|
38
42
|
private
|
39
43
|
|
44
|
+
def add_to_symbol_queue(name)
|
45
|
+
@symbol_queue << name unless symbols.include?(name) || symbol_ignored?(name)
|
46
|
+
end
|
47
|
+
|
40
48
|
sig { returns(T::Set[String]) }
|
41
49
|
def symbols
|
42
|
-
symbols
|
43
|
-
|
50
|
+
@symbols ||= begin
|
51
|
+
symbols = Tapioca::Compilers::SymbolTable::SymbolLoader.list_from_paths(gem.files)
|
52
|
+
symbols.union(engine_symbols(symbols))
|
53
|
+
end
|
44
54
|
end
|
45
55
|
|
46
56
|
sig { params(symbols: T::Set[String]).returns(T::Set[String]) }
|
@@ -65,28 +75,30 @@ module Tapioca
|
|
65
75
|
Set.new
|
66
76
|
end
|
67
77
|
|
68
|
-
sig { params(symbol: String).
|
69
|
-
def generate_from_symbol(symbol)
|
78
|
+
sig { params(tree: RBI::Tree, symbol: String).void }
|
79
|
+
def generate_from_symbol(tree, symbol)
|
70
80
|
constant = resolve_constant(symbol)
|
71
81
|
|
72
82
|
return unless constant
|
73
83
|
|
74
|
-
compile(symbol, constant)
|
84
|
+
compile(tree, symbol, constant)
|
75
85
|
end
|
76
86
|
|
77
|
-
sig
|
78
|
-
|
79
|
-
|
87
|
+
sig do
|
88
|
+
params(
|
89
|
+
symbol: String,
|
90
|
+
inherit: T::Boolean,
|
91
|
+
namespace: Module
|
92
|
+
).returns(BasicObject).checked(:never)
|
93
|
+
end
|
94
|
+
def resolve_constant(symbol, inherit: false, namespace: Object)
|
95
|
+
namespace.const_get(symbol, inherit)
|
80
96
|
rescue NameError, LoadError, RuntimeError, ArgumentError, TypeError
|
81
97
|
nil
|
82
98
|
end
|
83
99
|
|
84
|
-
sig
|
85
|
-
|
86
|
-
.returns(T.nilable(String))
|
87
|
-
.checked(:never)
|
88
|
-
end
|
89
|
-
def compile(name, constant)
|
100
|
+
sig { params(tree: RBI::Tree, name: T.nilable(String), constant: BasicObject).void.checked(:never) }
|
101
|
+
def compile(tree, name, constant)
|
90
102
|
return unless constant
|
91
103
|
return unless name
|
92
104
|
return if name.strip.empty?
|
@@ -94,33 +106,28 @@ module Tapioca
|
|
94
106
|
return if name.downcase == name
|
95
107
|
return if alias_namespaced?(name)
|
96
108
|
return if seen?(name)
|
97
|
-
return unless parent_declares_constant?(name)
|
98
109
|
return if T::Enum === constant # T::Enum instances are defined via `compile_enums`
|
99
110
|
|
100
111
|
mark_seen(name)
|
101
|
-
compile_constant(name, constant)
|
112
|
+
compile_constant(tree, name, constant)
|
102
113
|
end
|
103
114
|
|
104
|
-
sig
|
105
|
-
|
106
|
-
.returns(T.nilable(String))
|
107
|
-
.checked(:never)
|
108
|
-
end
|
109
|
-
def compile_constant(name, constant)
|
115
|
+
sig { params(tree: RBI::Tree, name: String, constant: BasicObject).void.checked(:never) }
|
116
|
+
def compile_constant(tree, name, constant)
|
110
117
|
case constant
|
111
118
|
when Module
|
112
119
|
if name_of(constant) != name
|
113
|
-
compile_alias(name, constant)
|
120
|
+
compile_alias(tree, name, constant)
|
114
121
|
else
|
115
|
-
compile_module(name, constant)
|
122
|
+
compile_module(tree, name, constant)
|
116
123
|
end
|
117
124
|
else
|
118
|
-
compile_object(name, constant)
|
125
|
+
compile_object(tree, name, constant)
|
119
126
|
end
|
120
127
|
end
|
121
128
|
|
122
|
-
sig { params(name: String, constant: Module).
|
123
|
-
def compile_alias(name, constant)
|
129
|
+
sig { params(tree: RBI::Tree, name: String, constant: Module).void }
|
130
|
+
def compile_alias(tree, name, constant)
|
124
131
|
return if symbol_ignored?(name)
|
125
132
|
|
126
133
|
target = name_of(constant)
|
@@ -131,114 +138,99 @@ module Tapioca
|
|
131
138
|
|
132
139
|
return if IGNORED_SYMBOLS.include?(name)
|
133
140
|
|
134
|
-
|
141
|
+
tree << RBI::Const.new(name, target)
|
135
142
|
end
|
136
143
|
|
137
|
-
sig
|
138
|
-
|
139
|
-
.returns(T.nilable(String))
|
140
|
-
.checked(:never)
|
141
|
-
end
|
142
|
-
def compile_object(name, value)
|
144
|
+
sig { params(tree: RBI::Tree, name: String, value: BasicObject).void.checked(:never) }
|
145
|
+
def compile_object(tree, name, value)
|
143
146
|
return if symbol_ignored?(name)
|
144
147
|
klass = class_of(value)
|
145
|
-
|
148
|
+
klass_name = name_of(klass)
|
149
|
+
|
150
|
+
if klass_name == "T::Private::Types::TypeAlias"
|
151
|
+
tree << RBI::Const.new(name, "T.type_alias { #{T.unsafe(value).aliased_type} }")
|
152
|
+
return
|
153
|
+
end
|
154
|
+
|
155
|
+
return if klass_name&.start_with?("T::Types::", "T::Private::")
|
156
|
+
|
157
|
+
type_name = klass_name || "T.untyped"
|
158
|
+
# TODO: Do this in a more generic and clean way.
|
159
|
+
type_name = "#{type_name}[T.untyped]" if type_name == "ObjectSpace::WeakMap"
|
146
160
|
|
147
|
-
|
148
|
-
indented("#{name} = T.let(T.unsafe(nil), #{type_name})")
|
161
|
+
tree << RBI::Const.new(name, "T.let(T.unsafe(nil), #{type_name})")
|
149
162
|
end
|
150
163
|
|
151
|
-
sig { params(name: String, constant: Module).
|
152
|
-
def compile_module(name, constant)
|
153
|
-
return unless public_module?(constant)
|
164
|
+
sig { params(tree: RBI::Tree, name: String, constant: Module).void }
|
165
|
+
def compile_module(tree, name, constant)
|
154
166
|
return unless defined_in_gem?(constant, strict: false)
|
155
167
|
|
156
|
-
|
168
|
+
scope =
|
157
169
|
if constant.is_a?(Class)
|
158
|
-
|
170
|
+
superclass = compile_superclass(constant)
|
171
|
+
RBI::Class.new(name, superclass_name: superclass)
|
159
172
|
else
|
160
|
-
|
173
|
+
RBI::Module.new(name)
|
161
174
|
end
|
162
175
|
|
163
|
-
|
176
|
+
compile_body(scope, name, constant)
|
164
177
|
|
165
|
-
return if symbol_ignored?(name) &&
|
178
|
+
return if symbol_ignored?(name) && scope.empty?
|
166
179
|
|
167
|
-
|
168
|
-
|
169
|
-
body,
|
170
|
-
indented("end"),
|
171
|
-
compile_subconstants(name, constant),
|
172
|
-
].select { |b| !b.nil? && b.strip != "" }.join("\n")
|
180
|
+
tree << scope
|
181
|
+
compile_subconstants(tree, name, constant)
|
173
182
|
end
|
174
183
|
|
175
|
-
sig { params(name: String, constant: Module).
|
176
|
-
def compile_body(name, constant)
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
compile_mixins(constant),
|
185
|
-
compile_mixes_in_class_methods(constant),
|
186
|
-
compile_props(constant),
|
187
|
-
compile_enums(constant),
|
188
|
-
methods,
|
189
|
-
].select { |b| b != "" }.join("\n\n")
|
190
|
-
end
|
184
|
+
sig { params(tree: RBI::Tree, name: String, constant: Module).void }
|
185
|
+
def compile_body(tree, name, constant)
|
186
|
+
compile_methods(tree, name, constant)
|
187
|
+
compile_module_helpers(tree, constant)
|
188
|
+
compile_type_variables(tree, constant)
|
189
|
+
compile_mixins(tree, constant)
|
190
|
+
compile_mixes_in_class_methods(tree, constant)
|
191
|
+
compile_props(tree, constant)
|
192
|
+
compile_enums(tree, constant)
|
191
193
|
end
|
192
194
|
|
193
|
-
sig { params(constant: Module).
|
194
|
-
def compile_module_helpers(constant)
|
195
|
+
sig { params(tree: RBI::Tree, constant: Module).void }
|
196
|
+
def compile_module_helpers(tree, constant)
|
195
197
|
abstract_type = T::Private::Abstract::Data.get(constant, :abstract_type)
|
196
198
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
helpers << indented("sealed!") if T::Private::Sealed.sealed_module?(constant)
|
201
|
-
|
202
|
-
helpers.join("\n")
|
199
|
+
tree << RBI::Helper.new(abstract_type.to_s) if abstract_type
|
200
|
+
tree << RBI::Helper.new("final") if T::Private::Final.final_module?(constant)
|
201
|
+
tree << RBI::Helper.new("sealed") if T::Private::Sealed.sealed_module?(constant)
|
203
202
|
end
|
204
203
|
|
205
|
-
sig { params(constant: Module).
|
206
|
-
def compile_props(constant)
|
207
|
-
return
|
204
|
+
sig { params(tree: RBI::Tree, constant: Module).void }
|
205
|
+
def compile_props(tree, constant)
|
206
|
+
return unless T::Props::ClassMethods === constant
|
208
207
|
|
209
208
|
constant.props.map do |name, prop|
|
210
|
-
method = "prop"
|
211
|
-
method = "const" if prop.fetch(:immutable, false)
|
212
209
|
type = prop.fetch(:type_object, "T.untyped").to_s.gsub(".returns(<VOID>)", ".void")
|
213
210
|
|
214
|
-
|
215
|
-
|
211
|
+
default = prop.key?(:default) ? "T.unsafe(nil)" : nil
|
212
|
+
tree << if prop.fetch(:immutable, false)
|
213
|
+
RBI::TStructConst.new(name.to_s, type, default: default)
|
216
214
|
else
|
217
|
-
|
215
|
+
RBI::TStructProp.new(name.to_s, type, default: default)
|
218
216
|
end
|
219
|
-
end
|
217
|
+
end
|
220
218
|
end
|
221
219
|
|
222
|
-
sig { params(constant: Module).
|
223
|
-
def compile_enums(constant)
|
224
|
-
return
|
220
|
+
sig { params(tree: RBI::Tree, constant: Module).void }
|
221
|
+
def compile_enums(tree, constant)
|
222
|
+
return unless T::Enum > constant
|
225
223
|
|
226
|
-
enums = T.
|
224
|
+
enums = T.unsafe(constant).values.map do |enum_type|
|
227
225
|
enum_type.instance_variable_get(:@const_name).to_s
|
228
226
|
end
|
229
227
|
|
230
|
-
|
231
|
-
indented('enums do'),
|
232
|
-
*enums.map { |e| indented(" #{e} = new") }.join("\n"),
|
233
|
-
indented('end'),
|
234
|
-
]
|
235
|
-
|
236
|
-
content.join("\n")
|
228
|
+
tree << RBI::TEnumBlock.new(enums)
|
237
229
|
end
|
238
230
|
|
239
|
-
sig { params(name: String, constant: Module).
|
240
|
-
def compile_subconstants(name, constant)
|
241
|
-
|
231
|
+
sig { params(tree: RBI::Tree, name: String, constant: Module).void }
|
232
|
+
def compile_subconstants(tree, name, constant)
|
233
|
+
constants_of(constant).sort.uniq.map do |constant_name|
|
242
234
|
symbol = (name == "Object" ? "" : name) + "::#{constant_name}"
|
243
235
|
subconstant = resolve_constant(symbol)
|
244
236
|
|
@@ -247,15 +239,58 @@ module Tapioca
|
|
247
239
|
next if (Object == constant || BasicObject == constant) && Module === subconstant
|
248
240
|
next unless subconstant
|
249
241
|
|
250
|
-
compile(symbol, subconstant)
|
251
|
-
end
|
242
|
+
compile(tree, symbol, subconstant)
|
243
|
+
end
|
244
|
+
end
|
252
245
|
|
253
|
-
|
246
|
+
sig { params(tree: RBI::Tree, constant: Module).void }
|
247
|
+
def compile_type_variables(tree, constant)
|
248
|
+
compile_type_variable_declarations(tree, constant)
|
254
249
|
|
255
|
-
|
250
|
+
sclass = RBI::SingletonClass.new
|
251
|
+
compile_type_variable_declarations(sclass, singleton_class_of(constant))
|
252
|
+
tree << sclass if sclass.nodes.length > 1
|
256
253
|
end
|
257
254
|
|
258
|
-
sig { params(constant:
|
255
|
+
sig { params(tree: RBI::Tree, constant: Module).void }
|
256
|
+
def compile_type_variable_declarations(tree, constant)
|
257
|
+
# Try to find the type variables defined on this constant, bail if we can't
|
258
|
+
type_variables = GenericTypeRegistry.lookup_type_variables(constant)
|
259
|
+
return unless type_variables
|
260
|
+
|
261
|
+
# Create a map of subconstants (via their object ids) to their names.
|
262
|
+
# We need this later when we want to lookup the name of the registered type
|
263
|
+
# variable via the value of the type variable constant.
|
264
|
+
subconstant_to_name_lookup = constants_of(constant).map do |constant_name|
|
265
|
+
[
|
266
|
+
object_id_of(resolve_constant(constant_name.to_s, namespace: constant)),
|
267
|
+
constant_name,
|
268
|
+
]
|
269
|
+
end.to_h
|
270
|
+
|
271
|
+
# Map each type variable to its string representation.
|
272
|
+
#
|
273
|
+
# Each entry of `type_variables` maps an object_id to a String,
|
274
|
+
# and the order they are inserted into the hash is the order they should be
|
275
|
+
# defined in the source code.
|
276
|
+
#
|
277
|
+
# By looping over these entries and then getting the actual constant name
|
278
|
+
# from the `subconstant_to_name_lookup` we defined above, gives us all the
|
279
|
+
# information we need to serialize type variable definitions.
|
280
|
+
type_variable_declarations = type_variables.map do |type_variable_id, serialized_type_variable|
|
281
|
+
constant_name = subconstant_to_name_lookup[type_variable_id]
|
282
|
+
# Here, we know that constant_value will be an instance of
|
283
|
+
# T::Types::CustomTypeVariable, which knows how to serialize
|
284
|
+
# itself to a type_member/type_template
|
285
|
+
tree << RBI::TypeMember.new(constant_name.to_s, serialized_type_variable)
|
286
|
+
end
|
287
|
+
|
288
|
+
return if type_variable_declarations.empty?
|
289
|
+
|
290
|
+
tree << RBI::Extend.new("T::Generic")
|
291
|
+
end
|
292
|
+
|
293
|
+
sig { params(constant: Class).returns(T.nilable(String)) }
|
259
294
|
def compile_superclass(constant)
|
260
295
|
superclass = T.let(nil, T.nilable(Class)) # rubocop:disable Lint/UselessAssignment
|
261
296
|
|
@@ -263,15 +298,6 @@ module Tapioca
|
|
263
298
|
constant_name = name_of(constant)
|
264
299
|
constant = superclass
|
265
300
|
|
266
|
-
# Some classes have superclasses that are private constants
|
267
|
-
# so if we generate code with that superclass, the output
|
268
|
-
# will not be compilable (since private constants are not
|
269
|
-
# publicly visible).
|
270
|
-
#
|
271
|
-
# So we skip superclasses that are not public and walk up the
|
272
|
-
# chain.
|
273
|
-
next unless public_module?(superclass)
|
274
|
-
|
275
301
|
# Some types have "themselves" as their superclass
|
276
302
|
# which can happen via:
|
277
303
|
#
|
@@ -291,7 +317,9 @@ module Tapioca
|
|
291
317
|
# B = A
|
292
318
|
# A.superclass.name #=> "B"
|
293
319
|
# B #=> A
|
294
|
-
superclass_name =
|
320
|
+
superclass_name = name_of(superclass)
|
321
|
+
next unless superclass_name
|
322
|
+
|
295
323
|
resolved_superclass = resolve_constant(superclass_name)
|
296
324
|
next unless Module === resolved_superclass
|
297
325
|
next if name_of(resolved_superclass) == constant_name
|
@@ -300,17 +328,19 @@ module Tapioca
|
|
300
328
|
break
|
301
329
|
end
|
302
330
|
|
303
|
-
return
|
304
|
-
return
|
331
|
+
return if superclass == ::Object || superclass == ::Delegator
|
332
|
+
return if superclass.nil?
|
305
333
|
|
306
334
|
name = name_of(superclass)
|
307
|
-
return
|
335
|
+
return if name.nil? || name.empty?
|
336
|
+
|
337
|
+
add_to_symbol_queue(name)
|
308
338
|
|
309
|
-
"
|
339
|
+
"::#{name}"
|
310
340
|
end
|
311
341
|
|
312
|
-
sig { params(constant: Module).
|
313
|
-
def compile_mixins(constant)
|
342
|
+
sig { params(tree: RBI::Tree, constant: Module).void }
|
343
|
+
def compile_mixins(tree, constant)
|
314
344
|
singleton_class = singleton_class_of(constant)
|
315
345
|
|
316
346
|
interesting_ancestors = interesting_ancestors_of(constant)
|
@@ -319,42 +349,46 @@ module Tapioca
|
|
319
349
|
prepend = interesting_ancestors.take_while { |c| !are_equal?(constant, c) }
|
320
350
|
include = interesting_ancestors.drop(prepend.size + 1)
|
321
351
|
extend = interesting_singleton_class_ancestors.reject do |mod|
|
322
|
-
|
352
|
+
Module != class_of(mod) || are_equal?(mod, singleton_class)
|
323
353
|
end
|
324
354
|
|
325
|
-
|
355
|
+
prepend
|
326
356
|
.reverse
|
327
357
|
.select { |mod| (name = name_of(mod)) && !name.start_with?("T::") }
|
328
|
-
.select(&method(:public_module?))
|
329
358
|
.map do |mod|
|
359
|
+
add_to_symbol_queue(name_of(mod))
|
360
|
+
|
330
361
|
# TODO: Sorbet currently does not handle prepend
|
331
362
|
# properly for method resolution, so we generate an
|
332
363
|
# include statement instead
|
333
|
-
|
364
|
+
qname = qualified_name_of(mod)
|
365
|
+
tree << RBI::Include.new(T.must(qname))
|
334
366
|
end
|
335
367
|
|
336
|
-
|
368
|
+
include
|
337
369
|
.reverse
|
338
370
|
.select { |mod| (name = name_of(mod)) && !name.start_with?("T::") }
|
339
|
-
.select(&method(:public_module?))
|
340
371
|
.map do |mod|
|
341
|
-
|
372
|
+
add_to_symbol_queue(name_of(mod))
|
373
|
+
|
374
|
+
qname = qualified_name_of(mod)
|
375
|
+
tree << RBI::Include.new(T.must(qname))
|
342
376
|
end
|
343
377
|
|
344
|
-
|
378
|
+
extend
|
345
379
|
.reverse
|
346
380
|
.select { |mod| (name = name_of(mod)) && !name.start_with?("T::") }
|
347
|
-
.select(&method(:public_module?))
|
348
381
|
.map do |mod|
|
349
|
-
|
350
|
-
end
|
382
|
+
add_to_symbol_queue(name_of(mod))
|
351
383
|
|
352
|
-
|
384
|
+
qname = qualified_name_of(mod)
|
385
|
+
tree << RBI::Extend.new(T.must(qname))
|
386
|
+
end
|
353
387
|
end
|
354
388
|
|
355
|
-
sig { params(constant: Module).
|
356
|
-
def compile_mixes_in_class_methods(constant)
|
357
|
-
return
|
389
|
+
sig { params(tree: RBI::Tree, constant: Module).void }
|
390
|
+
def compile_mixes_in_class_methods(tree, constant)
|
391
|
+
return if constant.is_a?(Class)
|
358
392
|
|
359
393
|
mixins_from_modules = {}
|
360
394
|
|
@@ -386,11 +420,13 @@ module Tapioca
|
|
386
420
|
dynamic_extends_from_dynamic_includes = mixins_from_modules.values.flatten
|
387
421
|
dynamic_extends = all_dynamic_extends - dynamic_extends_from_dynamic_includes
|
388
422
|
|
389
|
-
|
423
|
+
all_dynamic_includes
|
390
424
|
.select { |mod| (name = name_of(mod)) && !name.start_with?("T::") }
|
391
|
-
.select(&method(:public_module?))
|
392
425
|
.map do |mod|
|
393
|
-
|
426
|
+
add_to_symbol_queue(name_of(mod))
|
427
|
+
|
428
|
+
qname = qualified_name_of(mod)
|
429
|
+
tree << RBI::Include.new(T.must(qname))
|
394
430
|
end.join("\n")
|
395
431
|
|
396
432
|
ancestors = singleton_class_of(constant).ancestors
|
@@ -402,84 +438,57 @@ module Tapioca
|
|
402
438
|
mixed_in_module = if extends_as_concern && Module === class_methods_module
|
403
439
|
class_methods_module
|
404
440
|
else
|
405
|
-
dynamic_extends.find
|
406
|
-
mod != constant && public_module?(mod)
|
407
|
-
end
|
441
|
+
dynamic_extends.find { |mod| mod != constant }
|
408
442
|
end
|
409
443
|
|
410
|
-
return
|
444
|
+
return if mixed_in_module.nil?
|
411
445
|
|
412
446
|
qualified_name = qualified_name_of(mixed_in_module)
|
413
|
-
return
|
447
|
+
return if qualified_name.nil? || qualified_name == ""
|
414
448
|
|
415
|
-
|
416
|
-
result,
|
417
|
-
indented("mixes_in_class_methods(#{qualified_name})"),
|
418
|
-
].select { |b| b != "" }.join("\n\n")
|
449
|
+
tree << RBI::MixesInClassMethods.new(qualified_name)
|
419
450
|
rescue
|
420
|
-
|
451
|
+
nil # silence errors
|
421
452
|
end
|
422
453
|
|
423
|
-
sig { params(name: String, constant: Module).
|
424
|
-
def compile_methods(name, constant)
|
425
|
-
|
454
|
+
sig { params(tree: RBI::Tree, name: String, constant: Module).void }
|
455
|
+
def compile_methods(tree, name, constant)
|
456
|
+
compile_method(
|
457
|
+
tree,
|
426
458
|
name,
|
427
459
|
constant,
|
428
460
|
initialize_method_for(constant)
|
429
461
|
)
|
430
462
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
return if symbol_ignored?(name) && instance_methods.empty? && singleton_methods.empty?
|
435
|
-
|
436
|
-
[
|
437
|
-
initialize_method || "",
|
438
|
-
instance_methods,
|
439
|
-
singleton_methods,
|
440
|
-
].select { |b| b.strip != "" }.join("\n\n")
|
463
|
+
compile_directly_owned_methods(tree, name, constant)
|
464
|
+
compile_directly_owned_methods(tree, name, singleton_class_of(constant))
|
441
465
|
end
|
442
466
|
|
443
|
-
sig
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
unless compiled.empty? || visibility == :public
|
466
|
-
# add visibility badge
|
467
|
-
compiled.unshift('', indented(visibility.to_s), '')
|
467
|
+
sig do
|
468
|
+
params(
|
469
|
+
tree: RBI::Tree,
|
470
|
+
module_name: String,
|
471
|
+
mod: Module,
|
472
|
+
for_visibility: T::Array[Symbol]
|
473
|
+
).void
|
474
|
+
end
|
475
|
+
def compile_directly_owned_methods(tree, module_name, mod, for_visibility = [:public, :protected, :private])
|
476
|
+
method_names_by_visibility(mod)
|
477
|
+
.delete_if { |visibility, _method_list| !for_visibility.include?(visibility) }
|
478
|
+
.each do |visibility, method_list|
|
479
|
+
method_list.sort!.map do |name|
|
480
|
+
next if name == :initialize
|
481
|
+
vis = case visibility
|
482
|
+
when :protected
|
483
|
+
RBI::Visibility::Protected
|
484
|
+
when :private
|
485
|
+
RBI::Visibility::Private
|
486
|
+
else
|
487
|
+
RBI::Visibility::Public
|
468
488
|
end
|
469
|
-
|
470
|
-
compiled
|
489
|
+
compile_method(tree, module_name, mod, mod.instance_method(name), vis)
|
471
490
|
end
|
472
|
-
|
473
|
-
.join("\n")
|
474
|
-
end
|
475
|
-
|
476
|
-
return "" if methods.strip == ""
|
477
|
-
|
478
|
-
[
|
479
|
-
preamble,
|
480
|
-
methods,
|
481
|
-
postamble,
|
482
|
-
].compact.join("\n")
|
491
|
+
end
|
483
492
|
end
|
484
493
|
|
485
494
|
sig { params(mod: Module).returns(T::Hash[Symbol, T::Array[Symbol]]) }
|
@@ -503,12 +512,14 @@ module Tapioca
|
|
503
512
|
|
504
513
|
sig do
|
505
514
|
params(
|
515
|
+
tree: RBI::Tree,
|
506
516
|
symbol_name: String,
|
507
517
|
constant: Module,
|
508
|
-
method: T.nilable(UnboundMethod)
|
509
|
-
|
518
|
+
method: T.nilable(UnboundMethod),
|
519
|
+
visibility: RBI::Visibility
|
520
|
+
).void
|
510
521
|
end
|
511
|
-
def compile_method(symbol_name, constant, method)
|
522
|
+
def compile_method(tree, symbol_name, constant, method, visibility = RBI::Visibility::Public)
|
512
523
|
return unless method
|
513
524
|
return unless method.owner == constant
|
514
525
|
return if symbol_ignored?(symbol_name) && !method_in_gem?(method)
|
@@ -555,37 +566,34 @@ module Tapioca
|
|
555
566
|
[type, name]
|
556
567
|
end
|
557
568
|
|
558
|
-
|
569
|
+
rbi_method = RBI::Method.new(method_name, is_singleton: constant.singleton_class?, visibility: visibility)
|
570
|
+
rbi_method.sigs << compile_signature(signature, sanitized_parameters) if signature
|
571
|
+
|
572
|
+
sanitized_parameters.each do |type, name|
|
559
573
|
case type
|
560
574
|
when :req
|
561
|
-
name
|
575
|
+
rbi_method << RBI::Param.new(name)
|
562
576
|
when :opt
|
563
|
-
|
577
|
+
rbi_method << RBI::OptParam.new(name, "T.unsafe(nil)")
|
564
578
|
when :rest
|
565
|
-
|
579
|
+
rbi_method << RBI::RestParam.new(name)
|
566
580
|
when :keyreq
|
567
|
-
|
581
|
+
rbi_method << RBI::KwParam.new(name)
|
568
582
|
when :key
|
569
|
-
|
583
|
+
rbi_method << RBI::KwOptParam.new(name, "T.unsafe(nil)")
|
570
584
|
when :keyrest
|
571
|
-
|
585
|
+
rbi_method << RBI::KwRestParam.new(name)
|
572
586
|
when :block
|
573
|
-
|
587
|
+
rbi_method << RBI::BlockParam.new(name)
|
574
588
|
end
|
575
|
-
end
|
576
|
-
|
577
|
-
parameter_list = "(#{parameter_list})" if parameter_list != ""
|
578
|
-
signature_str = indented(compile_signature(signature, sanitized_parameters)) if signature
|
589
|
+
end
|
579
590
|
|
580
|
-
|
581
|
-
signature_str,
|
582
|
-
indented("def #{method_name}#{parameter_list}; end"),
|
583
|
-
].compact.join("\n")
|
591
|
+
tree << rbi_method
|
584
592
|
end
|
585
593
|
|
586
594
|
TYPE_PARAMETER_MATCHER = /T\.type_parameter\(:?([[:word:]]+)\)/
|
587
595
|
|
588
|
-
sig { params(signature: T.untyped, parameters: T::Array[[Symbol, String]]).returns(
|
596
|
+
sig { params(signature: T.untyped, parameters: T::Array[[Symbol, String]]).returns(RBI::Sig) }
|
589
597
|
def compile_signature(signature, parameters)
|
590
598
|
parameter_types = T.let(signature.arg_types.to_h, T::Hash[Symbol, T::Types::Base])
|
591
599
|
parameter_types.merge!(signature.kwarg_types)
|
@@ -593,41 +601,35 @@ module Tapioca
|
|
593
601
|
parameter_types[signature.keyrest_name] = signature.keyrest_type if signature.has_keyrest
|
594
602
|
parameter_types[signature.block_name] = signature.block_type if signature.block_name
|
595
603
|
|
596
|
-
|
597
|
-
type = parameter_types[name.to_sym]
|
598
|
-
"#{name}: #{type}"
|
599
|
-
end.join(", ")
|
604
|
+
sig = RBI::Sig.new
|
600
605
|
|
601
|
-
|
606
|
+
parameters.each do |_, name|
|
607
|
+
type = sanitize_signature_types(parameter_types[name.to_sym].to_s)
|
608
|
+
add_to_symbol_queue(type)
|
609
|
+
sig << RBI::SigParam.new(name, type)
|
610
|
+
end
|
602
611
|
|
603
|
-
|
604
|
-
|
612
|
+
return_type = type_of(signature.return_type)
|
613
|
+
sig.return_type = sanitize_signature_types(return_type)
|
614
|
+
add_to_symbol_queue(sig.return_type)
|
605
615
|
|
606
|
-
|
616
|
+
parameter_types.values.join(", ").scan(TYPE_PARAMETER_MATCHER).flatten.uniq.each do |k, _|
|
617
|
+
sig.type_params << k
|
618
|
+
end
|
619
|
+
|
620
|
+
case signature.mode
|
607
621
|
when "abstract"
|
608
|
-
|
622
|
+
sig.is_abstract = true
|
609
623
|
when "override"
|
610
|
-
|
624
|
+
sig.is_override = true
|
611
625
|
when "overridable_override"
|
612
|
-
|
626
|
+
sig.is_overridable = true
|
627
|
+
sig.is_override = true
|
613
628
|
when "overridable"
|
614
|
-
|
615
|
-
else
|
616
|
-
""
|
629
|
+
sig.is_overridable = true
|
617
630
|
end
|
618
631
|
|
619
|
-
|
620
|
-
signature_body << mode
|
621
|
-
signature_body << type_parameters
|
622
|
-
signature_body << ".params(#{params})" unless params.empty?
|
623
|
-
signature_body << ".returns(#{returns})"
|
624
|
-
signature_body = signature_body
|
625
|
-
.gsub(".returns(<VOID>)", ".void")
|
626
|
-
.gsub("<NOT-TYPED>", "T.untyped")
|
627
|
-
.gsub(".params()", "")
|
628
|
-
.gsub(TYPE_PARAMETER_MATCHER, "T.type_parameter(:\\1)")[1..-1]
|
629
|
-
|
630
|
-
"sig { #{signature_body} }"
|
632
|
+
sig
|
631
633
|
end
|
632
634
|
|
633
635
|
sig { params(symbol_name: String).returns(T::Boolean) }
|
@@ -643,27 +645,6 @@ module Tapioca
|
|
643
645
|
!!name.match(/^[[:word:]]+[?!=]?$/)
|
644
646
|
end
|
645
647
|
|
646
|
-
sig do
|
647
|
-
type_parameters(:U)
|
648
|
-
.params(
|
649
|
-
step: Integer,
|
650
|
-
_blk: T.proc
|
651
|
-
.returns(T.type_parameter(:U))
|
652
|
-
)
|
653
|
-
.returns(T.type_parameter(:U))
|
654
|
-
end
|
655
|
-
def with_indentation(step = 1, &_blk)
|
656
|
-
@indent += 2 * step
|
657
|
-
yield
|
658
|
-
ensure
|
659
|
-
@indent -= 2 * step
|
660
|
-
end
|
661
|
-
|
662
|
-
sig { params(str: String).returns(String) }
|
663
|
-
def indented(str)
|
664
|
-
" " * @indent + str
|
665
|
-
end
|
666
|
-
|
667
648
|
sig { params(method: UnboundMethod).returns(T::Boolean) }
|
668
649
|
def method_in_gem?(method)
|
669
650
|
source_location = method.source_location&.first
|
@@ -721,33 +702,6 @@ module Tapioca
|
|
721
702
|
nil
|
722
703
|
end
|
723
704
|
|
724
|
-
def parent_declares_constant?(name)
|
725
|
-
name_parts = name.split("::")
|
726
|
-
|
727
|
-
parent_name = name_parts[0...-1].join("::")
|
728
|
-
parent_name = parent_name[2..-1] if parent_name.start_with?("::")
|
729
|
-
parent_name = 'Object' if parent_name == ""
|
730
|
-
parent = T.cast(resolve_constant(parent_name), T.nilable(Module))
|
731
|
-
|
732
|
-
return false unless parent
|
733
|
-
|
734
|
-
constants_of(parent).include?(name_parts.last.to_sym)
|
735
|
-
end
|
736
|
-
|
737
|
-
sig { params(constant: Module).returns(T::Boolean) }
|
738
|
-
def public_module?(constant)
|
739
|
-
constant_name = name_of(constant)
|
740
|
-
return false unless constant_name
|
741
|
-
return false if constant_name.start_with?('T::Private')
|
742
|
-
|
743
|
-
begin
|
744
|
-
# can't use !! here because the constant might override ! and mess with us
|
745
|
-
Module === eval(constant_name) # rubocop:disable Security/Eval
|
746
|
-
rescue NameError
|
747
|
-
false
|
748
|
-
end
|
749
|
-
end
|
750
|
-
|
751
705
|
sig { params(constant: BasicObject).returns(Class).checked(:never) }
|
752
706
|
def class_of(constant)
|
753
707
|
Kernel.instance_method(:class).bind(constant).call
|
@@ -829,7 +783,7 @@ module Tapioca
|
|
829
783
|
begin
|
830
784
|
target = Kernel.instance_method(:send).bind(constant).call(:target)
|
831
785
|
rescue NoMethodError
|
832
|
-
return
|
786
|
+
return
|
833
787
|
end
|
834
788
|
|
835
789
|
raw_name_of(target)
|
@@ -859,12 +813,21 @@ module Tapioca
|
|
859
813
|
nil
|
860
814
|
end
|
861
815
|
|
862
|
-
sig { params(
|
816
|
+
sig { params(sig_string: String).returns(String) }
|
817
|
+
def sanitize_signature_types(sig_string)
|
818
|
+
sig_string
|
819
|
+
.gsub(".returns(<VOID>)", ".void")
|
820
|
+
.gsub("<VOID>", "void")
|
821
|
+
.gsub("<NOT-TYPED>", "T.untyped")
|
822
|
+
.gsub(".params()", "")
|
823
|
+
end
|
824
|
+
|
825
|
+
sig { params(constant: T::Types::Base).returns(String) }
|
863
826
|
def type_of(constant)
|
864
827
|
constant.to_s.gsub(/\bAttachedClass\b/, "T.attached_class")
|
865
828
|
end
|
866
829
|
|
867
|
-
sig { params(object:
|
830
|
+
sig { params(object: BasicObject).returns(Integer).checked(:never) }
|
868
831
|
def object_id_of(object)
|
869
832
|
Object.instance_method(:object_id).bind(object).call
|
870
833
|
end
|