rbs_rails 0.11.0 → 0.12.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +1 -1
- data/CHANGELOG.md +13 -0
- data/Gemfile +3 -3
- data/Gemfile.lock +179 -125
- data/README.md +1 -0
- data/Steepfile +5 -0
- data/lib/generators/rbs_rails/install_generator.rb +16 -12
- data/lib/rbs_rails/active_record.rb +58 -46
- data/lib/rbs_rails/dependency_builder.rb +5 -1
- data/lib/rbs_rails/rake_task.rb +7 -7
- data/lib/rbs_rails/util.rb +14 -10
- data/lib/rbs_rails/version.rb +1 -1
- data/rbs_collection.lock.yaml +228 -48
- data/rbs_collection.yaml +0 -2
- data/rbs_rails.gemspec +1 -1
- data/sig/rbs_rails/active_record.rbs +9 -3
- data/sig/rbs_rails/dependency_builder.rbs +4 -0
- data/sig/rbs_rails/rake_task.rbs +1 -1
- data/sig/rbs_rails/util.rbs +1 -1
- metadata +4 -9
- data/sig/_internal/fileutils.rbs +0 -4
- data/sig/_internal/thor.rbs +0 -5
@@ -12,12 +12,14 @@ module RbsRails
|
|
12
12
|
end
|
13
13
|
|
14
14
|
class Generator
|
15
|
+
IGNORED_ENUM_KEYS = %i[_prefix _suffix _default _scopes]
|
16
|
+
|
15
17
|
def initialize(klass, dependencies:)
|
16
18
|
@klass = klass
|
17
19
|
@dependencies = dependencies
|
18
|
-
@klass_name = Util.module_name(klass)
|
20
|
+
@klass_name = Util.module_name(klass, abs: false)
|
19
21
|
|
20
|
-
namespaces = klass_name.split('::').tap{ |names| names.pop }
|
22
|
+
namespaces = klass_name(abs: false).split('::').tap{ |names| names.pop }
|
21
23
|
@dependencies << namespaces.join('::') unless namespaces.empty?
|
22
24
|
end
|
23
25
|
|
@@ -28,7 +30,7 @@ module RbsRails
|
|
28
30
|
private def klass_decl
|
29
31
|
<<~RBS
|
30
32
|
#{header}
|
31
|
-
extend _ActiveRecord_Relation_ClassMethods[#{klass_name}, #{relation_class_name}, #{pk_type}]
|
33
|
+
extend ::_ActiveRecord_Relation_ClassMethods[#{klass_name}, #{relation_class_name}, #{pk_type}]
|
32
34
|
|
33
35
|
#{columns}
|
34
36
|
#{associations}
|
@@ -60,7 +62,7 @@ module RbsRails
|
|
60
62
|
|
61
63
|
private def generated_relation_methods_decl
|
62
64
|
<<~RBS
|
63
|
-
module
|
65
|
+
module #{generated_relation_methods_name(abs: false)}
|
64
66
|
#{enum_scope_methods(singleton: false)}
|
65
67
|
#{scopes(singleton: false)}
|
66
68
|
#{delegated_type_scope(singleton: false)}
|
@@ -70,10 +72,10 @@ module RbsRails
|
|
70
72
|
|
71
73
|
private def relation_decl
|
72
74
|
<<~RBS
|
73
|
-
class #{relation_class_name} < ::ActiveRecord::Relation
|
74
|
-
include
|
75
|
-
include _ActiveRecord_Relation[#{klass_name}, #{pk_type}]
|
76
|
-
include Enumerable[#{klass_name}]
|
75
|
+
class #{relation_class_name(abs: false)} < ::ActiveRecord::Relation
|
76
|
+
include #{generated_relation_methods_name}
|
77
|
+
include ::_ActiveRecord_Relation[#{klass_name}, #{pk_type}]
|
78
|
+
include ::Enumerable[#{klass_name}]
|
77
79
|
end
|
78
80
|
RBS
|
79
81
|
end
|
@@ -81,22 +83,22 @@ module RbsRails
|
|
81
83
|
private def collection_proxy_decl
|
82
84
|
<<~RBS
|
83
85
|
class ActiveRecord_Associations_CollectionProxy < ::ActiveRecord::Associations::CollectionProxy
|
84
|
-
include
|
85
|
-
include _ActiveRecord_Relation[#{klass_name}, #{pk_type}]
|
86
|
+
include #{generated_relation_methods_name}
|
87
|
+
include ::_ActiveRecord_Relation[#{klass_name}, #{pk_type}]
|
86
88
|
end
|
87
89
|
RBS
|
88
90
|
end
|
89
91
|
|
90
92
|
private def header
|
91
93
|
namespace = +''
|
92
|
-
klass_name.split('::').map do |mod_name|
|
94
|
+
klass_name(abs: false).split('::').map do |mod_name|
|
93
95
|
namespace += "::#{mod_name}"
|
94
96
|
mod_object = Object.const_get(namespace)
|
95
97
|
case mod_object
|
96
98
|
when Class
|
97
99
|
# @type var superclass: Class
|
98
100
|
superclass = _ = mod_object.superclass
|
99
|
-
superclass_name = Util.module_name(superclass)
|
101
|
+
superclass_name = Util.module_name(superclass, abs: false)
|
100
102
|
@dependencies << superclass_name
|
101
103
|
|
102
104
|
"class #{mod_name} < ::#{superclass_name}"
|
@@ -109,7 +111,7 @@ module RbsRails
|
|
109
111
|
end
|
110
112
|
|
111
113
|
private def footer
|
112
|
-
"end\n" * klass_name.split('::').size
|
114
|
+
"end\n" * klass_name(abs: false).split('::').size
|
113
115
|
end
|
114
116
|
|
115
117
|
private def associations
|
@@ -131,9 +133,9 @@ module RbsRails
|
|
131
133
|
|
132
134
|
<<~RUBY.chomp
|
133
135
|
def #{a.name}: () -> #{collection_type}
|
134
|
-
def #{a.name}=: (#{collection_type} | Array[#{type}]) -> (#{collection_type} | Array[#{type}])
|
135
|
-
def #{singular_name}_ids: () -> Array[Integer]
|
136
|
-
def #{singular_name}_ids=: (Array[Integer]) -> Array[Integer]
|
136
|
+
def #{a.name}=: (#{collection_type} | ::Array[#{type}]) -> (#{collection_type} | ::Array[#{type}])
|
137
|
+
def #{singular_name}_ids: () -> ::Array[::Integer]
|
138
|
+
def #{singular_name}_ids=: (::Array[::Integer]) -> ::Array[::Integer]
|
137
139
|
RUBY
|
138
140
|
end.join("\n")
|
139
141
|
end
|
@@ -147,7 +149,7 @@ module RbsRails
|
|
147
149
|
<<~RUBY.chomp
|
148
150
|
def #{a.name}: () -> #{type_optional}
|
149
151
|
def #{a.name}=: (#{type_optional}) -> #{type_optional}
|
150
|
-
def build_#{a.name}: (untyped) -> #{type}
|
152
|
+
def build_#{a.name}: (?untyped) -> #{type}
|
151
153
|
def create_#{a.name}: (untyped) -> #{type}
|
152
154
|
def create_#{a.name}!: (untyped) -> #{type}
|
153
155
|
def reload_#{a.name}: () -> #{type_optional}
|
@@ -159,11 +161,13 @@ module RbsRails
|
|
159
161
|
klass.reflect_on_all_associations(:belongs_to).map do |a|
|
160
162
|
@dependencies << a.klass.name unless a.polymorphic?
|
161
163
|
|
164
|
+
is_optional = a.options[:optional]
|
165
|
+
|
162
166
|
type = a.polymorphic? ? 'untyped' : Util.module_name(a.klass)
|
163
167
|
type_optional = optional(type)
|
164
168
|
# @type var methods: Array[String]
|
165
169
|
methods = []
|
166
|
-
methods << "def #{a.name}: () -> #{type}"
|
170
|
+
methods << "def #{a.name}: () -> #{is_optional ? type_optional : type}"
|
167
171
|
methods << "def #{a.name}=: (#{type_optional}) -> #{type_optional}"
|
168
172
|
methods << "def reload_#{a.name}: () -> #{type_optional}"
|
169
173
|
if !a.polymorphic?
|
@@ -186,21 +190,21 @@ module RbsRails
|
|
186
190
|
case reflection.macro
|
187
191
|
when :has_one_attached
|
188
192
|
<<~EOS
|
189
|
-
def #{name}: () -> ActiveStorage::Attached::One
|
190
|
-
def #{name}=: (ActionDispatch::Http::UploadedFile) -> ActionDispatch::Http::UploadedFile
|
191
|
-
| (Rack::Test::UploadedFile) -> Rack::Test::UploadedFile
|
192
|
-
| (ActiveStorage::Blob) -> ActiveStorage::Blob
|
193
|
-
| (String) -> String
|
194
|
-
| ({ io: IO, filename: String, content_type: String? }) -> { io: IO, filename: String, content_type: String? }
|
193
|
+
def #{name}: () -> ::ActiveStorage::Attached::One
|
194
|
+
def #{name}=: (::ActionDispatch::Http::UploadedFile) -> ::ActionDispatch::Http::UploadedFile
|
195
|
+
| (::Rack::Test::UploadedFile) -> ::Rack::Test::UploadedFile
|
196
|
+
| (::ActiveStorage::Blob) -> ::ActiveStorage::Blob
|
197
|
+
| (::String) -> ::String
|
198
|
+
| ({ io: ::IO, filename: ::String, content_type: ::String? }) -> { io: ::IO, filename: ::String, content_type: ::String? }
|
195
199
|
| (nil) -> nil
|
196
200
|
EOS
|
197
201
|
when :has_many_attached
|
198
202
|
<<~EOS
|
199
|
-
def #{name}: () -> ActiveStorage::Attached::Many
|
203
|
+
def #{name}: () -> ::ActiveStorage::Attached::Many
|
200
204
|
def #{name}=: (untyped) -> untyped
|
201
205
|
EOS
|
202
206
|
else
|
203
|
-
raise
|
207
|
+
raise "unknown macro: #{reflection.macro}"
|
204
208
|
end
|
205
209
|
end.join("\n")
|
206
210
|
sigs << "end"
|
@@ -316,7 +320,7 @@ module RbsRails
|
|
316
320
|
methods = []
|
317
321
|
enum_definitions.each do |hash|
|
318
322
|
hash.each do |name, values|
|
319
|
-
next if name
|
323
|
+
next if IGNORED_ENUM_KEYS.include?(name)
|
320
324
|
|
321
325
|
values.each do |label, value|
|
322
326
|
value_method_name = enum_method_name(hash, name, label)
|
@@ -334,7 +338,7 @@ module RbsRails
|
|
334
338
|
methods = []
|
335
339
|
enum_definitions.each do |hash|
|
336
340
|
hash.each do |name, values|
|
337
|
-
next if name
|
341
|
+
next if IGNORED_ENUM_KEYS.include?(name)
|
338
342
|
|
339
343
|
values.each do |label, value|
|
340
344
|
value_method_name = enum_method_name(hash, name, label)
|
@@ -456,7 +460,7 @@ module RbsRails
|
|
456
460
|
private def parse_model_file
|
457
461
|
return @parse_model_file if defined?(@parse_model_file)
|
458
462
|
|
459
|
-
path = Rails.root.join('app/models/', klass_name.underscore + '.rb')
|
463
|
+
path = Rails.root.join('app/models/', klass_name(abs: false).underscore + '.rb')
|
460
464
|
return @parse_model_file = nil unless path.exist?
|
461
465
|
return [] unless path.exist?
|
462
466
|
|
@@ -467,24 +471,32 @@ module RbsRails
|
|
467
471
|
end
|
468
472
|
|
469
473
|
private def traverse(node, &block)
|
470
|
-
return to_enum(__method__ || raise, node) unless
|
474
|
+
return to_enum(__method__ || raise, node) unless block
|
471
475
|
|
472
|
-
# @type var block: ^(Parser::AST::Node) -> untyped
|
473
476
|
block.call node
|
474
477
|
node.children.each do |child|
|
475
478
|
traverse(child, &block) if child.is_a?(Parser::AST::Node)
|
476
479
|
end
|
477
480
|
end
|
478
481
|
|
479
|
-
private def relation_class_name
|
480
|
-
"ActiveRecord_Relation"
|
482
|
+
private def relation_class_name(abs: true)
|
483
|
+
abs ? "#{klass_name}::ActiveRecord_Relation" : "ActiveRecord_Relation"
|
484
|
+
end
|
485
|
+
|
486
|
+
private def klass_name(abs: true)
|
487
|
+
abs ? "::#{@klass_name}" : @klass_name
|
481
488
|
end
|
482
489
|
|
490
|
+
private def generated_relation_methods_name(abs: true)
|
491
|
+
abs ? "#{klass_name}::GeneratedRelationMethods" : "GeneratedRelationMethods"
|
492
|
+
end
|
493
|
+
|
494
|
+
|
483
495
|
private def columns
|
484
496
|
mod_sig = +"module GeneratedAttributeMethods\n"
|
485
497
|
mod_sig << klass.columns.map do |col|
|
486
498
|
class_name = if enum_definitions.any? { |hash| hash.key?(col.name) || hash.key?(col.name.to_sym) }
|
487
|
-
'String'
|
499
|
+
'::String'
|
488
500
|
else
|
489
501
|
sql_type_to_class(col.type)
|
490
502
|
end
|
@@ -499,12 +511,12 @@ module RbsRails
|
|
499
511
|
def #{col.name}_will_change!: () -> void
|
500
512
|
def #{col.name}_was: () -> #{class_name_opt}
|
501
513
|
def #{col.name}_previously_changed?: () -> bool
|
502
|
-
def #{col.name}_previous_change: () -> Array[#{class_name_opt}]?
|
514
|
+
def #{col.name}_previous_change: () -> ::Array[#{class_name_opt}]?
|
503
515
|
def #{col.name}_previously_was: () -> #{class_name_opt}
|
504
516
|
def #{col.name}_before_last_save: () -> #{class_name_opt}
|
505
|
-
def #{col.name}_change_to_be_saved: () -> Array[#{class_name_opt}]?
|
517
|
+
def #{col.name}_change_to_be_saved: () -> ::Array[#{class_name_opt}]?
|
506
518
|
def #{col.name}_in_database: () -> #{class_name_opt}
|
507
|
-
def saved_change_to_#{col.name}: () -> Array[#{class_name_opt}]?
|
519
|
+
def saved_change_to_#{col.name}: () -> ::Array[#{class_name_opt}]?
|
508
520
|
def saved_change_to_#{col.name}?: () -> bool
|
509
521
|
def will_save_change_to_#{col.name}?: () -> bool
|
510
522
|
def restore_#{col.name}!: () -> void
|
@@ -525,25 +537,25 @@ module RbsRails
|
|
525
537
|
private def sql_type_to_class(t)
|
526
538
|
case t
|
527
539
|
when :integer
|
528
|
-
'Integer'
|
540
|
+
'::Integer'
|
529
541
|
when :float
|
530
|
-
'Float'
|
542
|
+
'::Float'
|
531
543
|
when :decimal
|
532
|
-
'BigDecimal'
|
544
|
+
'::BigDecimal'
|
533
545
|
when :string, :text, :citext, :uuid, :binary
|
534
|
-
'String'
|
546
|
+
'::String'
|
535
547
|
when :datetime
|
536
|
-
'ActiveSupport::TimeWithZone'
|
548
|
+
'::ActiveSupport::TimeWithZone'
|
537
549
|
when :boolean
|
538
550
|
"bool"
|
539
551
|
when :jsonb, :json
|
540
552
|
"untyped"
|
541
553
|
when :date
|
542
|
-
'Date'
|
554
|
+
'::Date'
|
543
555
|
when :time
|
544
|
-
'Time'
|
556
|
+
'::Time'
|
545
557
|
when :inet
|
546
|
-
"IPAddr"
|
558
|
+
"::IPAddr"
|
547
559
|
else
|
548
560
|
# Unknown column type, give up
|
549
561
|
'untyped'
|
@@ -551,7 +563,7 @@ module RbsRails
|
|
551
563
|
end
|
552
564
|
|
553
565
|
private
|
554
|
-
attr_reader :klass
|
566
|
+
attr_reader :klass
|
555
567
|
end
|
556
568
|
end
|
557
569
|
end
|
@@ -10,7 +10,7 @@ module RbsRails
|
|
10
10
|
def build
|
11
11
|
dep_rbs = +""
|
12
12
|
deps.uniq!
|
13
|
-
while dep =
|
13
|
+
while dep = shift
|
14
14
|
next unless done.add?(dep)
|
15
15
|
|
16
16
|
case dep_object = Object.const_get(dep)
|
@@ -39,5 +39,9 @@ module RbsRails
|
|
39
39
|
Util.format_rbs(dep_rbs)
|
40
40
|
end
|
41
41
|
end
|
42
|
+
|
43
|
+
private def shift
|
44
|
+
deps.shift&.sub(/^::/, '')
|
45
|
+
end
|
42
46
|
end
|
43
47
|
end
|
data/lib/rbs_rails/rake_task.rb
CHANGED
@@ -3,17 +3,17 @@ require 'rake/tasklib'
|
|
3
3
|
|
4
4
|
module RbsRails
|
5
5
|
class RakeTask < Rake::TaskLib
|
6
|
-
attr_accessor :ignore_model_if, :name
|
6
|
+
attr_accessor :ignore_model_if, :name
|
7
|
+
attr_writer :signature_root_dir
|
7
8
|
|
8
9
|
def initialize(name = :rbs_rails, &block)
|
9
10
|
super()
|
10
11
|
|
11
12
|
@name = name
|
13
|
+
@signature_root_dir = Rails.root / 'sig/rbs_rails'
|
12
14
|
|
13
15
|
block.call(self) if block
|
14
16
|
|
15
|
-
setup_signature_root_dir!
|
16
|
-
|
17
17
|
def_generate_rbs_for_models
|
18
18
|
def_generate_rbs_for_path_helpers
|
19
19
|
def_all
|
@@ -64,10 +64,10 @@ module RbsRails
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
private def
|
68
|
-
@signature_root_dir
|
69
|
-
|
70
|
-
|
67
|
+
private def signature_root_dir
|
68
|
+
Pathname(@signature_root_dir).tap do |dir|
|
69
|
+
dir.mkpath
|
70
|
+
end
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|
data/lib/rbs_rails/util.rb
CHANGED
@@ -4,19 +4,23 @@ module RbsRails
|
|
4
4
|
|
5
5
|
extend self
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
else
|
13
|
-
def module_name(mod)
|
14
|
-
MODULE_NAME.bind(mod).call
|
15
|
-
end
|
7
|
+
def module_name(mod, abs: true)
|
8
|
+
name = MODULE_NAME.bind_call(mod)
|
9
|
+
name ="::#{name}" if abs
|
10
|
+
name
|
16
11
|
end
|
17
12
|
|
18
13
|
def format_rbs(rbs)
|
19
|
-
decls =
|
14
|
+
decls =
|
15
|
+
if Gem::Version.new('3') <= Gem::Version.new(RBS::VERSION)
|
16
|
+
parsed = _ = RBS::Parser.parse_signature(rbs)
|
17
|
+
parsed[1] + parsed[2]
|
18
|
+
else
|
19
|
+
# TODO: Remove this type annotation when rbs_rails drops support of RBS 2.x.
|
20
|
+
# @type var parsed: [RBS::Declarations::t]
|
21
|
+
parsed = _ = RBS::Parser.parse_signature(rbs)
|
22
|
+
end
|
23
|
+
|
20
24
|
StringIO.new.tap do |io|
|
21
25
|
RBS::Writer.new(out: io).write(decls)
|
22
26
|
end.string
|
data/lib/rbs_rails/version.rb
CHANGED