tapioca 0.4.21 → 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/lib/tapioca/compilers/dsl/active_job.rb +71 -0
- data/lib/tapioca/compilers/requires_compiler.rb +1 -1
- data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +241 -361
- data/lib/tapioca/core_ext/string.rb +18 -0
- data/lib/tapioca/gemfile.rb +1 -1
- data/lib/tapioca/generator.rb +5 -3
- data/lib/tapioca/internal.rb +7 -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/version.rb +1 -1
- metadata +12 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8e3ea6e1fb437f52cfb699c43b4c3d46115592ac09a69aec5a8d0701906f42cd
|
|
4
|
+
data.tar.gz: 9fba45117a3f1f72ab8d3278838fb7d4a860eaa7cadc03535d99be618e8994c9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6519978a03ff03499f223d810a9f0d2bfd74e406017efb300a72fff0d95e1e08b64d2165ae1b54bad48f8767c5f831fe5f4398185282a5643224499355d7badc
|
|
7
|
+
data.tar.gz: 28ace672d799beb84aa802fe0773e574d3a827c53e15564d643dbe04e6330d6abb11d640a06b064641781258600ce73f3b5695915caaf9ce0813679dede867b2
|
data/Gemfile
CHANGED
|
@@ -4,18 +4,18 @@ source("https://rubygems.org")
|
|
|
4
4
|
|
|
5
5
|
gemspec
|
|
6
6
|
|
|
7
|
-
gem 'rubocop-shopify', require: false
|
|
8
|
-
|
|
9
|
-
group(:deployment, :development) do
|
|
10
|
-
gem("rake")
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
gem("yard", "~> 0.9.25")
|
|
14
|
-
gem("pry-byebug")
|
|
15
7
|
gem("minitest")
|
|
16
8
|
gem("minitest-hooks")
|
|
17
9
|
gem("minitest-reporters")
|
|
10
|
+
gem("pry-byebug")
|
|
11
|
+
gem("rubocop-shopify", require: false)
|
|
12
|
+
gem("rubocop-sorbet", ">= 0.4.1")
|
|
18
13
|
gem("sorbet")
|
|
14
|
+
gem("yard", "~> 0.9.25")
|
|
15
|
+
|
|
16
|
+
group(:deployment, :development) do
|
|
17
|
+
gem("rake")
|
|
18
|
+
end
|
|
19
19
|
|
|
20
20
|
group(:development, :test) do
|
|
21
21
|
gem("smart_properties", ">= 1.15.0", require: false)
|
|
@@ -26,14 +26,13 @@ group(:development, :test) do
|
|
|
26
26
|
gem("activerecord-typedstore", "~> 1.3", require: false)
|
|
27
27
|
gem("sqlite3")
|
|
28
28
|
gem("identity_cache", "~> 1.0", require: false)
|
|
29
|
-
gem(
|
|
30
|
-
ref:
|
|
29
|
+
gem("cityhash", git: "https://github.com/csfrancis/cityhash.git",
|
|
30
|
+
ref: "3cfc7d01f333c01811d5e834f1495eaa29f87c36", require: false)
|
|
31
31
|
gem("activemodel-serializers-xml", "~> 1.0", require: false)
|
|
32
32
|
gem("activeresource", "~> 5.1", require: false)
|
|
33
|
-
gem("google-protobuf", "~>3.12.0", require: false)
|
|
33
|
+
gem("google-protobuf", "~> 3.12.0", require: false)
|
|
34
34
|
# Fix version to 0.14.1 since it is the last version to support Ruby 2.4
|
|
35
35
|
gem("shopify-money", "= 0.14.1", require: false)
|
|
36
|
-
gem("sidekiq", "~>5.0", require: false) # Version 6 dropped support for Ruby 2.4
|
|
36
|
+
gem("sidekiq", "~> 5.0", require: false) # Version 6 dropped support for Ruby 2.4
|
|
37
|
+
gem("nokogiri", "1.10.10", require: false) # Lock to last supported for Ruby 2.4
|
|
37
38
|
end
|
|
38
|
-
|
|
39
|
-
gem "rubocop-sorbet", ">= 0.4.1"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "parlour"
|
|
5
|
+
|
|
6
|
+
begin
|
|
7
|
+
require "active_job"
|
|
8
|
+
rescue LoadError
|
|
9
|
+
return
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module Tapioca
|
|
13
|
+
module Compilers
|
|
14
|
+
module Dsl
|
|
15
|
+
# `Tapioca::Compilers::Dsl::ActiveJob` generates RBI files for subclasses of
|
|
16
|
+
# [`ActiveJob::Base`](https://api.rubyonrails.org/classes/ActiveJob/Base.html).
|
|
17
|
+
#
|
|
18
|
+
# For example, with the following `ActiveJob` subclass:
|
|
19
|
+
#
|
|
20
|
+
# ~~~rb
|
|
21
|
+
# class NotifyUserJob < ActiveJob::Base
|
|
22
|
+
# def perform(user)
|
|
23
|
+
# # ...
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
# ~~~
|
|
27
|
+
#
|
|
28
|
+
# this generator will produce the RBI file `notify_user_job.rbi` with the following content:
|
|
29
|
+
#
|
|
30
|
+
# ~~~rbi
|
|
31
|
+
# # notify_user_job.rbi
|
|
32
|
+
# # typed: true
|
|
33
|
+
# class NotifyUserJob
|
|
34
|
+
# sig { params(user: T.untyped).returns(NotifyUserJob) }
|
|
35
|
+
# def self.perform_later(user); end
|
|
36
|
+
#
|
|
37
|
+
# sig { params(user: T.untyped).returns(NotifyUserJob) }
|
|
38
|
+
# def self.perform_now(user); end
|
|
39
|
+
# end
|
|
40
|
+
# ~~~
|
|
41
|
+
class ActiveJob < Base
|
|
42
|
+
extend T::Sig
|
|
43
|
+
|
|
44
|
+
sig { override.params(root: Parlour::RbiGenerator::Namespace, constant: T.class_of(::ActiveJob::Base)).void }
|
|
45
|
+
def decorate(root, constant)
|
|
46
|
+
root.path(constant) do |job|
|
|
47
|
+
next unless constant.instance_methods(false).include?(:perform)
|
|
48
|
+
|
|
49
|
+
method = constant.instance_method(:perform)
|
|
50
|
+
parameters = compile_method_parameters_to_parlour(method)
|
|
51
|
+
|
|
52
|
+
%w[perform_later perform_now].each do |name|
|
|
53
|
+
create_method(
|
|
54
|
+
job,
|
|
55
|
+
name,
|
|
56
|
+
parameters: parameters,
|
|
57
|
+
return_type: constant.name,
|
|
58
|
+
class_method: true
|
|
59
|
+
)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
sig { override.returns(T::Enumerable[Module]) }
|
|
65
|
+
def gather_constants
|
|
66
|
+
::ActiveJob::Base.descendants
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -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,13 +75,13 @@ 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
87
|
sig do
|
|
@@ -87,12 +97,8 @@ module Tapioca
|
|
|
87
97
|
nil
|
|
88
98
|
end
|
|
89
99
|
|
|
90
|
-
sig
|
|
91
|
-
|
|
92
|
-
.returns(T.nilable(String))
|
|
93
|
-
.checked(:never)
|
|
94
|
-
end
|
|
95
|
-
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)
|
|
96
102
|
return unless constant
|
|
97
103
|
return unless name
|
|
98
104
|
return if name.strip.empty?
|
|
@@ -100,33 +106,28 @@ module Tapioca
|
|
|
100
106
|
return if name.downcase == name
|
|
101
107
|
return if alias_namespaced?(name)
|
|
102
108
|
return if seen?(name)
|
|
103
|
-
return unless parent_declares_constant?(name)
|
|
104
109
|
return if T::Enum === constant # T::Enum instances are defined via `compile_enums`
|
|
105
110
|
|
|
106
111
|
mark_seen(name)
|
|
107
|
-
compile_constant(name, constant)
|
|
112
|
+
compile_constant(tree, name, constant)
|
|
108
113
|
end
|
|
109
114
|
|
|
110
|
-
sig
|
|
111
|
-
|
|
112
|
-
.returns(T.nilable(String))
|
|
113
|
-
.checked(:never)
|
|
114
|
-
end
|
|
115
|
-
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)
|
|
116
117
|
case constant
|
|
117
118
|
when Module
|
|
118
119
|
if name_of(constant) != name
|
|
119
|
-
compile_alias(name, constant)
|
|
120
|
+
compile_alias(tree, name, constant)
|
|
120
121
|
else
|
|
121
|
-
compile_module(name, constant)
|
|
122
|
+
compile_module(tree, name, constant)
|
|
122
123
|
end
|
|
123
124
|
else
|
|
124
|
-
compile_object(name, constant)
|
|
125
|
+
compile_object(tree, name, constant)
|
|
125
126
|
end
|
|
126
127
|
end
|
|
127
128
|
|
|
128
|
-
sig { params(name: String, constant: Module).
|
|
129
|
-
def compile_alias(name, constant)
|
|
129
|
+
sig { params(tree: RBI::Tree, name: String, constant: Module).void }
|
|
130
|
+
def compile_alias(tree, name, constant)
|
|
130
131
|
return if symbol_ignored?(name)
|
|
131
132
|
|
|
132
133
|
target = name_of(constant)
|
|
@@ -137,119 +138,99 @@ module Tapioca
|
|
|
137
138
|
|
|
138
139
|
return if IGNORED_SYMBOLS.include?(name)
|
|
139
140
|
|
|
140
|
-
|
|
141
|
+
tree << RBI::Const.new(name, target)
|
|
141
142
|
end
|
|
142
143
|
|
|
143
|
-
sig
|
|
144
|
-
|
|
145
|
-
.returns(T.nilable(String))
|
|
146
|
-
.checked(:never)
|
|
147
|
-
end
|
|
148
|
-
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)
|
|
149
146
|
return if symbol_ignored?(name)
|
|
150
147
|
klass = class_of(value)
|
|
151
148
|
klass_name = name_of(klass)
|
|
152
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
|
+
|
|
153
155
|
return if klass_name&.start_with?("T::Types::", "T::Private::")
|
|
154
156
|
|
|
155
|
-
type_name =
|
|
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"
|
|
160
|
+
|
|
161
|
+
tree << RBI::Const.new(name, "T.let(T.unsafe(nil), #{type_name})")
|
|
157
162
|
end
|
|
158
163
|
|
|
159
|
-
sig { params(name: String, constant: Module).
|
|
160
|
-
def compile_module(name, constant)
|
|
161
|
-
return unless public_module?(constant)
|
|
164
|
+
sig { params(tree: RBI::Tree, name: String, constant: Module).void }
|
|
165
|
+
def compile_module(tree, name, constant)
|
|
162
166
|
return unless defined_in_gem?(constant, strict: false)
|
|
163
167
|
|
|
164
|
-
|
|
168
|
+
scope =
|
|
165
169
|
if constant.is_a?(Class)
|
|
166
|
-
|
|
170
|
+
superclass = compile_superclass(constant)
|
|
171
|
+
RBI::Class.new(name, superclass_name: superclass)
|
|
167
172
|
else
|
|
168
|
-
|
|
173
|
+
RBI::Module.new(name)
|
|
169
174
|
end
|
|
170
175
|
|
|
171
|
-
|
|
176
|
+
compile_body(scope, name, constant)
|
|
172
177
|
|
|
173
|
-
return if symbol_ignored?(name) &&
|
|
178
|
+
return if symbol_ignored?(name) && scope.empty?
|
|
174
179
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
body,
|
|
178
|
-
indented("end"),
|
|
179
|
-
compile_subconstants(name, constant),
|
|
180
|
-
].select { |b| !b.nil? && b.strip != "" }.join("\n")
|
|
180
|
+
tree << scope
|
|
181
|
+
compile_subconstants(tree, name, constant)
|
|
181
182
|
end
|
|
182
183
|
|
|
183
|
-
sig { params(name: String, constant: Module).
|
|
184
|
-
def compile_body(name, constant)
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
compile_type_variables(constant),
|
|
193
|
-
compile_mixins(constant),
|
|
194
|
-
compile_mixes_in_class_methods(constant),
|
|
195
|
-
compile_props(constant),
|
|
196
|
-
compile_enums(constant),
|
|
197
|
-
methods,
|
|
198
|
-
].select { |b| b && !b.empty? }.join("\n\n")
|
|
199
|
-
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)
|
|
200
193
|
end
|
|
201
194
|
|
|
202
|
-
sig { params(constant: Module).
|
|
203
|
-
def compile_module_helpers(constant)
|
|
195
|
+
sig { params(tree: RBI::Tree, constant: Module).void }
|
|
196
|
+
def compile_module_helpers(tree, constant)
|
|
204
197
|
abstract_type = T::Private::Abstract::Data.get(constant, :abstract_type)
|
|
205
198
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
helpers << indented("sealed!") if T::Private::Sealed.sealed_module?(constant)
|
|
210
|
-
|
|
211
|
-
return if helpers.empty?
|
|
212
|
-
|
|
213
|
-
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)
|
|
214
202
|
end
|
|
215
203
|
|
|
216
|
-
sig { params(constant: Module).
|
|
217
|
-
def compile_props(constant)
|
|
204
|
+
sig { params(tree: RBI::Tree, constant: Module).void }
|
|
205
|
+
def compile_props(tree, constant)
|
|
218
206
|
return unless T::Props::ClassMethods === constant
|
|
219
207
|
|
|
220
208
|
constant.props.map do |name, prop|
|
|
221
|
-
method = "prop"
|
|
222
|
-
method = "const" if prop.fetch(:immutable, false)
|
|
223
209
|
type = prop.fetch(:type_object, "T.untyped").to_s.gsub(".returns(<VOID>)", ".void")
|
|
224
210
|
|
|
225
|
-
|
|
226
|
-
|
|
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)
|
|
227
214
|
else
|
|
228
|
-
|
|
215
|
+
RBI::TStructProp.new(name.to_s, type, default: default)
|
|
229
216
|
end
|
|
230
|
-
end
|
|
217
|
+
end
|
|
231
218
|
end
|
|
232
219
|
|
|
233
|
-
sig { params(constant: Module).
|
|
234
|
-
def compile_enums(constant)
|
|
220
|
+
sig { params(tree: RBI::Tree, constant: Module).void }
|
|
221
|
+
def compile_enums(tree, constant)
|
|
235
222
|
return unless T::Enum > constant
|
|
236
223
|
|
|
237
224
|
enums = T.unsafe(constant).values.map do |enum_type|
|
|
238
225
|
enum_type.instance_variable_get(:@const_name).to_s
|
|
239
226
|
end
|
|
240
227
|
|
|
241
|
-
|
|
242
|
-
indented('enums do'),
|
|
243
|
-
*enums.map { |e| indented(" #{e} = new") }.join("\n"),
|
|
244
|
-
indented('end'),
|
|
245
|
-
]
|
|
246
|
-
|
|
247
|
-
content.join("\n")
|
|
228
|
+
tree << RBI::TEnumBlock.new(enums)
|
|
248
229
|
end
|
|
249
230
|
|
|
250
|
-
sig { params(name: String, constant: Module).
|
|
251
|
-
def compile_subconstants(name, constant)
|
|
252
|
-
|
|
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|
|
|
253
234
|
symbol = (name == "Object" ? "" : name) + "::#{constant_name}"
|
|
254
235
|
subconstant = resolve_constant(symbol)
|
|
255
236
|
|
|
@@ -258,75 +239,58 @@ module Tapioca
|
|
|
258
239
|
next if (Object == constant || BasicObject == constant) && Module === subconstant
|
|
259
240
|
next unless subconstant
|
|
260
241
|
|
|
261
|
-
compile(symbol, subconstant)
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
return if output.empty?
|
|
265
|
-
|
|
266
|
-
"\n" + output.join("\n\n")
|
|
242
|
+
compile(tree, symbol, subconstant)
|
|
243
|
+
end
|
|
267
244
|
end
|
|
268
245
|
|
|
269
|
-
sig { params(constant: Module).
|
|
270
|
-
def compile_type_variables(constant)
|
|
271
|
-
|
|
272
|
-
singleton_class_type_variables = compile_type_variable_declarations(singleton_class_of(constant))
|
|
273
|
-
|
|
274
|
-
return if !type_variables && !singleton_class_type_variables
|
|
246
|
+
sig { params(tree: RBI::Tree, constant: Module).void }
|
|
247
|
+
def compile_type_variables(tree, constant)
|
|
248
|
+
compile_type_variable_declarations(tree, constant)
|
|
275
249
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
[
|
|
280
|
-
type_variables,
|
|
281
|
-
singleton_class_type_variables,
|
|
282
|
-
].compact.join("\n").rstrip
|
|
250
|
+
sclass = RBI::SingletonClass.new
|
|
251
|
+
compile_type_variable_declarations(sclass, singleton_class_of(constant))
|
|
252
|
+
tree << sclass if sclass.nodes.length > 1
|
|
283
253
|
end
|
|
284
254
|
|
|
285
|
-
sig { params(constant: Module).
|
|
286
|
-
def compile_type_variable_declarations(constant)
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
return unless type_variables
|
|
291
|
-
|
|
292
|
-
# Create a map of subconstants (via their object ids) to their names.
|
|
293
|
-
# We need this later when we want to lookup the name of the registered type
|
|
294
|
-
# variable via the value of the type variable constant.
|
|
295
|
-
subconstant_to_name_lookup = constants_of(constant).map do |constant_name|
|
|
296
|
-
[
|
|
297
|
-
object_id_of(resolve_constant(constant_name.to_s, namespace: constant)),
|
|
298
|
-
constant_name,
|
|
299
|
-
]
|
|
300
|
-
end.to_h
|
|
301
|
-
|
|
302
|
-
# Map each type variable to its string representation.
|
|
303
|
-
#
|
|
304
|
-
# Each entry of `type_variables` maps an object_id to a String,
|
|
305
|
-
# and the order they are inserted into the hash is the order they should be
|
|
306
|
-
# defined in the source code.
|
|
307
|
-
#
|
|
308
|
-
# By looping over these entries and then getting the actual constant name
|
|
309
|
-
# from the `subconstant_to_name_lookup` we defined above, gives us all the
|
|
310
|
-
# information we need to serialize type variable definitions.
|
|
311
|
-
type_variable_declarations = type_variables.map do |type_variable_id, serialized_type_variable|
|
|
312
|
-
constant_name = subconstant_to_name_lookup[type_variable_id]
|
|
313
|
-
# Here, we know that constant_value will be an instance of
|
|
314
|
-
# T::Types::CustomTypeVariable, which knows how to serialize
|
|
315
|
-
# itself to a type_member/type_template
|
|
316
|
-
indented("#{constant_name} = #{serialized_type_variable}")
|
|
317
|
-
end.compact
|
|
318
|
-
|
|
319
|
-
return if type_variable_declarations.empty?
|
|
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
|
|
320
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|
|
|
321
265
|
[
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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)
|
|
326
286
|
end
|
|
287
|
+
|
|
288
|
+
return if type_variable_declarations.empty?
|
|
289
|
+
|
|
290
|
+
tree << RBI::Extend.new("T::Generic")
|
|
327
291
|
end
|
|
328
292
|
|
|
329
|
-
sig { params(constant: Class).returns(String) }
|
|
293
|
+
sig { params(constant: Class).returns(T.nilable(String)) }
|
|
330
294
|
def compile_superclass(constant)
|
|
331
295
|
superclass = T.let(nil, T.nilable(Class)) # rubocop:disable Lint/UselessAssignment
|
|
332
296
|
|
|
@@ -334,15 +298,6 @@ module Tapioca
|
|
|
334
298
|
constant_name = name_of(constant)
|
|
335
299
|
constant = superclass
|
|
336
300
|
|
|
337
|
-
# Some classes have superclasses that are private constants
|
|
338
|
-
# so if we generate code with that superclass, the output
|
|
339
|
-
# will not be compilable (since private constants are not
|
|
340
|
-
# publicly visible).
|
|
341
|
-
#
|
|
342
|
-
# So we skip superclasses that are not public and walk up the
|
|
343
|
-
# chain.
|
|
344
|
-
next unless public_module?(superclass)
|
|
345
|
-
|
|
346
301
|
# Some types have "themselves" as their superclass
|
|
347
302
|
# which can happen via:
|
|
348
303
|
#
|
|
@@ -362,7 +317,9 @@ module Tapioca
|
|
|
362
317
|
# B = A
|
|
363
318
|
# A.superclass.name #=> "B"
|
|
364
319
|
# B #=> A
|
|
365
|
-
superclass_name =
|
|
320
|
+
superclass_name = name_of(superclass)
|
|
321
|
+
next unless superclass_name
|
|
322
|
+
|
|
366
323
|
resolved_superclass = resolve_constant(superclass_name)
|
|
367
324
|
next unless Module === resolved_superclass
|
|
368
325
|
next if name_of(resolved_superclass) == constant_name
|
|
@@ -371,17 +328,19 @@ module Tapioca
|
|
|
371
328
|
break
|
|
372
329
|
end
|
|
373
330
|
|
|
374
|
-
return
|
|
375
|
-
return
|
|
331
|
+
return if superclass == ::Object || superclass == ::Delegator
|
|
332
|
+
return if superclass.nil?
|
|
376
333
|
|
|
377
334
|
name = name_of(superclass)
|
|
378
|
-
return
|
|
335
|
+
return if name.nil? || name.empty?
|
|
336
|
+
|
|
337
|
+
add_to_symbol_queue(name)
|
|
379
338
|
|
|
380
|
-
"
|
|
339
|
+
"::#{name}"
|
|
381
340
|
end
|
|
382
341
|
|
|
383
|
-
sig { params(constant: Module).
|
|
384
|
-
def compile_mixins(constant)
|
|
342
|
+
sig { params(tree: RBI::Tree, constant: Module).void }
|
|
343
|
+
def compile_mixins(tree, constant)
|
|
385
344
|
singleton_class = singleton_class_of(constant)
|
|
386
345
|
|
|
387
346
|
interesting_ancestors = interesting_ancestors_of(constant)
|
|
@@ -390,42 +349,46 @@ module Tapioca
|
|
|
390
349
|
prepend = interesting_ancestors.take_while { |c| !are_equal?(constant, c) }
|
|
391
350
|
include = interesting_ancestors.drop(prepend.size + 1)
|
|
392
351
|
extend = interesting_singleton_class_ancestors.reject do |mod|
|
|
393
|
-
|
|
352
|
+
Module != class_of(mod) || are_equal?(mod, singleton_class)
|
|
394
353
|
end
|
|
395
354
|
|
|
396
|
-
|
|
355
|
+
prepend
|
|
397
356
|
.reverse
|
|
398
357
|
.select { |mod| (name = name_of(mod)) && !name.start_with?("T::") }
|
|
399
|
-
.select(&method(:public_module?))
|
|
400
358
|
.map do |mod|
|
|
359
|
+
add_to_symbol_queue(name_of(mod))
|
|
360
|
+
|
|
401
361
|
# TODO: Sorbet currently does not handle prepend
|
|
402
362
|
# properly for method resolution, so we generate an
|
|
403
363
|
# include statement instead
|
|
404
|
-
|
|
364
|
+
qname = qualified_name_of(mod)
|
|
365
|
+
tree << RBI::Include.new(T.must(qname))
|
|
405
366
|
end
|
|
406
367
|
|
|
407
|
-
|
|
368
|
+
include
|
|
408
369
|
.reverse
|
|
409
370
|
.select { |mod| (name = name_of(mod)) && !name.start_with?("T::") }
|
|
410
|
-
.select(&method(:public_module?))
|
|
411
371
|
.map do |mod|
|
|
412
|
-
|
|
372
|
+
add_to_symbol_queue(name_of(mod))
|
|
373
|
+
|
|
374
|
+
qname = qualified_name_of(mod)
|
|
375
|
+
tree << RBI::Include.new(T.must(qname))
|
|
413
376
|
end
|
|
414
377
|
|
|
415
|
-
|
|
378
|
+
extend
|
|
416
379
|
.reverse
|
|
417
380
|
.select { |mod| (name = name_of(mod)) && !name.start_with?("T::") }
|
|
418
|
-
.select(&method(:public_module?))
|
|
419
381
|
.map do |mod|
|
|
420
|
-
|
|
421
|
-
end
|
|
382
|
+
add_to_symbol_queue(name_of(mod))
|
|
422
383
|
|
|
423
|
-
|
|
384
|
+
qname = qualified_name_of(mod)
|
|
385
|
+
tree << RBI::Extend.new(T.must(qname))
|
|
386
|
+
end
|
|
424
387
|
end
|
|
425
388
|
|
|
426
|
-
sig { params(constant: Module).
|
|
427
|
-
def compile_mixes_in_class_methods(constant)
|
|
428
|
-
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)
|
|
429
392
|
|
|
430
393
|
mixins_from_modules = {}
|
|
431
394
|
|
|
@@ -457,11 +420,13 @@ module Tapioca
|
|
|
457
420
|
dynamic_extends_from_dynamic_includes = mixins_from_modules.values.flatten
|
|
458
421
|
dynamic_extends = all_dynamic_extends - dynamic_extends_from_dynamic_includes
|
|
459
422
|
|
|
460
|
-
|
|
423
|
+
all_dynamic_includes
|
|
461
424
|
.select { |mod| (name = name_of(mod)) && !name.start_with?("T::") }
|
|
462
|
-
.select(&method(:public_module?))
|
|
463
425
|
.map do |mod|
|
|
464
|
-
|
|
426
|
+
add_to_symbol_queue(name_of(mod))
|
|
427
|
+
|
|
428
|
+
qname = qualified_name_of(mod)
|
|
429
|
+
tree << RBI::Include.new(T.must(qname))
|
|
465
430
|
end.join("\n")
|
|
466
431
|
|
|
467
432
|
ancestors = singleton_class_of(constant).ancestors
|
|
@@ -473,69 +438,57 @@ module Tapioca
|
|
|
473
438
|
mixed_in_module = if extends_as_concern && Module === class_methods_module
|
|
474
439
|
class_methods_module
|
|
475
440
|
else
|
|
476
|
-
dynamic_extends.find
|
|
477
|
-
mod != constant && public_module?(mod)
|
|
478
|
-
end
|
|
441
|
+
dynamic_extends.find { |mod| mod != constant }
|
|
479
442
|
end
|
|
480
443
|
|
|
481
|
-
return
|
|
444
|
+
return if mixed_in_module.nil?
|
|
482
445
|
|
|
483
446
|
qualified_name = qualified_name_of(mixed_in_module)
|
|
484
|
-
return
|
|
447
|
+
return if qualified_name.nil? || qualified_name == ""
|
|
485
448
|
|
|
486
|
-
|
|
487
|
-
result,
|
|
488
|
-
indented("mixes_in_class_methods(#{qualified_name})"),
|
|
489
|
-
].select { |b| b != "" }.join("\n\n")
|
|
449
|
+
tree << RBI::MixesInClassMethods.new(qualified_name)
|
|
490
450
|
rescue
|
|
491
|
-
|
|
451
|
+
nil # silence errors
|
|
492
452
|
end
|
|
493
453
|
|
|
494
|
-
sig { params(name: String, constant: Module).
|
|
495
|
-
def compile_methods(name, constant)
|
|
496
|
-
|
|
454
|
+
sig { params(tree: RBI::Tree, name: String, constant: Module).void }
|
|
455
|
+
def compile_methods(tree, name, constant)
|
|
456
|
+
compile_method(
|
|
457
|
+
tree,
|
|
497
458
|
name,
|
|
498
459
|
constant,
|
|
499
460
|
initialize_method_for(constant)
|
|
500
461
|
)
|
|
501
462
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
return if symbol_ignored?(name) && !instance_methods && !singleton_methods
|
|
506
|
-
|
|
507
|
-
[
|
|
508
|
-
initialize_method,
|
|
509
|
-
instance_methods,
|
|
510
|
-
singleton_methods,
|
|
511
|
-
].select { |b| b && !b.strip.empty? }.join("\n\n")
|
|
463
|
+
compile_directly_owned_methods(tree, name, constant)
|
|
464
|
+
compile_directly_owned_methods(tree, name, singleton_class_of(constant))
|
|
512
465
|
end
|
|
513
466
|
|
|
514
|
-
sig
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
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
|
|
529
488
|
end
|
|
530
|
-
|
|
531
|
-
compiled
|
|
489
|
+
compile_method(tree, module_name, mod, mod.instance_method(name), vis)
|
|
532
490
|
end
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
return if methods.empty?
|
|
536
|
-
|
|
537
|
-
methods.join("\n")
|
|
538
|
-
end
|
|
491
|
+
end
|
|
539
492
|
end
|
|
540
493
|
|
|
541
494
|
sig { params(mod: Module).returns(T::Hash[Symbol, T::Array[Symbol]]) }
|
|
@@ -559,12 +512,14 @@ module Tapioca
|
|
|
559
512
|
|
|
560
513
|
sig do
|
|
561
514
|
params(
|
|
515
|
+
tree: RBI::Tree,
|
|
562
516
|
symbol_name: String,
|
|
563
517
|
constant: Module,
|
|
564
|
-
method: T.nilable(UnboundMethod)
|
|
565
|
-
|
|
518
|
+
method: T.nilable(UnboundMethod),
|
|
519
|
+
visibility: RBI::Visibility
|
|
520
|
+
).void
|
|
566
521
|
end
|
|
567
|
-
def compile_method(symbol_name, constant, method)
|
|
522
|
+
def compile_method(tree, symbol_name, constant, method, visibility = RBI::Visibility::Public)
|
|
568
523
|
return unless method
|
|
569
524
|
return unless method.owner == constant
|
|
570
525
|
return if symbol_ignored?(symbol_name) && !method_in_gem?(method)
|
|
@@ -611,37 +566,34 @@ module Tapioca
|
|
|
611
566
|
[type, name]
|
|
612
567
|
end
|
|
613
568
|
|
|
614
|
-
|
|
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|
|
|
615
573
|
case type
|
|
616
574
|
when :req
|
|
617
|
-
name
|
|
575
|
+
rbi_method << RBI::Param.new(name)
|
|
618
576
|
when :opt
|
|
619
|
-
|
|
577
|
+
rbi_method << RBI::OptParam.new(name, "T.unsafe(nil)")
|
|
620
578
|
when :rest
|
|
621
|
-
|
|
579
|
+
rbi_method << RBI::RestParam.new(name)
|
|
622
580
|
when :keyreq
|
|
623
|
-
|
|
581
|
+
rbi_method << RBI::KwParam.new(name)
|
|
624
582
|
when :key
|
|
625
|
-
|
|
583
|
+
rbi_method << RBI::KwOptParam.new(name, "T.unsafe(nil)")
|
|
626
584
|
when :keyrest
|
|
627
|
-
|
|
585
|
+
rbi_method << RBI::KwRestParam.new(name)
|
|
628
586
|
when :block
|
|
629
|
-
|
|
587
|
+
rbi_method << RBI::BlockParam.new(name)
|
|
630
588
|
end
|
|
631
|
-
end
|
|
632
|
-
|
|
633
|
-
parameter_list = "(#{parameter_list})" if parameter_list != ""
|
|
634
|
-
signature_str = indented(compile_signature(signature, sanitized_parameters)) if signature
|
|
589
|
+
end
|
|
635
590
|
|
|
636
|
-
|
|
637
|
-
signature_str,
|
|
638
|
-
indented("def #{method_name}#{parameter_list}; end"),
|
|
639
|
-
].compact.join("\n")
|
|
591
|
+
tree << rbi_method
|
|
640
592
|
end
|
|
641
593
|
|
|
642
594
|
TYPE_PARAMETER_MATCHER = /T\.type_parameter\(:?([[:word:]]+)\)/
|
|
643
595
|
|
|
644
|
-
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) }
|
|
645
597
|
def compile_signature(signature, parameters)
|
|
646
598
|
parameter_types = T.let(signature.arg_types.to_h, T::Hash[Symbol, T::Types::Base])
|
|
647
599
|
parameter_types.merge!(signature.kwarg_types)
|
|
@@ -649,41 +601,35 @@ module Tapioca
|
|
|
649
601
|
parameter_types[signature.keyrest_name] = signature.keyrest_type if signature.has_keyrest
|
|
650
602
|
parameter_types[signature.block_name] = signature.block_type if signature.block_name
|
|
651
603
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
604
|
+
sig = RBI::Sig.new
|
|
605
|
+
|
|
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
|
|
656
611
|
|
|
657
|
-
|
|
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)
|
|
658
615
|
|
|
659
|
-
|
|
660
|
-
|
|
616
|
+
parameter_types.values.join(", ").scan(TYPE_PARAMETER_MATCHER).flatten.uniq.each do |k, _|
|
|
617
|
+
sig.type_params << k
|
|
618
|
+
end
|
|
661
619
|
|
|
662
|
-
|
|
620
|
+
case signature.mode
|
|
663
621
|
when "abstract"
|
|
664
|
-
|
|
622
|
+
sig.is_abstract = true
|
|
665
623
|
when "override"
|
|
666
|
-
|
|
624
|
+
sig.is_override = true
|
|
667
625
|
when "overridable_override"
|
|
668
|
-
|
|
626
|
+
sig.is_overridable = true
|
|
627
|
+
sig.is_override = true
|
|
669
628
|
when "overridable"
|
|
670
|
-
|
|
671
|
-
else
|
|
672
|
-
""
|
|
629
|
+
sig.is_overridable = true
|
|
673
630
|
end
|
|
674
631
|
|
|
675
|
-
|
|
676
|
-
signature_body << mode
|
|
677
|
-
signature_body << type_parameters
|
|
678
|
-
signature_body << ".params(#{params})" unless params.empty?
|
|
679
|
-
signature_body << ".returns(#{returns})"
|
|
680
|
-
signature_body = signature_body
|
|
681
|
-
.gsub(".returns(<VOID>)", ".void")
|
|
682
|
-
.gsub("<NOT-TYPED>", "T.untyped")
|
|
683
|
-
.gsub(".params()", "")
|
|
684
|
-
.gsub(TYPE_PARAMETER_MATCHER, "T.type_parameter(:\\1)")[1..-1]
|
|
685
|
-
|
|
686
|
-
"sig { #{signature_body} }"
|
|
632
|
+
sig
|
|
687
633
|
end
|
|
688
634
|
|
|
689
635
|
sig { params(symbol_name: String).returns(T::Boolean) }
|
|
@@ -699,54 +645,6 @@ module Tapioca
|
|
|
699
645
|
!!name.match(/^[[:word:]]+[?!=]?$/)
|
|
700
646
|
end
|
|
701
647
|
|
|
702
|
-
sig do
|
|
703
|
-
type_parameters(:U)
|
|
704
|
-
.params(
|
|
705
|
-
step: Integer,
|
|
706
|
-
_blk: T.proc
|
|
707
|
-
.returns(T.type_parameter(:U))
|
|
708
|
-
)
|
|
709
|
-
.returns(T.type_parameter(:U))
|
|
710
|
-
end
|
|
711
|
-
def with_indentation(step = 1, &_blk)
|
|
712
|
-
@indent += 2 * step
|
|
713
|
-
yield
|
|
714
|
-
ensure
|
|
715
|
-
@indent -= 2 * step
|
|
716
|
-
end
|
|
717
|
-
|
|
718
|
-
sig do
|
|
719
|
-
params(
|
|
720
|
-
constant: Module,
|
|
721
|
-
blk: T.proc
|
|
722
|
-
.returns(T.nilable(String))
|
|
723
|
-
)
|
|
724
|
-
.returns(T.nilable(String))
|
|
725
|
-
end
|
|
726
|
-
def with_indentation_for_constant(constant, &blk)
|
|
727
|
-
step = if constant.singleton_class?
|
|
728
|
-
1
|
|
729
|
-
else
|
|
730
|
-
0
|
|
731
|
-
end
|
|
732
|
-
|
|
733
|
-
result = with_indentation(step, &blk)
|
|
734
|
-
|
|
735
|
-
return result unless result
|
|
736
|
-
return result unless constant.singleton_class?
|
|
737
|
-
|
|
738
|
-
[
|
|
739
|
-
indented("class << self"),
|
|
740
|
-
result,
|
|
741
|
-
indented("end"),
|
|
742
|
-
].compact.join("\n")
|
|
743
|
-
end
|
|
744
|
-
|
|
745
|
-
sig { params(str: String).returns(String) }
|
|
746
|
-
def indented(str)
|
|
747
|
-
" " * @indent + str
|
|
748
|
-
end
|
|
749
|
-
|
|
750
648
|
sig { params(method: UnboundMethod).returns(T::Boolean) }
|
|
751
649
|
def method_in_gem?(method)
|
|
752
650
|
source_location = method.source_location&.first
|
|
@@ -804,33 +702,6 @@ module Tapioca
|
|
|
804
702
|
nil
|
|
805
703
|
end
|
|
806
704
|
|
|
807
|
-
def parent_declares_constant?(name)
|
|
808
|
-
name_parts = name.split("::")
|
|
809
|
-
|
|
810
|
-
parent_name = name_parts[0...-1].join("::")
|
|
811
|
-
parent_name = parent_name[2..-1] if parent_name.start_with?("::")
|
|
812
|
-
parent_name = 'Object' if parent_name == ""
|
|
813
|
-
parent = T.cast(resolve_constant(parent_name), T.nilable(Module))
|
|
814
|
-
|
|
815
|
-
return false unless parent
|
|
816
|
-
|
|
817
|
-
constants_of(parent).include?(name_parts.last.to_sym)
|
|
818
|
-
end
|
|
819
|
-
|
|
820
|
-
sig { params(constant: Module).returns(T::Boolean) }
|
|
821
|
-
def public_module?(constant)
|
|
822
|
-
constant_name = name_of(constant)
|
|
823
|
-
return false unless constant_name
|
|
824
|
-
return false if constant_name.start_with?('T::Private')
|
|
825
|
-
|
|
826
|
-
begin
|
|
827
|
-
# can't use !! here because the constant might override ! and mess with us
|
|
828
|
-
Module === eval(constant_name) # rubocop:disable Security/Eval
|
|
829
|
-
rescue NameError
|
|
830
|
-
false
|
|
831
|
-
end
|
|
832
|
-
end
|
|
833
|
-
|
|
834
705
|
sig { params(constant: BasicObject).returns(Class).checked(:never) }
|
|
835
706
|
def class_of(constant)
|
|
836
707
|
Kernel.instance_method(:class).bind(constant).call
|
|
@@ -912,7 +783,7 @@ module Tapioca
|
|
|
912
783
|
begin
|
|
913
784
|
target = Kernel.instance_method(:send).bind(constant).call(:target)
|
|
914
785
|
rescue NoMethodError
|
|
915
|
-
return
|
|
786
|
+
return
|
|
916
787
|
end
|
|
917
788
|
|
|
918
789
|
raw_name_of(target)
|
|
@@ -942,6 +813,15 @@ module Tapioca
|
|
|
942
813
|
nil
|
|
943
814
|
end
|
|
944
815
|
|
|
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
|
+
|
|
945
825
|
sig { params(constant: T::Types::Base).returns(String) }
|
|
946
826
|
def type_of(constant)
|
|
947
827
|
constant.to_s.gsub(/\bAttachedClass\b/, "T.attached_class")
|