rbs_rails 0.3.0 → 0.7.0
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/.github/workflows/ci.yml +18 -0
- data/.gitignore +3 -0
- data/.gitmodules +0 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +3 -2
- data/README.md +23 -43
- data/Rakefile +11 -2
- data/Steepfile +10 -1
- data/assets/sig/pg.rbs +5 -0
- data/assets/sig/que.rbs +4 -0
- data/assets/sig/queue_classic.rbs +4 -0
- data/assets/sig/rack.rbs +1 -0
- data/assets/sig/rails.rbs +1 -5
- data/assets/sig/sidekiq.rbs +4 -0
- data/assets/sig/sneakers.rbs +4 -0
- data/assets/sig/sucker_punch.rbs +4 -0
- data/bin/add-type-params.rb +7 -0
- data/bin/gem_rbs +94 -0
- data/bin/postprocess.rb +15 -6
- data/bin/rbs +29 -2
- data/bin/rbs-prototype-rb.rb +59 -6
- data/lib/rbs_rails.rb +4 -0
- data/lib/rbs_rails/active_record.rb +100 -50
- data/lib/rbs_rails/dependency_builder.rb +43 -0
- data/lib/rbs_rails/rake_task.rb +83 -0
- data/lib/rbs_rails/util.rb +25 -0
- data/lib/rbs_rails/version.rb +1 -1
- data/rbs_rails.gemspec +2 -1
- data/sig/fileutils.rbs +1 -0
- data/sig/rake.rbs +6 -0
- data/sig/rbs_rails/active_record.rbs +8 -2
- data/sig/rbs_rails/dependency_builder.rbs +9 -0
- data/sig/rbs_rails/rake_task.rbs +26 -0
- data/sig/rbs_rails/util.rbs +11 -0
- metadata +34 -13
- data/.travis.yml +0 -8
- data/assets/sig/action_controller.rbs +0 -49
- data/assets/sig/active_record.rbs +0 -137
- data/assets/sig/generated/actionpack.rbs +0 -11677
- data/assets/sig/generated/actionview.rbs +0 -10491
- data/assets/sig/generated/activemodel.rbs +0 -4139
- data/assets/sig/generated/activerecord-meta-programming.rbs +0 -98
- data/assets/sig/generated/activerecord.rbs +0 -24023
- data/assets/sig/generated/activesupport.rbs +0 -12207
- data/assets/sig/generated/railties.rbs +0 -4647
data/bin/rbs-prototype-rb.rb
CHANGED
@@ -17,7 +17,7 @@ using Module.new {
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
def process_class_methods(node, decls:, comments:,
|
20
|
+
def process_class_methods(node, decls:, comments:, context:)
|
21
21
|
return false unless node.type == :ITER
|
22
22
|
|
23
23
|
fcall = node.children[0]
|
@@ -37,13 +37,13 @@ using Module.new {
|
|
37
37
|
decls.push mod
|
38
38
|
|
39
39
|
each_node [node.children[1]] do |child|
|
40
|
-
process child, decls: mod.members, comments: comments,
|
40
|
+
process child, decls: mod.members, comments: comments, context: RBS::Prototype::RB::Context.initial
|
41
41
|
end
|
42
42
|
|
43
43
|
true
|
44
44
|
end
|
45
45
|
|
46
|
-
def process_struct_new(node, decls:, comments:,
|
46
|
+
def process_struct_new(node, decls:, comments:, context:)
|
47
47
|
return unless node.type == :CDECL
|
48
48
|
|
49
49
|
name, *_, rhs = node.children
|
@@ -68,6 +68,7 @@ using Module.new {
|
|
68
68
|
kls.members << RBS::AST::Members::AttrAccessor.new(
|
69
69
|
name: f.children.first,
|
70
70
|
type: untyped,
|
71
|
+
kind: :instance,
|
71
72
|
ivar_name: false,
|
72
73
|
annotations: [],
|
73
74
|
location: nil,
|
@@ -78,13 +79,65 @@ using Module.new {
|
|
78
79
|
|
79
80
|
if body
|
80
81
|
each_node [body] do |child|
|
81
|
-
process child, decls: kls.members, comments: comments,
|
82
|
+
process child, decls: kls.members, comments: comments, context: RBS::Prototype::RB::Context.initial
|
82
83
|
end
|
83
84
|
end
|
84
85
|
|
85
86
|
true
|
86
87
|
end
|
87
88
|
|
89
|
+
def process_attr_internal(node, decls:, comments:, context:)
|
90
|
+
case node.type
|
91
|
+
when :FCALL, :VCALL
|
92
|
+
args = node.children[1]&.children || []
|
93
|
+
|
94
|
+
case node.children[0]
|
95
|
+
when :attr_internal_reader
|
96
|
+
args.each do |arg|
|
97
|
+
if arg && (name = literal_to_symbol(arg))
|
98
|
+
decls << RBS::AST::Members::AttrReader.new(
|
99
|
+
name: name,
|
100
|
+
ivar_name: :"@_#{name}",
|
101
|
+
type: RBS::Types::Bases::Any.new(location: nil),
|
102
|
+
kind: context.attribute_kind,
|
103
|
+
location: nil,
|
104
|
+
comment: comments[node.first_lineno - 1],
|
105
|
+
annotations: []
|
106
|
+
)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
when :attr_internal_writer
|
110
|
+
args.each do |arg|
|
111
|
+
if arg && (name = literal_to_symbol(arg))
|
112
|
+
decls << RBS::AST::Members::AttrWriter.new(
|
113
|
+
name: name,
|
114
|
+
ivar_name: :"@_#{name}",
|
115
|
+
type: RBS::Types::Bases::Any.new(location: nil),
|
116
|
+
kind: context.attribute_kind,
|
117
|
+
location: nil,
|
118
|
+
comment: comments[node.first_lineno - 1],
|
119
|
+
annotations: []
|
120
|
+
)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
when :attr_internal_accessor, :attr_internal
|
124
|
+
args.each do |arg|
|
125
|
+
if arg && (name = literal_to_symbol(arg))
|
126
|
+
decls << RBS::AST::Members::AttrAccessor.new(
|
127
|
+
name: name,
|
128
|
+
ivar_name: :"@_#{name}",
|
129
|
+
type: RBS::Types::Bases::Any.new(location: nil),
|
130
|
+
kind: context.attribute_kind,
|
131
|
+
location: nil,
|
132
|
+
comment: comments[node.first_lineno - 1],
|
133
|
+
annotations: []
|
134
|
+
)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
88
141
|
def class_new_method_to_type(node)
|
89
142
|
case node.type
|
90
143
|
when :CALL
|
@@ -122,14 +175,14 @@ using Module.new {
|
|
122
175
|
|
123
176
|
def struct_as_superclass
|
124
177
|
name = RBS::TypeName.new(name: 'Struct', namespace: RBS::Namespace.root)
|
125
|
-
RBS::AST::Declarations::Class::Super.new(name: name, args: ['untyped'])
|
178
|
+
RBS::AST::Declarations::Class::Super.new(name: name, args: ['untyped'], location: nil)
|
126
179
|
end
|
127
180
|
end
|
128
181
|
}
|
129
182
|
|
130
183
|
module PrototypeExt
|
131
184
|
def process(...)
|
132
|
-
process_class_methods(...) || process_struct_new(...) || super
|
185
|
+
process_class_methods(...) || process_struct_new(...) || process_attr_internal(...) || super
|
133
186
|
end
|
134
187
|
|
135
188
|
def literal_to_type(node)
|
data/lib/rbs_rails.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
require 'parser/current'
|
2
|
+
require 'rbs'
|
3
|
+
require 'stringio'
|
2
4
|
|
3
5
|
require_relative "rbs_rails/version"
|
6
|
+
require_relative "rbs_rails/util"
|
4
7
|
require_relative 'rbs_rails/active_record'
|
5
8
|
require_relative 'rbs_rails/path_helpers'
|
9
|
+
require_relative 'rbs_rails/dependency_builder'
|
6
10
|
|
7
11
|
module RbsRails
|
8
12
|
class Error < StandardError; end
|
@@ -1,59 +1,84 @@
|
|
1
1
|
module RbsRails
|
2
2
|
module ActiveRecord
|
3
|
-
|
4
|
-
|
3
|
+
|
4
|
+
def self.class_to_rbs(klass, dependencies: [])
|
5
|
+
Generator.new(klass, dependencies: dependencies).generate
|
5
6
|
end
|
6
7
|
|
7
8
|
class Generator
|
8
|
-
def initialize(klass)
|
9
|
+
def initialize(klass, dependencies:)
|
9
10
|
@klass = klass
|
11
|
+
@dependencies = dependencies
|
12
|
+
@klass_name = Util.module_name(klass)
|
13
|
+
|
14
|
+
namespaces = klass_name.split('::').tap{ |names| names.pop }
|
15
|
+
@dependencies << namespaces.join('::') unless namespaces.empty?
|
10
16
|
end
|
11
17
|
|
12
18
|
def generate
|
13
|
-
|
14
|
-
klass_decl,
|
15
|
-
relation_decl,
|
16
|
-
collection_proxy_decl,
|
17
|
-
].join("\n")
|
19
|
+
Util.format_rbs klass_decl
|
18
20
|
end
|
19
21
|
|
20
22
|
private def klass_decl
|
21
23
|
<<~RBS
|
22
24
|
#{header}
|
23
|
-
extend _ActiveRecord_Relation_ClassMethods[#{
|
25
|
+
extend _ActiveRecord_Relation_ClassMethods[#{klass_name}, #{relation_class_name}]
|
24
26
|
|
25
|
-
#{columns
|
26
|
-
#{associations
|
27
|
-
#{enum_instance_methods
|
28
|
-
#{enum_scope_methods(singleton: true)
|
29
|
-
#{scopes(singleton: true)
|
30
|
-
|
27
|
+
#{columns}
|
28
|
+
#{associations}
|
29
|
+
#{enum_instance_methods}
|
30
|
+
#{enum_scope_methods(singleton: true)}
|
31
|
+
#{scopes(singleton: true)}
|
32
|
+
|
33
|
+
#{relation_decl}
|
34
|
+
|
35
|
+
#{collection_proxy_decl}
|
36
|
+
|
37
|
+
#{footer}
|
31
38
|
RBS
|
32
39
|
end
|
33
40
|
|
34
41
|
private def relation_decl
|
35
42
|
<<~RBS
|
36
43
|
class #{relation_class_name} < ActiveRecord::Relation
|
37
|
-
include _ActiveRecord_Relation[#{
|
38
|
-
include Enumerable[#{
|
39
|
-
#{enum_scope_methods(singleton: false)
|
40
|
-
#{scopes(singleton: false)
|
44
|
+
include _ActiveRecord_Relation[#{klass_name}]
|
45
|
+
include Enumerable[#{klass_name}]
|
46
|
+
#{enum_scope_methods(singleton: false)}
|
47
|
+
#{scopes(singleton: false)}
|
41
48
|
end
|
42
49
|
RBS
|
43
50
|
end
|
44
51
|
|
45
52
|
private def collection_proxy_decl
|
46
53
|
<<~RBS
|
47
|
-
class
|
54
|
+
class ActiveRecord_Associations_CollectionProxy < ActiveRecord::Associations::CollectionProxy
|
48
55
|
end
|
49
56
|
RBS
|
50
57
|
end
|
51
58
|
|
52
|
-
|
53
59
|
private def header
|
54
|
-
|
55
|
-
|
56
|
-
|
60
|
+
namespace = +''
|
61
|
+
klass_name.split('::').map do |mod_name|
|
62
|
+
namespace += "::#{mod_name}"
|
63
|
+
mod_object = Object.const_get(namespace)
|
64
|
+
case mod_object
|
65
|
+
when Class
|
66
|
+
# @type var superclass: Class
|
67
|
+
superclass = _ = mod_object.superclass
|
68
|
+
superclass_name = Util.module_name(superclass)
|
69
|
+
@dependencies << superclass_name
|
70
|
+
|
71
|
+
"class #{mod_name} < #{superclass_name}"
|
72
|
+
when Module
|
73
|
+
"module #{mod_name}"
|
74
|
+
else
|
75
|
+
raise 'unreachable'
|
76
|
+
end
|
77
|
+
end.join("\n")
|
78
|
+
end
|
79
|
+
|
80
|
+
private def footer
|
81
|
+
"end\n" * klass_name.split('::').size
|
57
82
|
end
|
58
83
|
|
59
84
|
private def associations
|
@@ -66,21 +91,45 @@ module RbsRails
|
|
66
91
|
|
67
92
|
private def has_many
|
68
93
|
klass.reflect_on_all_associations(:has_many).map do |a|
|
69
|
-
|
94
|
+
singular_name = a.name.to_s.singularize
|
95
|
+
type = Util.module_name(a.klass)
|
96
|
+
collection_type = "#{type}::ActiveRecord_Associations_CollectionProxy"
|
97
|
+
<<~RUBY.chomp
|
98
|
+
def #{a.name}: () -> #{collection_type}
|
99
|
+
def #{a.name}=: (#{collection_type} | Array[#{type}]) -> (#{collection_type} | Array[#{type}])
|
100
|
+
def #{singular_name}_ids: () -> Array[Integer]
|
101
|
+
def #{singular_name}_ids=: (Array[Integer]) -> Array[Integer]
|
102
|
+
RUBY
|
70
103
|
end.join("\n")
|
71
104
|
end
|
72
105
|
|
73
106
|
private def has_one
|
74
107
|
klass.reflect_on_all_associations(:has_one).map do |a|
|
75
|
-
type = a.polymorphic? ? 'untyped' : a.klass
|
76
|
-
|
108
|
+
type = a.polymorphic? ? 'untyped' : Util.module_name(a.klass)
|
109
|
+
type_optional = optional(type)
|
110
|
+
<<~RUBY.chomp
|
111
|
+
def #{a.name}: () -> #{type}
|
112
|
+
def #{a.name}=: (#{type_optional}) -> #{type_optional}
|
113
|
+
def build_#{a.name}: (untyped) -> #{type}
|
114
|
+
def create_#{a.name}: (untyped) -> #{type}
|
115
|
+
def create_#{a.name}!: (untyped) -> #{type}
|
116
|
+
def reload_#{a.name}: () -> #{type_optional}
|
117
|
+
RUBY
|
77
118
|
end.join("\n")
|
78
119
|
end
|
79
120
|
|
80
121
|
private def belongs_to
|
81
122
|
klass.reflect_on_all_associations(:belongs_to).map do |a|
|
82
|
-
type = a.polymorphic? ? 'untyped' : a.klass
|
83
|
-
|
123
|
+
type = a.polymorphic? ? 'untyped' : Util.module_name(a.klass)
|
124
|
+
type_optional = optional(type)
|
125
|
+
<<~RUBY.chomp
|
126
|
+
def #{a.name}: () -> #{type}
|
127
|
+
def #{a.name}=: (#{type_optional}) -> #{type_optional}
|
128
|
+
def build_#{a.name}: (untyped) -> #{type}
|
129
|
+
def create_#{a.name}: (untyped) -> #{type}
|
130
|
+
def create_#{a.name}!: (untyped) -> #{type}
|
131
|
+
def reload_#{a.name}: () -> #{type_optional}
|
132
|
+
RUBY
|
84
133
|
end.join("\n")
|
85
134
|
end
|
86
135
|
|
@@ -130,6 +179,7 @@ module RbsRails
|
|
130
179
|
return [] unless ast
|
131
180
|
|
132
181
|
traverse(ast).map do |node|
|
182
|
+
# @type block: nil | Hash[untyped, untyped]
|
133
183
|
next unless node.type == :send
|
134
184
|
next unless node.children[0].nil?
|
135
185
|
next unless node.children[1] == :enum
|
@@ -168,6 +218,7 @@ module RbsRails
|
|
168
218
|
return '' unless ast
|
169
219
|
|
170
220
|
traverse(ast).map do |node|
|
221
|
+
# @type block: nil | String
|
171
222
|
next unless node.type == :send
|
172
223
|
next unless node.children[0].nil?
|
173
224
|
next unless node.children[1] == :scope
|
@@ -209,10 +260,7 @@ module RbsRails
|
|
209
260
|
private def parse_model_file
|
210
261
|
return @parse_model_file if defined?(@parse_model_file)
|
211
262
|
|
212
|
-
|
213
|
-
# @type var class_name: String
|
214
|
-
class_name = _ = klass.name
|
215
|
-
path = Rails.root.join('app/models/', class_name.underscore + '.rb')
|
263
|
+
path = Rails.root.join('app/models/', klass_name.underscore + '.rb')
|
216
264
|
return @parse_model_file = nil unless path.exist?
|
217
265
|
return [] unless path.exist?
|
218
266
|
|
@@ -233,12 +281,16 @@ module RbsRails
|
|
233
281
|
end
|
234
282
|
|
235
283
|
private def relation_class_name
|
236
|
-
"
|
284
|
+
"ActiveRecord_Relation"
|
237
285
|
end
|
238
286
|
|
239
287
|
private def columns
|
240
288
|
klass.columns.map do |col|
|
241
|
-
class_name =
|
289
|
+
class_name = if enum_definitions.any? { |hash| hash.key?(col.name) || hash.key?(col.name.to_sym) }
|
290
|
+
'String'
|
291
|
+
else
|
292
|
+
sql_type_to_class(col.type)
|
293
|
+
end
|
242
294
|
class_name_opt = optional(class_name)
|
243
295
|
column_type = col.null ? class_name_opt : class_name
|
244
296
|
sig = <<~EOS
|
@@ -265,35 +317,33 @@ module RbsRails
|
|
265
317
|
private def sql_type_to_class(t)
|
266
318
|
case t
|
267
319
|
when :integer
|
268
|
-
Integer
|
320
|
+
'Integer'
|
269
321
|
when :float
|
270
|
-
Float
|
271
|
-
when :
|
272
|
-
|
322
|
+
'Float'
|
323
|
+
when :decimal
|
324
|
+
'BigDecimal'
|
325
|
+
when :string, :text, :citext, :uuid, :binary
|
326
|
+
'String'
|
273
327
|
when :datetime
|
274
|
-
|
275
|
-
# ActiveSupport::TimeWithZone.name
|
276
|
-
Time.name
|
328
|
+
'ActiveSupport::TimeWithZone'
|
277
329
|
when :boolean
|
278
|
-
"
|
330
|
+
"bool"
|
279
331
|
when :jsonb, :json
|
280
332
|
"untyped"
|
281
333
|
when :date
|
282
|
-
|
283
|
-
# Date.name
|
284
|
-
'untyped'
|
334
|
+
'Date'
|
285
335
|
when :time
|
286
|
-
Time
|
336
|
+
'Time'
|
287
337
|
when :inet
|
288
338
|
"IPAddr"
|
289
339
|
else
|
290
|
-
|
340
|
+
# Unknown column type, give up
|
341
|
+
'untyped'
|
291
342
|
end
|
292
343
|
end
|
293
344
|
|
294
345
|
private
|
295
|
-
|
296
|
-
attr_reader :klass
|
346
|
+
attr_reader :klass, :klass_name
|
297
347
|
end
|
298
348
|
end
|
299
349
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module RbsRails
|
2
|
+
class DependencyBuilder
|
3
|
+
attr_reader :deps
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@deps = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def build
|
10
|
+
dep_rbs = +""
|
11
|
+
done = Set.new(['ActiveRecord::Base', 'ActiveRecord', 'Object'])
|
12
|
+
deps.uniq!
|
13
|
+
while dep = deps.shift
|
14
|
+
next unless done.add?(dep)
|
15
|
+
|
16
|
+
case dep_object = Object.const_get(dep)
|
17
|
+
when Class
|
18
|
+
superclass = dep_object.superclass or raise
|
19
|
+
super_name = Util.module_name(superclass)
|
20
|
+
deps << super_name
|
21
|
+
dep_rbs << "class #{dep} < #{super_name} end\n"
|
22
|
+
when Module
|
23
|
+
dep_rbs << "module #{dep} end\n"
|
24
|
+
else
|
25
|
+
raise
|
26
|
+
end
|
27
|
+
|
28
|
+
# push namespaces
|
29
|
+
namespaces = dep.split('::')
|
30
|
+
namespaces.pop
|
31
|
+
namespaces.inject('') do |base, name|
|
32
|
+
full_name = base.empty? ? name : [base, name].join('::')
|
33
|
+
deps << full_name
|
34
|
+
full_name
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
unless dep_rbs.empty?
|
39
|
+
Util.format_rbs(dep_rbs)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/tasklib'
|
3
|
+
|
4
|
+
module RbsRails
|
5
|
+
class RakeTask < Rake::TaskLib
|
6
|
+
attr_accessor :ignore_model_if, :name, :signature_root_dir
|
7
|
+
|
8
|
+
def initialize(name = :rbs_rails, &block)
|
9
|
+
super()
|
10
|
+
|
11
|
+
@name = name
|
12
|
+
|
13
|
+
block.call(self) if block
|
14
|
+
|
15
|
+
setup_signature_root_dir!
|
16
|
+
|
17
|
+
def_copy_signature_files
|
18
|
+
def_generate_rbs_for_models
|
19
|
+
def_generate_rbs_for_path_helpers
|
20
|
+
def_all
|
21
|
+
end
|
22
|
+
|
23
|
+
def def_all
|
24
|
+
desc 'Run all tasks of rbs_rails'
|
25
|
+
|
26
|
+
deps = [:"#{name}:copy_signature_files", :"#{name}:generate_rbs_for_models", :"#{name}:generate_rbs_for_path_helpers"]
|
27
|
+
task("#{name}:all": deps)
|
28
|
+
end
|
29
|
+
|
30
|
+
def def_copy_signature_files
|
31
|
+
desc 'Copy RBS files for rbs_rails'
|
32
|
+
task("#{name}:copy_signature_files": :environment) do
|
33
|
+
require 'rbs_rails'
|
34
|
+
|
35
|
+
RbsRails.copy_signatures(to: signature_root_dir)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def def_generate_rbs_for_models
|
40
|
+
desc 'Generate RBS files for Active Record models'
|
41
|
+
task("#{name}:generate_rbs_for_models": :environment) do
|
42
|
+
require 'rbs_rails'
|
43
|
+
|
44
|
+
Rails.application.eager_load!
|
45
|
+
|
46
|
+
dep_builder = DependencyBuilder.new
|
47
|
+
|
48
|
+
# HACK: for steep
|
49
|
+
(_ = ::ActiveRecord::Base).descendants.each do |klass|
|
50
|
+
next if klass.abstract_class?
|
51
|
+
next if ignore_model_if&.call(klass)
|
52
|
+
|
53
|
+
path = signature_root_dir / "app/models/#{klass.name.underscore}.rbs"
|
54
|
+
path.dirname.mkpath
|
55
|
+
|
56
|
+
sig = RbsRails::ActiveRecord.class_to_rbs(klass, dependencies: dep_builder.deps)
|
57
|
+
path.write sig
|
58
|
+
end
|
59
|
+
|
60
|
+
if dep_rbs = dep_builder.build
|
61
|
+
signature_root_dir.join('model_dependencies.rbs').write(dep_rbs)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def def_generate_rbs_for_path_helpers
|
67
|
+
desc 'Generate RBS files for path helpers'
|
68
|
+
task("#{name}:generate_rbs_for_path_helpers": :environment) do
|
69
|
+
require 'rbs_rails'
|
70
|
+
|
71
|
+
out_path = signature_root_dir.join 'path_helpers.rbs'
|
72
|
+
rbs = RbsRails::PathHelpers.generate
|
73
|
+
out_path.write rbs
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private def setup_signature_root_dir!
|
78
|
+
@signature_root_dir ||= Rails.root / 'sig/rbs_rails'
|
79
|
+
@signature_root_dir = Pathname(@signature_root_dir)
|
80
|
+
@signature_root_dir.mkpath
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|