tapioca 0.4.21 → 0.4.25
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/exe/tapioca +2 -0
- data/lib/tapioca/compilers/dsl/active_job.rb +79 -0
- data/lib/tapioca/compilers/requires_compiler.rb +1 -1
- data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +261 -362
- data/lib/tapioca/core_ext/string.rb +18 -0
- data/lib/tapioca/gemfile.rb +41 -12
- data/lib/tapioca/generator.rb +5 -3
- data/lib/tapioca/internal.rb +8 -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 +86 -0
- data/lib/tapioca/rbi/visitor.rb +21 -0
- data/lib/tapioca/sorbet_ext/fixed_hash_patch.rb +20 -0
- data/lib/tapioca/version.rb +1 -1
- metadata +13 -3
@@ -0,0 +1,18 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
class String
|
5
|
+
extend T::Sig
|
6
|
+
|
7
|
+
sig { returns(String) }
|
8
|
+
def underscore
|
9
|
+
return self unless /[A-Z-]|::/.match?(self)
|
10
|
+
|
11
|
+
word = to_s.gsub("::", "/")
|
12
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
|
13
|
+
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
14
|
+
word.tr!("-", "_")
|
15
|
+
word.downcase!
|
16
|
+
word
|
17
|
+
end
|
18
|
+
end
|
data/lib/tapioca/gemfile.rb
CHANGED
@@ -53,21 +53,30 @@ module Tapioca
|
|
53
53
|
|
54
54
|
sig { returns([T::Array[Gem], T::Array[String]]) }
|
55
55
|
def load_dependencies
|
56
|
-
|
57
|
-
|
58
|
-
missing_specs = T::Array[String].new
|
59
|
-
|
60
|
-
dependencies = definition
|
61
|
-
.resolve
|
62
|
-
.materialize(deps, missing_specs)
|
56
|
+
materialized_dependencies, missing_specs = materialize_deps
|
57
|
+
dependencies = materialized_dependencies
|
63
58
|
.map { |spec| Gem.new(spec) }
|
64
59
|
.reject { |gem| gem.ignore?(dir) }
|
65
60
|
.uniq(&:rbi_file_name)
|
66
61
|
.sort_by(&:rbi_file_name)
|
67
|
-
|
68
62
|
[dependencies, missing_specs]
|
69
63
|
end
|
70
64
|
|
65
|
+
sig { returns([T::Array[::Gem::Specification], T::Array[String]]) }
|
66
|
+
def materialize_deps
|
67
|
+
deps = definition.locked_gems.dependencies.values
|
68
|
+
missing_specs = T::Array[String].new
|
69
|
+
materialized_dependencies = if definition.resolve.method(:materialize).arity == 1 # Support bundler >= v2.2.25
|
70
|
+
md = definition.resolve.materialize(deps)
|
71
|
+
missing_spec_names = md.missing_specs.map(&:name)
|
72
|
+
missing_specs = T.cast(md.missing_specs.map { |spec| "#{spec.name} (#{spec.version})" }, T::Array[String])
|
73
|
+
md.to_a.reject { |spec| missing_spec_names.include?(spec.name) }
|
74
|
+
else
|
75
|
+
definition.resolve.materialize(deps, missing_specs)
|
76
|
+
end
|
77
|
+
[materialized_dependencies, missing_specs]
|
78
|
+
end
|
79
|
+
|
71
80
|
sig { returns(Bundler::Runtime) }
|
72
81
|
def runtime
|
73
82
|
Bundler::Runtime.new(File.dirname(gemfile.path), definition)
|
@@ -108,8 +117,14 @@ module Tapioca
|
|
108
117
|
|
109
118
|
sig { returns(T::Array[Pathname]) }
|
110
119
|
def files
|
111
|
-
|
112
|
-
|
120
|
+
if default_gem?
|
121
|
+
@spec.files.map do |file|
|
122
|
+
ruby_lib_dir.join(file)
|
123
|
+
end
|
124
|
+
else
|
125
|
+
@spec.full_require_paths.flat_map do |path|
|
126
|
+
Pathname.glob((Pathname.new(path) / "**/*.rb").to_s)
|
127
|
+
end
|
113
128
|
end
|
114
129
|
end
|
115
130
|
|
@@ -125,11 +140,25 @@ module Tapioca
|
|
125
140
|
|
126
141
|
sig { params(path: String).returns(T::Boolean) }
|
127
142
|
def contains_path?(path)
|
128
|
-
|
143
|
+
if default_gem?
|
144
|
+
files.any? { |file| file.to_s == to_realpath(path) }
|
145
|
+
else
|
146
|
+
to_realpath(path).start_with?(full_gem_path) || has_parent_gemspec?(path)
|
147
|
+
end
|
129
148
|
end
|
130
149
|
|
131
150
|
private
|
132
151
|
|
152
|
+
sig { returns(T::Boolean) }
|
153
|
+
def default_gem?
|
154
|
+
@spec.respond_to?(:default_gem?) && @spec.default_gem?
|
155
|
+
end
|
156
|
+
|
157
|
+
sig { returns(Pathname) }
|
158
|
+
def ruby_lib_dir
|
159
|
+
Pathname.new(RbConfig::CONFIG["rubylibdir"])
|
160
|
+
end
|
161
|
+
|
133
162
|
sig { returns(String) }
|
134
163
|
def version_string
|
135
164
|
version = @spec.version.to_s
|
@@ -176,7 +205,7 @@ module Tapioca
|
|
176
205
|
|
177
206
|
sig { returns(T::Boolean) }
|
178
207
|
def gem_in_bundle_path?
|
179
|
-
full_gem_path.start_with?(Bundler.bundle_path.to_s)
|
208
|
+
full_gem_path.start_with?(Bundler.bundle_path.to_s, Bundler.app_cache.to_s)
|
180
209
|
end
|
181
210
|
end
|
182
211
|
end
|
data/lib/tapioca/generator.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
require 'pathname'
|
5
5
|
require 'thor'
|
6
|
+
require "tapioca/core_ext/string"
|
6
7
|
|
7
8
|
module Tapioca
|
8
9
|
class Generator < ::Thor::Shell::Color
|
@@ -285,7 +286,7 @@ module Tapioca
|
|
285
286
|
def constantize(constant_names)
|
286
287
|
constant_map = constant_names.map do |name|
|
287
288
|
begin
|
288
|
-
[name, name
|
289
|
+
[name, Object.const_get(name)]
|
289
290
|
rescue NameError
|
290
291
|
[name, nil]
|
291
292
|
end
|
@@ -600,8 +601,9 @@ module Tapioca
|
|
600
601
|
if diff.empty?
|
601
602
|
say("Nothing to do, all RBIs are up-to-date.")
|
602
603
|
else
|
603
|
-
say("RBI files are out-of-date, please run:")
|
604
|
-
say(" `#{Config::DEFAULT_COMMAND} dsl`")
|
604
|
+
say("RBI files are out-of-date. In your development environment, please run:", :green)
|
605
|
+
say(" `#{Config::DEFAULT_COMMAND} dsl`", [:green, :bold])
|
606
|
+
say("Once it is complete, be sure to commit and push any changes", :green)
|
605
607
|
|
606
608
|
say("")
|
607
609
|
|
data/lib/tapioca/internal.rb
CHANGED
@@ -6,12 +6,20 @@ require "tapioca/loader"
|
|
6
6
|
require "tapioca/constant_locator"
|
7
7
|
require "tapioca/generic_type_registry"
|
8
8
|
require "tapioca/sorbet_ext/generic_name_patch"
|
9
|
+
require "tapioca/sorbet_ext/fixed_hash_patch"
|
9
10
|
require "tapioca/config"
|
10
11
|
require "tapioca/config_builder"
|
11
12
|
require "tapioca/generator"
|
12
13
|
require "tapioca/cli"
|
13
14
|
require "tapioca/cli/main"
|
14
15
|
require "tapioca/gemfile"
|
16
|
+
require "tapioca/rbi/model"
|
17
|
+
require "tapioca/rbi/visitor"
|
18
|
+
require "tapioca/rbi/rewriters/nest_singleton_methods"
|
19
|
+
require "tapioca/rbi/rewriters/nest_non_public_methods"
|
20
|
+
require "tapioca/rbi/rewriters/group_nodes"
|
21
|
+
require "tapioca/rbi/rewriters/sort_nodes"
|
22
|
+
require "tapioca/rbi/printer"
|
15
23
|
require "tapioca/compilers/sorbet"
|
16
24
|
require "tapioca/compilers/requires_compiler"
|
17
25
|
require "tapioca/compilers/symbol_table_compiler"
|
@@ -0,0 +1,405 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Tapioca
|
5
|
+
module RBI
|
6
|
+
class Node
|
7
|
+
extend T::Sig
|
8
|
+
extend T::Helpers
|
9
|
+
|
10
|
+
abstract!
|
11
|
+
|
12
|
+
sig { returns(T.nilable(Tree)) }
|
13
|
+
attr_accessor :parent_tree
|
14
|
+
|
15
|
+
sig { void }
|
16
|
+
def initialize
|
17
|
+
@parent_tree = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
sig { void }
|
21
|
+
def detach
|
22
|
+
tree = parent_tree
|
23
|
+
return unless tree
|
24
|
+
tree.nodes.delete(self)
|
25
|
+
self.parent_tree = nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Tree < Node
|
30
|
+
extend T::Sig
|
31
|
+
|
32
|
+
sig { returns(T::Array[Node]) }
|
33
|
+
attr_reader :nodes
|
34
|
+
|
35
|
+
sig { void }
|
36
|
+
def initialize
|
37
|
+
super()
|
38
|
+
@nodes = T.let([], T::Array[Node])
|
39
|
+
end
|
40
|
+
|
41
|
+
sig { params(node: Node).void }
|
42
|
+
def <<(node)
|
43
|
+
node.parent_tree = self
|
44
|
+
@nodes << node
|
45
|
+
end
|
46
|
+
|
47
|
+
sig { returns(T::Boolean) }
|
48
|
+
def empty?
|
49
|
+
nodes.empty?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Scopes
|
54
|
+
|
55
|
+
class Scope < Tree
|
56
|
+
extend T::Helpers
|
57
|
+
|
58
|
+
abstract!
|
59
|
+
end
|
60
|
+
|
61
|
+
class Module < Scope
|
62
|
+
extend T::Sig
|
63
|
+
|
64
|
+
sig { returns(String) }
|
65
|
+
attr_accessor :name
|
66
|
+
|
67
|
+
sig { params(name: String).void }
|
68
|
+
def initialize(name)
|
69
|
+
super()
|
70
|
+
@name = name
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class Class < Scope
|
75
|
+
extend T::Sig
|
76
|
+
|
77
|
+
sig { returns(String) }
|
78
|
+
attr_accessor :name
|
79
|
+
|
80
|
+
sig { returns(T.nilable(String)) }
|
81
|
+
attr_accessor :superclass_name
|
82
|
+
|
83
|
+
sig { params(name: String, superclass_name: T.nilable(String)).void }
|
84
|
+
def initialize(name, superclass_name: nil)
|
85
|
+
super()
|
86
|
+
@name = name
|
87
|
+
@superclass_name = superclass_name
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class SingletonClass < Scope
|
92
|
+
extend T::Sig
|
93
|
+
|
94
|
+
sig { void }
|
95
|
+
def initialize
|
96
|
+
super()
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Consts
|
101
|
+
|
102
|
+
class Const < Node
|
103
|
+
extend T::Sig
|
104
|
+
|
105
|
+
sig { returns(String) }
|
106
|
+
attr_reader :name, :value
|
107
|
+
|
108
|
+
sig { params(name: String, value: String).void }
|
109
|
+
def initialize(name, value)
|
110
|
+
super()
|
111
|
+
@name = name
|
112
|
+
@value = value
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Methods and args
|
117
|
+
|
118
|
+
class Method < Node
|
119
|
+
extend T::Sig
|
120
|
+
|
121
|
+
sig { returns(String) }
|
122
|
+
attr_accessor :name
|
123
|
+
|
124
|
+
sig { returns(T::Array[Param]) }
|
125
|
+
attr_reader :params
|
126
|
+
|
127
|
+
sig { returns(T::Boolean) }
|
128
|
+
attr_accessor :is_singleton
|
129
|
+
|
130
|
+
sig { returns(Visibility) }
|
131
|
+
attr_accessor :visibility
|
132
|
+
|
133
|
+
sig { returns(T::Array[Sig]) }
|
134
|
+
attr_accessor :sigs
|
135
|
+
|
136
|
+
sig do
|
137
|
+
params(
|
138
|
+
name: String,
|
139
|
+
params: T::Array[Param],
|
140
|
+
is_singleton: T::Boolean,
|
141
|
+
visibility: Visibility,
|
142
|
+
sigs: T::Array[Sig]
|
143
|
+
).void
|
144
|
+
end
|
145
|
+
def initialize(name, params: [], is_singleton: false, visibility: Visibility::Public, sigs: [])
|
146
|
+
super()
|
147
|
+
@name = name
|
148
|
+
@params = params
|
149
|
+
@is_singleton = is_singleton
|
150
|
+
@visibility = visibility
|
151
|
+
@sigs = sigs
|
152
|
+
end
|
153
|
+
|
154
|
+
sig { params(param: Param).void }
|
155
|
+
def <<(param)
|
156
|
+
@params << param
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class Param < Node
|
161
|
+
extend T::Sig
|
162
|
+
|
163
|
+
sig { returns(String) }
|
164
|
+
attr_reader :name
|
165
|
+
|
166
|
+
sig { params(name: String).void }
|
167
|
+
def initialize(name)
|
168
|
+
super()
|
169
|
+
@name = name
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
class OptParam < Param
|
174
|
+
extend T::Sig
|
175
|
+
|
176
|
+
sig { returns(String) }
|
177
|
+
attr_reader :value
|
178
|
+
|
179
|
+
sig { params(name: String, value: String).void }
|
180
|
+
def initialize(name, value)
|
181
|
+
super(name)
|
182
|
+
@value = value
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
class RestParam < Param; end
|
187
|
+
class KwParam < Param; end
|
188
|
+
class KwOptParam < OptParam; end
|
189
|
+
class KwRestParam < Param; end
|
190
|
+
class BlockParam < Param; end
|
191
|
+
|
192
|
+
# Mixins
|
193
|
+
|
194
|
+
class Mixin < Node
|
195
|
+
extend T::Sig
|
196
|
+
extend T::Helpers
|
197
|
+
|
198
|
+
abstract!
|
199
|
+
|
200
|
+
sig { returns(String) }
|
201
|
+
attr_reader :name
|
202
|
+
|
203
|
+
sig { params(name: String).void }
|
204
|
+
def initialize(name)
|
205
|
+
super()
|
206
|
+
@name = name
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
class Include < Mixin; end
|
211
|
+
class Extend < Mixin; end
|
212
|
+
|
213
|
+
# Visibility
|
214
|
+
|
215
|
+
class Visibility < Node
|
216
|
+
extend T::Sig
|
217
|
+
extend T::Helpers
|
218
|
+
|
219
|
+
abstract!
|
220
|
+
|
221
|
+
sig { returns(Symbol) }
|
222
|
+
attr_reader :visibility
|
223
|
+
|
224
|
+
sig { params(visibility: Symbol).void }
|
225
|
+
def initialize(visibility)
|
226
|
+
super()
|
227
|
+
@visibility = visibility
|
228
|
+
end
|
229
|
+
|
230
|
+
sig { returns(T::Boolean) }
|
231
|
+
def public?
|
232
|
+
visibility == :public
|
233
|
+
end
|
234
|
+
|
235
|
+
Public = T.let(Visibility.new(:public), Visibility)
|
236
|
+
Protected = T.let(Visibility.new(:protected), Visibility)
|
237
|
+
Private = T.let(Visibility.new(:private), Visibility)
|
238
|
+
end
|
239
|
+
|
240
|
+
# Sorbet's sigs
|
241
|
+
|
242
|
+
class Sig < Node
|
243
|
+
extend T::Sig
|
244
|
+
|
245
|
+
sig { returns(T::Array[SigParam]) }
|
246
|
+
attr_reader :params
|
247
|
+
|
248
|
+
sig { returns(T.nilable(String)) }
|
249
|
+
attr_accessor :return_type
|
250
|
+
|
251
|
+
sig { returns(T::Boolean) }
|
252
|
+
attr_accessor :is_abstract, :is_override, :is_overridable
|
253
|
+
|
254
|
+
sig { returns(T::Array[String]) }
|
255
|
+
attr_reader :type_params
|
256
|
+
|
257
|
+
sig do
|
258
|
+
params(
|
259
|
+
params: T::Array[SigParam],
|
260
|
+
return_type: T.nilable(String),
|
261
|
+
is_abstract: T::Boolean,
|
262
|
+
is_override: T::Boolean,
|
263
|
+
is_overridable: T::Boolean,
|
264
|
+
type_params: T::Array[String]
|
265
|
+
).void
|
266
|
+
end
|
267
|
+
def initialize(
|
268
|
+
params: [],
|
269
|
+
return_type: nil,
|
270
|
+
is_abstract: false,
|
271
|
+
is_override: false,
|
272
|
+
is_overridable: false,
|
273
|
+
type_params: []
|
274
|
+
)
|
275
|
+
super()
|
276
|
+
@params = params
|
277
|
+
@return_type = return_type
|
278
|
+
@is_abstract = is_abstract
|
279
|
+
@is_override = is_override
|
280
|
+
@is_overridable = is_overridable
|
281
|
+
@type_params = type_params
|
282
|
+
end
|
283
|
+
|
284
|
+
sig { params(param: SigParam).void }
|
285
|
+
def <<(param)
|
286
|
+
@params << param
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
class SigParam < Node
|
291
|
+
extend T::Sig
|
292
|
+
|
293
|
+
sig { returns(String) }
|
294
|
+
attr_reader :name, :type
|
295
|
+
|
296
|
+
sig { params(name: String, type: String).void }
|
297
|
+
def initialize(name, type)
|
298
|
+
super()
|
299
|
+
@name = name
|
300
|
+
@type = type
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# Sorbet's T::Struct
|
305
|
+
|
306
|
+
class TStruct < Class
|
307
|
+
extend T::Sig
|
308
|
+
|
309
|
+
sig { params(name: String).void }
|
310
|
+
def initialize(name)
|
311
|
+
super(name, superclass_name: "::T::Struct")
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
class TStructField < Node
|
316
|
+
extend T::Sig
|
317
|
+
extend T::Helpers
|
318
|
+
|
319
|
+
abstract!
|
320
|
+
|
321
|
+
sig { returns(String) }
|
322
|
+
attr_accessor :name, :type
|
323
|
+
|
324
|
+
sig { returns(T.nilable(String)) }
|
325
|
+
attr_accessor :default
|
326
|
+
|
327
|
+
sig do
|
328
|
+
params(
|
329
|
+
name: String,
|
330
|
+
type: String,
|
331
|
+
default: T.nilable(String)
|
332
|
+
).void
|
333
|
+
end
|
334
|
+
def initialize(name, type, default: nil)
|
335
|
+
super()
|
336
|
+
@name = name
|
337
|
+
@type = type
|
338
|
+
@default = default
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
class TStructProp < TStructField; end
|
343
|
+
class TStructConst < TStructField; end
|
344
|
+
|
345
|
+
# Sorbet's T::Enum
|
346
|
+
|
347
|
+
class TEnum < Class
|
348
|
+
extend T::Sig
|
349
|
+
|
350
|
+
sig { params(name: String).void }
|
351
|
+
def initialize(name)
|
352
|
+
super(name, superclass_name: "::T::Enum")
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
class TEnumBlock < Node
|
357
|
+
extend T::Sig
|
358
|
+
|
359
|
+
sig { returns(T::Array[String]) }
|
360
|
+
attr_reader :names
|
361
|
+
|
362
|
+
sig { params(names: T::Array[String]).void }
|
363
|
+
def initialize(names = [])
|
364
|
+
super()
|
365
|
+
@names = names
|
366
|
+
end
|
367
|
+
|
368
|
+
sig { returns(T::Boolean) }
|
369
|
+
def empty?
|
370
|
+
names.empty?
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
# Sorbet's misc.
|
375
|
+
|
376
|
+
class Helper < Node
|
377
|
+
extend T::Helpers
|
378
|
+
|
379
|
+
sig { returns(String) }
|
380
|
+
attr_reader :name
|
381
|
+
|
382
|
+
sig { params(name: String).void }
|
383
|
+
def initialize(name)
|
384
|
+
super()
|
385
|
+
@name = name
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
class TypeMember < Node
|
390
|
+
extend T::Sig
|
391
|
+
|
392
|
+
sig { returns(String) }
|
393
|
+
attr_reader :name, :value
|
394
|
+
|
395
|
+
sig { params(name: String, value: String).void }
|
396
|
+
def initialize(name, value)
|
397
|
+
super()
|
398
|
+
@name = name
|
399
|
+
@value = value
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
class MixesInClassMethods < Mixin; end
|
404
|
+
end
|
405
|
+
end
|