orthoses-rails 0.9.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -65
  3. data/lib/generators/orthoses/rails/install_generator.rb +18 -0
  4. data/lib/orthoses/active_record/belongs_to.rb +15 -4
  5. data/lib/orthoses/active_record/enum.rb +5 -0
  6. data/lib/orthoses/active_record/generated_attribute_methods.rb +47 -55
  7. data/lib/orthoses/active_record/has_many.rb +15 -4
  8. data/lib/orthoses/active_record/has_one.rb +12 -2
  9. data/lib/orthoses/active_record/relation.rb +56 -0
  10. data/lib/orthoses/active_record.rb +36 -0
  11. data/lib/orthoses/active_support/delegation.rb +17 -6
  12. data/lib/orthoses/active_support/time_with_zone.rb +20 -19
  13. data/lib/orthoses/rails/application.rb +33 -0
  14. data/lib/orthoses/rails/version.rb +1 -1
  15. data/lib/orthoses/rails.rb +3 -2
  16. metadata +8 -45
  17. data/examples/rails/Gemfile +0 -16
  18. data/examples/rails/Gemfile.lock +0 -179
  19. data/examples/rails/Rakefile +0 -328
  20. data/examples/rails/config/database.yml +0 -8
  21. data/examples/rails/config/storage.yml +0 -3
  22. data/examples/rails/known_sig/actionpack/7.0/action_controller/metal.rbs +0 -4
  23. data/examples/rails/known_sig/activemodel/7.0/active_model/serialization.rbs +0 -4
  24. data/examples/rails/known_sig/activemodel/7.0/active_model/validations.rbs +0 -4
  25. data/examples/rails/known_sig/activerecord/6.0/_active_record_relation.rbs +0 -49
  26. data/examples/rails/known_sig/activerecord/6.0/_active_record_relation_class_methods.rbs +0 -45
  27. data/examples/rails/known_sig/activerecord/6.0/active_record/result.rbs +0 -5
  28. data/examples/rails/known_sig/activerecord/6.1/_active_record_relation.rbs +0 -49
  29. data/examples/rails/known_sig/activerecord/6.1/_active_record_relation_class_methods.rbs +0 -45
  30. data/examples/rails/known_sig/activerecord/6.1/active_record/result.rbs +0 -5
  31. data/examples/rails/known_sig/activerecord/7.0/_active_record_relation.rbs +0 -49
  32. data/examples/rails/known_sig/activerecord/7.0/_active_record_relation_class_methods.rbs +0 -45
  33. data/examples/rails/known_sig/activerecord/7.0/active_record/encryption/context.rbs +0 -9
  34. data/examples/rails/known_sig/activerecord/7.0/active_record/result.rbs +0 -5
  35. data/examples/rails/known_sig/activesupport/7.0/active_support/callbacks/callback_chain.rbs +0 -9
  36. data/examples/rails/known_sig/activesupport/7.0/active_support/duration.rbs +0 -4
  37. data/examples/rails/known_sig/activesupport/7.0/active_support/hash_with_indifferent_access.rbs +0 -6
  38. data/examples/rails/known_sig/activesupport/7.0/active_support/multibyte/chars.rbs +0 -7
  39. data/examples/rails/known_sig/activesupport/7.0/active_support/time_with_zone.rbs +0 -5
  40. data/examples/rails/known_sig/activesupport/7.0/active_support/time_zone.rbs +0 -3
  41. data/examples/rails/known_sig/activesupport/7.0/date.rbs +0 -6
  42. data/examples/rails/known_sig/activesupport/7.0/date_and_time/zones.rbs +0 -4
  43. data/examples/rails/known_sig/activesupport/7.0/hash_with_indifferent_access.rbs +0 -2
  44. data/examples/rails/known_sig/activesupport/7.0/integer.rbs +0 -9
  45. data/examples/rails/known_sig/activesupport/7.0/numeric.rbs +0 -15
  46. data/examples/rails/known_sig/activesupport/7.0/string.rbs +0 -4
  47. data/examples/rails/known_sig/activesupport/7.0/time.rbs +0 -46
  48. data/examples/rails/tasks/action_pack.rake +0 -141
  49. data/examples/rails/tasks/action_view.rake +0 -77
  50. data/examples/rails/tasks/active_job.rake +0 -99
  51. data/examples/rails/tasks/active_model.rake +0 -46
  52. data/examples/rails/tasks/active_record.rake +0 -88
  53. data/examples/rails/tasks/active_storage.rake +0 -94
  54. data/examples/rails/tasks/active_support.rake +0 -99
  55. data/examples/rails/tasks/railties.rake +0 -34
  56. data/orthoses-rails.gemspec +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a43ce53af9e7aec6ef02751c5649146d817e76770a9b15bb2fb5a24fa1b0447b
4
- data.tar.gz: 83c78756ff7794059a1001902f887509d8be7b42f116a2ce30b1cdb27d75ff6a
3
+ metadata.gz: 620d49df1787f2c79e641435da0cf872d0d8604930729bc746a72ec787677b78
4
+ data.tar.gz: fc06f6c06c7941f5ca36bbc1aabf6730e641e7cac2ea2a4f7ee1242284ebb4de
5
5
  SHA512:
6
- metadata.gz: bce1abdf1faf93222005ba51aa4c74675fc98edef98a546faecd52280bf03ce11dc896379ab7269c3c7bda3be43eddae81cf01ab6fc701e8a2e96d4f841dd7b8
7
- data.tar.gz: be065396c52d757e110c2668e5eb90ada5f58275376bc93f0e9e4d25be4968735bccae5ace6d2ad7e08c8642b75b1ff5f5bd63b93c4019faba66101f1de34757
6
+ metadata.gz: 63e8a69d07faab3bda23d71df987b87352e245b46d14cf824576c2a66502ad95e2523bc8f11eb8030e3325707b7b9b8e2e28103c560dba01bb0234ecf23fb54c
7
+ data.tar.gz: 13fd887d6564a51e19a0cdea17b80b5d3cfedd5a56f4096c1ec44a27dca3ba3e6a57c34dd22aa069a808fea34ec2eab1f265f0fa7d42f1394f8c00937642eb03
data/README.md CHANGED
@@ -3,38 +3,19 @@
3
3
  [Orthoses](https://github.com/ksss/orthoses) extension for Ruby on Rails.
4
4
  Orthoses::Rails automatically generates RBS for methods added by Rails.
5
5
 
6
- ## Features
7
-
8
- ### Orthoses::ActiveModel
9
-
10
- - `HasSecurePassword`
11
- - Add signatures that generated form `has_secure_password`.
12
-
13
- ### Orthoses::ActiveRecord
14
-
15
- - `BelongsTo`
16
- - Add signatures that generated form `belongs_to`.
17
- - `DelegatedType`
18
- - Add signatures that generated from `delegated_type`
19
- - `Enum`
20
- - Add signatures that generated from `enum`
21
- - `HasMany`
22
- - Add signatures that generated form `has_many`.
23
- - `HasOne`
24
- - Add signatures that generated form `has_one`.
25
- - `Scope`
26
- - Add signatures that generated form `scope`.
27
-
28
- ### Orthoses::ActiveSupport
29
-
30
- - `ClassAttribute`
31
- - Add signatures that generated form `class_attribute`.
32
- - `Configurable`
33
- - Add signatures that generated from `config_accessor`
34
- - `Delegation`
35
- - Add signatures that generated from `delegate`. The type definition of the method or instance variable specified by `to` is required.
36
- - `MattrAccessor`
37
- - Add signatures that generated form `mattr_accessor`, `cattr_accessor`, `mattr_reader`, `cattr_reader`, `mattr_writer` and `cattr_writer`.
6
+ ## Usage
7
+
8
+ Build your Rake task for RBS generation.
9
+
10
+ ```rb
11
+ $ bin/rails generate orthoses:rails:install
12
+ ```
13
+
14
+ Then run the rake task.
15
+
16
+ ```
17
+ $ bin/rails orthoses:rails
18
+ ```
38
19
 
39
20
  ## Installation
40
21
 
@@ -46,39 +27,6 @@ If bundler is not being used to manage dependencies, install the gem by executin
46
27
 
47
28
  $ gem install orthoses-rails
48
29
 
49
- ## Usage
50
-
51
- Build your Rake task for RBS generation.
52
-
53
- ```rb
54
- task :rbs_generate => :environment do
55
- Orthoses::Builder.new do
56
- use Orthoses::CreateFileByName
57
- base_dir: Rails.root.join("sig/out"),
58
- header: "# !!! GENERATED CODE !!!"
59
- use Orthoses::Filter do |name, _content|
60
- path, _lineno = Object.const_source_location(name)
61
- return false unless path
62
- %r{app/models}.match?(path)
63
- end
64
- use YourCustom::Middleware
65
- use Orthoses::ActiveModel::HasSecurePassword
66
- use Orthoses::ActiveRecord::BelongsTo
67
- use Orthoses::ActiveRecord::HasMany
68
- use Orthoses::ActiveRecord::HasOne
69
- use Orthoses::ActiveSupport::ClassAttribute
70
- use Orthoses::ActiveSupport::MattrAccessor
71
- use Orthoses::Mixin
72
- use Orthoses::Constant, strict: false
73
- use Orthoses::ObjectSpaceAll
74
- use Orthoses::Autoload
75
- run -> {
76
- Rails.application.eager_load!
77
- }
78
- end.call
79
- end
80
- ```
81
-
82
30
  ## Development
83
31
 
84
32
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/base'
4
+ require 'orthoses/rails'
5
+
6
+ module Orthoses
7
+ module Rails
8
+ module Generators
9
+ class InstallGenerator < ::Rails::Generators::Base
10
+ source_root File.expand_path('templates', __dir__)
11
+
12
+ def copy_rake_task_file
13
+ copy_file "rails.rake", "lib/tasks/orthoses/rails.rake"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -15,7 +15,19 @@ module Orthoses
15
15
 
16
16
  lines = base.reflect_on_all_associations(:belongs_to).flat_map do |ref|
17
17
  # FIXME: Can I get list of class for polymorphic?
18
- type = ref.polymorphic? ? 'untyped' : ref.klass.to_s
18
+ type = if ref.polymorphic?
19
+ 'untyped'
20
+ else
21
+ begin
22
+ Utils.module_name(ref.klass) or next
23
+ rescue NameError => e
24
+ while e
25
+ Orthoses.logger.warn(e.message)
26
+ e = e.cause
27
+ end
28
+ next
29
+ end
30
+ end
19
31
  opt = "#{type}?"
20
32
 
21
33
  [
@@ -38,9 +50,8 @@ module Orthoses
38
50
  content.concat(lines)
39
51
  end
40
52
 
41
- store[base_name].tap do |content|
42
- store[base_name] << "include #{generated_association_methods}"
43
- end
53
+ sig = "include #{generated_association_methods}"
54
+ store[base_name] << sig if !store[base_name].body.include?(sig)
44
55
  end
45
56
  end
46
57
  end
@@ -20,6 +20,11 @@ module Orthoses
20
20
  enum.captures.each do |capture|
21
21
  base_name = Utils.module_name(capture.method.receiver) or next
22
22
 
23
+ sig = "include #{base_name}::ActiveRecord_Enum_EnumMethods"
24
+ if !store[base_name].body.include?(sig)
25
+ store[base_name] << sig
26
+ end
27
+
23
28
  if capture.argument[:definitions]
24
29
  # on rails 6
25
30
  definitions = capture.argument[:definitions].slice!(:_prefix, :_suffix, :_scopes, :_default)
@@ -3,6 +3,30 @@
3
3
  module Orthoses
4
4
  module ActiveRecord
5
5
  class GeneratedAttributeMethods
6
+ TARGET_TYPE_MAP = {
7
+ "attribute" => "() -> %<type>s",
8
+ "attribute=" => "(%<type>s) -> %<type>s",
9
+ "attribute?" => "() -> bool",
10
+ "attribute_before_last_save" => "() -> %<opt>s",
11
+ "attribute_before_type_cast" => "() -> %<type>s",
12
+ "attribute_came_from_user?" => "() -> bool",
13
+ "attribute_change" => "() -> [%<opt>s, %<opt>s]",
14
+ "attribute_change_to_be_saved" => "() -> Array[%<opt>s]?",
15
+ "attribute_changed?" => "() -> bool",
16
+ "attribute_for_database" => "() -> %<type>s",
17
+ "attribute_in_database" => "() -> %<opt>s",
18
+ "attribute_previous_change" => "() -> Array[%<opt>s]?",
19
+ "attribute_previously_changed?" => "() -> bool",
20
+ "attribute_previously_was" => "() -> %<opt>s",
21
+ "attribute_was" => "() -> %<opt>s",
22
+ "attribute_will_change!" => "() -> void",
23
+ "clear_attribute_change" => "() -> void",
24
+ "restore_attribute!" => "() -> void",
25
+ "saved_change_to_attribute" => "() -> Array[%<opt>s]?",
26
+ "saved_change_to_attribute?" => "() -> bool",
27
+ "will_save_change_to_attribute?" => "() -> bool",
28
+ }
29
+
6
30
  def initialize(loader)
7
31
  @loader = loader
8
32
  end
@@ -12,71 +36,39 @@ module Orthoses
12
36
  ::ActiveRecord::Base.descendants.each do |klass|
13
37
  next if klass.abstract_class?
14
38
 
15
- name = Utils.module_name(klass) || next
16
- lines = klass.columns.flat_map do |col|
17
- req = sql_type_to_rbs(col.type)
39
+ base_klass_name = Utils.module_name(klass) || next
40
+ begin
41
+ klass.columns
42
+ rescue ::ActiveRecord::StatementInvalid => e
43
+ Orthoses.logger.warn(e.to_s)
44
+ next
45
+ end
46
+
47
+ lines = []
48
+ klass.columns_hash.each do |name, col|
49
+ req = ActiveRecord.sql_type_to_rbs(col.type)
18
50
  opt = "#{req}?"
19
51
  type = col.null ? opt : req
20
52
 
21
- [
22
- "def #{col.name}: () -> #{type}",
23
- "def #{col.name}=: (#{type}) -> #{type}",
24
- "def #{col.name}?: () -> bool",
25
- "def #{col.name}_changed?: () -> bool",
26
- "def #{col.name}_change: () -> [#{opt}, #{opt}]",
27
- "def #{col.name}_will_change!: () -> void",
28
- "def #{col.name}_was: () -> #{opt}",
29
- "def #{col.name}_previously_changed?: () -> bool",
30
- "def #{col.name}_previous_change: () -> Array[#{opt}]?",
31
- "def #{col.name}_previously_was: () -> #{opt}",
32
- "def #{col.name}_before_last_save: () -> #{opt}",
33
- "def #{col.name}_change_to_be_saved: () -> Array[#{opt}]?",
34
- "def #{col.name}_in_database: () -> #{opt}",
35
- "def saved_change_to_#{col.name}: () -> Array[#{opt}]?",
36
- "def saved_change_to_#{col.name}?: () -> bool",
37
- "def will_save_change_to_#{col.name}?: () -> bool",
38
- "def restore_#{col.name}!: () -> void",
39
- "def clear_#{col.name}_change: () -> void",
40
- ]
53
+ ::ActiveRecord::Base.attribute_method_matchers.each do |matcher|
54
+ tmpl = TARGET_TYPE_MAP[matcher.target]
55
+ lines << "def #{matcher.method_name(name)}: #{tmpl % {type: type, opt: opt}}"
56
+ end
57
+ end
58
+ klass.attribute_aliases.each do |alias_name, column_name|
59
+ ::ActiveRecord::Base.attribute_method_matchers.each do |matcher|
60
+ lines << "alias #{matcher.method_name(alias_name)} #{matcher.method_name(column_name)}"
61
+ end
41
62
  end
42
- generated_attribute_methods = "#{name}::AttributeMethods::GeneratedAttributeMethods"
43
- store[name] << "include #{generated_attribute_methods}"
44
63
 
45
- store["#{name}::AttributeMethods"].header = "module #{name}::AttributeMethods"
64
+ generated_attribute_methods = "#{base_klass_name}::GeneratedAttributeMethods"
65
+ store[base_klass_name] << "include #{generated_attribute_methods}"
66
+
46
67
  store[generated_attribute_methods].header = "module #{generated_attribute_methods}"
47
68
  store[generated_attribute_methods].concat(lines)
48
69
  end
49
70
  end
50
71
  end
51
-
52
- # Thanks https://github.com/pocke/rbs_rails/blob/8a128a8d29f0861aa2c25aa4110ff7c2ea674865/lib/rbs_rails/active_record.rb#L525-L551
53
- def sql_type_to_rbs(t)
54
- case t
55
- when :integer
56
- 'Integer'
57
- when :float
58
- 'Float'
59
- when :decimal
60
- 'BigDecimal'
61
- when :string, :text, :citext, :uuid, :binary
62
- 'String'
63
- when :datetime
64
- 'ActiveSupport::TimeWithZone'
65
- when :boolean
66
- "bool"
67
- when :jsonb, :json
68
- "untyped"
69
- when :date
70
- 'Date'
71
- when :time
72
- 'Time'
73
- when :inet
74
- "IPAddr"
75
- else
76
- # Unknown column type, give up
77
- 'untyped'
78
- end
79
- end
80
72
  end
81
73
  end
82
74
  end
@@ -13,14 +13,23 @@ module Orthoses
13
13
  next if base.abstract_class?
14
14
  base_name = Utils.module_name(base) || next
15
15
 
16
- collection_proxy = "#{base_name}::ActiveRecord_Associations_CollectionProxy"
17
-
18
16
  lines = base.reflect_on_all_associations(:has_many).flat_map do |ref|
19
17
  singular_name = ref.name.to_s.singularize
18
+ type =
19
+ begin
20
+ Utils.module_name(ref.klass)
21
+ rescue NameError => e
22
+ while e
23
+ Orthoses.logger.warn(e.message)
24
+ e = e.cause
25
+ end
26
+ next
27
+ end
20
28
 
29
+ collection_proxy = "::#{type}::ActiveRecord_Associations_CollectionProxy"
21
30
  [
22
31
  "def #{ref.name}: () -> #{collection_proxy}",
23
- "def #{ref.name}=: (#{collection_proxy} | Array[#{ref.klass}]) -> (#{collection_proxy} | Array[#{ref.klass}])",
32
+ "def #{ref.name}=: (#{collection_proxy} | Array[#{type}]) -> (#{collection_proxy} | Array[#{type}])",
24
33
  "def #{singular_name}_ids: () -> Array[Integer]",
25
34
  "def #{singular_name}_ids=: (Array[Integer]) -> Array[Integer]",
26
35
  ]
@@ -29,7 +38,9 @@ module Orthoses
29
38
  generated_association_methods = "#{base_name}::GeneratedAssociationMethods"
30
39
  store[generated_association_methods].header = "module #{generated_association_methods}"
31
40
  store[generated_association_methods].concat(lines)
32
- store[base_name] << "include #{generated_association_methods}"
41
+
42
+ sig = "include #{generated_association_methods}"
43
+ store[base_name] << sig if !store[base_name].body.include?(sig)
33
44
  end
34
45
  end
35
46
  end
@@ -14,7 +14,16 @@ module Orthoses
14
14
  base_name = Utils.module_name(base) || next
15
15
 
16
16
  lines = base.reflect_on_all_associations(:has_one).flat_map do |ref|
17
- type = ref.klass.to_s
17
+ type =
18
+ begin
19
+ Utils.module_name(ref.klass) or next
20
+ rescue NameError => e
21
+ while e
22
+ Orthoses.logger.warn(e.message)
23
+ e = e.cause
24
+ end
25
+ next
26
+ end
18
27
  opt = "#{type}?"
19
28
 
20
29
  [
@@ -31,7 +40,8 @@ module Orthoses
31
40
  store[generated_association_methods].header = "module #{generated_association_methods}"
32
41
  store[generated_association_methods].concat(lines)
33
42
 
34
- store[base_name] << "include #{generated_association_methods}"
43
+ sig = "include #{generated_association_methods}"
44
+ store[base_name] << sig if !store[base_name].body.include?(sig)
35
45
  end
36
46
  end
37
47
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orthoses
4
+ module ActiveRecord
5
+ class Relation
6
+ def initialize(loader)
7
+ @loader = loader
8
+ end
9
+
10
+ def call
11
+ @loader.call.tap do |store|
12
+ ::ActiveRecord::Base.descendants.each do |klass|
13
+ next if klass.abstract_class?
14
+
15
+ primary_key = fetch_primary_key(klass)
16
+
17
+ model_name = Utils.module_name(klass) or next
18
+ class_specific_relation = "#{model_name}::ActiveRecord_Relation"
19
+ class_specific_proxy = "#{model_name}::ActiveRecord_Associations_CollectionProxy"
20
+ class_specific_generated_relation_methods = "#{model_name}::GeneratedRelationMethods"
21
+
22
+ store[class_specific_generated_relation_methods].tap do |c|
23
+ end
24
+
25
+ store[class_specific_relation].tap do |c|
26
+ c.header = "class #{class_specific_relation} < ::ActiveRecord::Relation"
27
+ c << "include #{class_specific_generated_relation_methods}"
28
+ c << "include _ActiveRecord_Relation[#{model_name}, #{primary_key}]"
29
+ c << "include Enumerable[#{model_name}]"
30
+ end
31
+
32
+ store[class_specific_proxy].tap do |c|
33
+ c.header = "class #{class_specific_proxy} < ::ActiveRecord::Associations::CollectionProxy"
34
+ c << "include _ActiveRecord_Relation[#{model_name}, #{primary_key}]"
35
+ end
36
+
37
+ store[model_name].tap do |c|
38
+ c << "extend _ActiveRecord_Relation_ClassMethods[#{model_name}, #{class_specific_relation}, #{primary_key}]"
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def fetch_primary_key(klass)
47
+ type = klass.type_for_attribute(klass.primary_key).type
48
+ ActiveRecord.sql_type_to_rbs(type)
49
+ rescue ::ActiveRecord::StatementInvalid => e
50
+ Orthoses.logger.warn(e.to_s)
51
+ "untyped"
52
+ end
53
+ end
54
+ end
55
+ end
56
+
@@ -7,4 +7,40 @@ require_relative 'active_record/generated_attribute_methods'
7
7
  require_relative 'active_record/has_many'
8
8
  require_relative 'active_record/has_one'
9
9
  require_relative 'active_record/query_methods'
10
+ require_relative 'active_record/relation'
10
11
  require_relative 'active_record/scope'
12
+
13
+ module Orthoses
14
+ module ActiveRecord
15
+ # Thanks https://github.com/pocke/rbs_rails/blob/8a128a8d29f0861aa2c25aa4110ff7c2ea674865/lib/rbs_rails/active_record.rb#L525-L551
16
+ def self.sql_type_to_rbs(t)
17
+ case t
18
+ when :integer, :big_integer
19
+ '::Integer'
20
+ when :float
21
+ '::Float'
22
+ when :decimal
23
+ '::BigDecimal'
24
+ when :string, :text, :citext, :uuid, :binary, :immutable_string
25
+ '::String'
26
+ when :datetime
27
+ '::ActiveSupport::TimeWithZone'
28
+ when :boolean
29
+ "bool"
30
+ when :date
31
+ '::Date'
32
+ when :time
33
+ '::Time'
34
+ when :cidr, :inet
35
+ "::IPAddr"
36
+ when :bit, :bit_varying, :enum, :hstore,
37
+ :interval, :jsonb, :json, :legacy_point, :money, :point, :vector, :xml
38
+ # FIXME
39
+ 'untyped'
40
+ else
41
+ # Unknown column type, give up
42
+ 'untyped'
43
+ end
44
+ end
45
+ end
46
+ end
@@ -20,14 +20,16 @@ module Orthoses
20
20
  delegate.captures.each do |capture|
21
21
  receiver_name = Utils.module_name(capture.method.receiver) or next
22
22
  receiver_content = store[receiver_name]
23
+ prefix = capture.argument[:private] ? "private " : ""
23
24
 
24
25
  case capture.argument[:to]
26
+ # delegate :foo, to: Foo
25
27
  when Module
26
28
  to_module_name = Utils.module_name(capture.argument[:to]) or next
27
29
  capture.argument[:methods].each do |arg|
28
30
  if sig = resource.build_signature(to_module_name, arg, :singleton, false)
29
31
  receiver_content << "# defined by `delegate` to: #{to_module_name}"
30
- receiver_content << sig
32
+ receiver_content << "#{prefix}#{sig}"
31
33
  else
32
34
  Orthoses.logger.warn("[ActiveSupport::Delegation] Ignore since missing type for #{to_module_name}.#{arg.inspect} in #{capture.argument.inspect}")
33
35
  end
@@ -35,20 +37,28 @@ module Orthoses
35
37
  else
36
38
  to_name = capture.argument[:to].to_s.to_sym
37
39
  tag, to_return_type = resource.find(receiver_name, to_name, :instance, false)
38
- raise "bug" if tag == :multi
40
+ if tag == :multi
41
+ to_return_type = if to_return_type.length == 1
42
+ to_return_type.first.type.return_type
43
+ else
44
+ nil
45
+ end
46
+ end
39
47
 
40
48
  case to_return_type
41
49
  when nil, RBS::Types::Bases::Any
50
+ # no type found
42
51
  capture.argument[:methods].each do |method|
43
52
  receiver_content << "# defined by `delegate` to: #{to_return_type}##{to_name}"
44
- receiver_content << "def #{method}: (*untyped, **untyped) -> untyped"
53
+ receiver_content << "#{prefix}def #{method}: (*untyped, **untyped) -> untyped"
45
54
  end
46
55
  else
56
+ # found return type in store or env
47
57
  to_typename = to_return_type.name.relative!.to_s
48
58
  capture.argument[:methods].each do |method|
49
59
  if sig = resource.build_signature(to_typename, method, :instance, true)
50
60
  receiver_content << "# defined by `delegate` to #{to_return_type}##{to_name}"
51
- receiver_content << sig
61
+ receiver_content << "#{prefix}#{sig}"
52
62
  else
53
63
  Orthoses.logger.warn("[ActiveSupport::Delegation] Ignore since missing type for #{to_typename}##{method.inspect} in #{capture.argument.inspect}")
54
64
  end
@@ -73,6 +83,7 @@ module Orthoses
73
83
  typename = TypeName(mod_name).absolute!
74
84
 
75
85
  if definition_method = build_definition(typename, kind)&.methods&.[](name)
86
+ # found in env
76
87
  return [:multi, definition_method.defs.map(&:type)]
77
88
  end
78
89
  resolve_type_by_name(@store[mod_name].to_decl.members, name, kind, argument)
@@ -85,7 +96,7 @@ module Orthoses
85
96
  when :singleton
86
97
  @definition_builder.build_singleton(typename)
87
98
  else
88
- raise "big"
99
+ raise "bug"
89
100
  end
90
101
  rescue RuntimeError => e
91
102
  if e.message.match?(/\AUnknown name for/)
@@ -115,7 +126,7 @@ module Orthoses
115
126
  when RBS::AST::Members::MethodDefinition
116
127
  next unless member.name == name && member.kind == kind
117
128
  if argument
118
- return [:multi, member.types]
129
+ return [:multi, member.overloads.map { |o| o.method_type }]
119
130
  else
120
131
  method_type = member.overloads.map(&:method_type).find do |method_type|
121
132
  method_type.type.required_positionals.empty? && method_type.type.required_keywords.empty?
@@ -13,6 +13,7 @@ module Orthoses
13
13
  store = @loader.call
14
14
 
15
15
  time_with_zone_store = store["ActiveSupport::TimeWithZone"]
16
+ time_with_zone_store.body.replace(filter_decl(time_with_zone_store))
16
17
  each_line_from_core_time_definition(store) do |line|
17
18
  time_with_zone_store << line
18
19
  end
@@ -22,19 +23,21 @@ module Orthoses
22
23
 
23
24
  private
24
25
 
25
- NOT_DELEGATE_METHODS = Set.new(%i[
26
- utc
27
- getgm
28
- getutc
29
- gmtime
30
- localtime
31
- ])
32
-
33
26
  TYPE_MERGE_METHODS = Set.new(%i[
34
27
  +
35
28
  -
36
29
  ])
37
30
 
31
+ def filter_decl(time_with_zone_store)
32
+ writer = RBS::Writer.new(out: StringIO.new)
33
+ time_with_zone_store.to_decl.members.each do |member|
34
+ # ActiveSupport::TimeWithZone.name has been deprecated
35
+ next if member.instance_of?(RBS::AST::Members::MethodDefinition) && member.kind == :singleton && member.name == :name
36
+ writer.write_member(member)
37
+ end
38
+ writer.out.string.each_line.to_a
39
+ end
40
+
38
41
  def add_signature(env, content)
39
42
  buffer, directives, decls = RBS::Parser.parse_signature(content.to_rbs)
40
43
  env.add_signature(buffer: buffer, directives: directives, decls: decls)
@@ -56,35 +59,33 @@ module Orthoses
56
59
  add_signature(env, store["ActiveSupport::TimeWithZone"])
57
60
 
58
61
  builder = RBS::DefinitionBuilder.new(env: env.resolve_type_names)
59
- one_ancestors = builder.ancestor_builder.one_instance_ancestors(type_name_time)
60
- one_ancestors.included_modules.each do |included_module|
61
- yield "include #{included_module.source.name}"
62
- end
63
62
  twz_methods = builder.build_instance(type_name_time_with_zone).methods
64
63
  builder.build_instance(type_name_time).methods.each do |sym, definition_method|
64
+ next if twz_methods.has_key?(sym) && !TYPE_MERGE_METHODS.include?(sym)
65
65
  next if !definition_method.public?
66
+
66
67
  definition_method.defs.reject! do |type_def|
67
68
  type_def.implemented_in != type_name_time
68
69
  end
69
70
  next if definition_method.defs.empty?
70
71
 
71
- if !NOT_DELEGATE_METHODS.include?(sym)
72
- definition_method.method_types.each do |method_type|
73
- rt = method_type.type.return_type
74
- if rt.instance_of?(RBS::Types::ClassInstance) && rt.name.to_s == "::Time"
75
- rt.instance_variable_set(:@name, RBS::Types::Bases::Self.new(location: nil))
76
- end
72
+ definition_method.method_types.each do |method_type|
73
+ rt = method_type.type.return_type
74
+ if rt.instance_of?(RBS::Types::ClassInstance) && rt.name.to_s == "::Time"
75
+ rt.instance_variable_set(:@name, RBS::Types::Bases::Self.new(location: nil))
77
76
  end
78
77
  end
79
78
 
80
79
  if definition_method.alias_of.nil?
81
80
  method_types = definition_method.method_types
82
81
 
82
+ # merge method types (e.g. :+, :-
83
+ # TimeWithZone -delegate-> Time(core_ext) -delegate-> Time(core)
83
84
  if TYPE_MERGE_METHODS.include?(sym)
84
85
  if twz_definition_method = twz_methods[sym]
85
86
  twz_definition_method.defs.each do |type_def|
86
87
  if type_def.implemented_in == type_name_time_with_zone
87
- method_types << type_def.type
88
+ method_types.unshift(type_def.type)
88
89
  end
89
90
  end
90
91
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orthoses
4
+ module Rails
5
+ class Application
6
+ def initialize(loader)
7
+ @loader = loader
8
+ end
9
+
10
+ def call
11
+ loader = @loader
12
+ Orthoses::Builder.new do
13
+ use Orthoses::ActiveModel::HasSecurePassword
14
+ use Orthoses::ActiveRecord::BelongsTo
15
+ use Orthoses::ActiveRecord::DelegatedType
16
+ use Orthoses::ActiveRecord::Enum
17
+ use Orthoses::ActiveRecord::GeneratedAttributeMethods
18
+ use Orthoses::ActiveRecord::HasMany
19
+ use Orthoses::ActiveRecord::HasOne
20
+ use Orthoses::ActiveRecord::Relation
21
+ use Orthoses::ActiveRecord::Scope
22
+
23
+ use Orthoses::ActiveSupport::ClassAttribute
24
+ use Orthoses::ActiveSupport::Concern
25
+ use Orthoses::ActiveSupport::Delegation
26
+ use Orthoses::ActiveSupport::Configurable
27
+ use Orthoses::ActiveSupport::MattrAccessor
28
+ reset_runner loader
29
+ end.call
30
+ end
31
+ end
32
+ end
33
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Orthoses
4
4
  module Rails
5
- VERSION = "0.9.0"
5
+ VERSION = "1.0.0"
6
6
  end
7
7
  end