tapioca 0.4.20 → 0.4.24
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/dsl/protobuf.rb +132 -16
- 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 +24 -4
- data/lib/tapioca/generator.rb +8 -11
- data/lib/tapioca/generic_type_registry.rb +22 -19
- 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
@@ -108,8 +108,14 @@ module Tapioca
|
|
108
108
|
|
109
109
|
sig { returns(T::Array[Pathname]) }
|
110
110
|
def files
|
111
|
-
|
112
|
-
|
111
|
+
if default_gem?
|
112
|
+
@spec.files.map do |file|
|
113
|
+
ruby_lib_dir.join(file)
|
114
|
+
end
|
115
|
+
else
|
116
|
+
@spec.full_require_paths.flat_map do |path|
|
117
|
+
Pathname.glob((Pathname.new(path) / "**/*.rb").to_s)
|
118
|
+
end
|
113
119
|
end
|
114
120
|
end
|
115
121
|
|
@@ -125,11 +131,25 @@ module Tapioca
|
|
125
131
|
|
126
132
|
sig { params(path: String).returns(T::Boolean) }
|
127
133
|
def contains_path?(path)
|
128
|
-
|
134
|
+
if default_gem?
|
135
|
+
files.any? { |file| file.to_s == to_realpath(path) }
|
136
|
+
else
|
137
|
+
to_realpath(path).start_with?(full_gem_path) || has_parent_gemspec?(path)
|
138
|
+
end
|
129
139
|
end
|
130
140
|
|
131
141
|
private
|
132
142
|
|
143
|
+
sig { returns(T::Boolean) }
|
144
|
+
def default_gem?
|
145
|
+
@spec.respond_to?(:default_gem?) && @spec.default_gem?
|
146
|
+
end
|
147
|
+
|
148
|
+
sig { returns(Pathname) }
|
149
|
+
def ruby_lib_dir
|
150
|
+
Pathname.new(RbConfig::CONFIG["rubylibdir"])
|
151
|
+
end
|
152
|
+
|
133
153
|
sig { returns(String) }
|
134
154
|
def version_string
|
135
155
|
version = @spec.version.to_s
|
@@ -176,7 +196,7 @@ module Tapioca
|
|
176
196
|
|
177
197
|
sig { returns(T::Boolean) }
|
178
198
|
def gem_in_bundle_path?
|
179
|
-
full_gem_path.start_with?(Bundler.bundle_path.to_s)
|
199
|
+
full_gem_path.start_with?(Bundler.bundle_path.to_s, Bundler.app_cache.to_s)
|
180
200
|
end
|
181
201
|
end
|
182
202
|
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
|
@@ -145,8 +146,6 @@ module Tapioca
|
|
145
146
|
}
|
146
147
|
)
|
147
148
|
|
148
|
-
constant_lookup = {}
|
149
|
-
|
150
149
|
compiler.run do |constant, contents|
|
151
150
|
constant_name = Module.instance_method(:name).bind(constant).call
|
152
151
|
|
@@ -159,13 +158,12 @@ module Tapioca
|
|
159
158
|
|
160
159
|
if filename
|
161
160
|
rbi_files_to_purge.delete(filename)
|
162
|
-
constant_lookup[filename.relative_path_from(outpath)] = constant_name
|
163
161
|
end
|
164
162
|
end
|
165
163
|
say("")
|
166
164
|
|
167
165
|
if should_verify
|
168
|
-
perform_dsl_verification(outpath
|
166
|
+
perform_dsl_verification(outpath)
|
169
167
|
else
|
170
168
|
purge_stale_dsl_rbi_files(rbi_files_to_purge)
|
171
169
|
|
@@ -288,7 +286,7 @@ module Tapioca
|
|
288
286
|
def constantize(constant_names)
|
289
287
|
constant_map = constant_names.map do |name|
|
290
288
|
begin
|
291
|
-
[name, name
|
289
|
+
[name, Object.const_get(name)]
|
292
290
|
rescue NameError
|
293
291
|
[name, nil]
|
294
292
|
end
|
@@ -596,17 +594,16 @@ module Tapioca
|
|
596
594
|
end.sort
|
597
595
|
end
|
598
596
|
|
599
|
-
sig { params(dir: Pathname
|
600
|
-
def perform_dsl_verification(dir
|
597
|
+
sig { params(dir: Pathname).void }
|
598
|
+
def perform_dsl_verification(dir)
|
601
599
|
diff = verify_dsl_rbi(tmp_dir: dir)
|
602
600
|
|
603
601
|
if diff.empty?
|
604
602
|
say("Nothing to do, all RBIs are up-to-date.")
|
605
603
|
else
|
606
|
-
|
607
|
-
|
608
|
-
say("
|
609
|
-
say(" `#{Config::DEFAULT_COMMAND} dsl #{constants}`")
|
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)
|
610
607
|
|
611
608
|
say("")
|
612
609
|
|
@@ -100,7 +100,7 @@ module Tapioca
|
|
100
100
|
# the generic class `Foo[Bar]` is still a `Foo`. That is:
|
101
101
|
# `Foo[Bar].new.is_a?(Foo)` should be true, which isn't the case
|
102
102
|
# if we just clone the class. But subclassing works just fine.
|
103
|
-
|
103
|
+
create_safe_subclass(constant)
|
104
104
|
else
|
105
105
|
# This can only be a module and it is fine to just clone modules
|
106
106
|
# since they can't have instances and will not have `is_a?` relationships.
|
@@ -151,28 +151,31 @@ module Tapioca
|
|
151
151
|
end
|
152
152
|
|
153
153
|
sig { params(constant: Class).returns(Class) }
|
154
|
-
def
|
155
|
-
#
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
#
|
161
|
-
|
162
|
-
|
163
|
-
# Get the filename the sealed class was declared in
|
164
|
-
decl_file = constant.instance_variable_get(:@sorbet_sealed_module_decl_file)
|
154
|
+
def create_safe_subclass(constant)
|
155
|
+
# Lookup the "inherited" class method
|
156
|
+
inherited_method = constant.method(:inherited)
|
157
|
+
# and the module that defines it
|
158
|
+
owner = inherited_method.owner
|
159
|
+
|
160
|
+
# If no one has overriden the inherited method yet, just subclass
|
161
|
+
return Class.new(constant) if Class == owner
|
162
|
+
|
165
163
|
begin
|
166
|
-
#
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
164
|
+
# Otherwise, some inherited method could be preventing us
|
165
|
+
# from creating subclasses, so let's override it and rescue
|
166
|
+
owner.send(:define_method, :inherited) do |s|
|
167
|
+
begin
|
168
|
+
inherited_method.call(s)
|
169
|
+
rescue
|
170
|
+
# Ignoring errors
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
171
174
|
# return a subclass
|
172
175
|
Class.new(constant)
|
173
176
|
ensure
|
174
|
-
# Reinstate the original
|
175
|
-
|
177
|
+
# Reinstate the original inherited method back.
|
178
|
+
owner.send(:define_method, :inherited, inherited_method)
|
176
179
|
end
|
177
180
|
end
|
178
181
|
|
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
|