orthoses 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ee37ddf25be5bbed113698301a2aeafb3b50e7af1da412b9a1fc6afad18d8c2
4
- data.tar.gz: '075957101080441e02f4129303e766ecdfe1e7f30616177bc41a2cbf41f521f8'
3
+ metadata.gz: 843da9ba9bba3cf5c84ec56041836cb9469ad5faffd188f8edc13a3920ca499e
4
+ data.tar.gz: 791b0d87a885b327a41fff090f9dadce9b377712e9d7d51bd52fbaa997c98242
5
5
  SHA512:
6
- metadata.gz: 98c1cff14563ecf14713890e56bddb053d6f128aacad7ff23b6f96cc8b2c338cbea511cc668ac18079ec921cb0183b145f6b26a3c04403a98e8aa0bf734942f7
7
- data.tar.gz: 5dd573a63a6998e3a1fac1dd94f292dd80742185277124f6449ded149be662b74995815bad629157fc553cb8bef15bb31b123fdbcdccb1af3dff4d2645bc0da2
6
+ metadata.gz: 81438b5d94ce56d7164cdc781eaaa2c526cbba21cab147fc91d4e1b0c9b7992e31259d9bda2f5e2441a3dc59e3f7ec940c910e1cf63bbec6ef84ca4b046af0ee
7
+ data.tar.gz: ec0049000f94a194747974233adaa1c51a7759c0d78fb84a11e543877ee15d01f212b59ed63c5cadbd221701de4bfa9c84c0f6fcc5feffdab0f954b1fd63e2d0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- orthoses (1.4.0)
4
+ orthoses (1.5.0)
5
5
  rbs (~> 2.0)
6
6
 
7
7
  GEM
@@ -14,30 +14,30 @@ GEM
14
14
  tzinfo (~> 2.0)
15
15
  ast (2.4.2)
16
16
  concurrent-ruby (1.1.10)
17
- csv (3.2.5)
17
+ csv (3.2.6)
18
18
  ffi (1.15.5)
19
- fileutils (1.6.0)
19
+ fileutils (1.7.0)
20
20
  i18n (1.12.0)
21
21
  concurrent-ruby (~> 1.0)
22
- json (2.6.2)
23
- language_server-protocol (3.17.0.1)
22
+ json (2.6.3)
23
+ language_server-protocol (3.17.0.2)
24
24
  listen (3.7.1)
25
25
  rb-fsevent (~> 0.10, >= 0.10.3)
26
26
  rb-inotify (~> 0.9, >= 0.9.10)
27
- logger (1.5.1)
27
+ logger (1.5.2)
28
28
  minitest (5.16.3)
29
29
  parallel (1.22.1)
30
- parser (3.1.2.1)
30
+ parser (3.1.3.0)
31
31
  ast (~> 2.4.1)
32
32
  rainbow (3.1.1)
33
33
  rake (13.0.6)
34
34
  rb-fsevent (0.11.2)
35
35
  rb-inotify (0.10.1)
36
36
  ffi (~> 1.0)
37
- rbs (2.7.0)
37
+ rbs (2.8.1)
38
38
  rgot (1.1.0)
39
- securerandom (0.2.0)
40
- steep (1.2.1)
39
+ securerandom (0.2.1)
40
+ steep (1.3.0)
41
41
  activesupport (>= 5.1)
42
42
  csv (>= 3.0.9)
43
43
  fileutils (>= 1.1.0)
@@ -48,11 +48,11 @@ GEM
48
48
  parallel (>= 1.0.0)
49
49
  parser (>= 3.1)
50
50
  rainbow (>= 2.2.2, < 4.0)
51
- rbs (>= 2.7.0)
51
+ rbs (>= 2.8.0)
52
52
  securerandom (>= 0.1)
53
53
  strscan (>= 1.0.0)
54
54
  terminal-table (>= 2, < 4)
55
- strscan (3.0.4)
55
+ strscan (3.0.5)
56
56
  terminal-table (3.0.2)
57
57
  unicode-display_width (>= 1.1.1, < 3)
58
58
  tzinfo (2.0.5)
data/README.md CHANGED
@@ -169,6 +169,14 @@ Run `rbs prototype runtime` command process with `patterns` option string.
169
169
 
170
170
  Force load const defined by `autoload`.
171
171
 
172
+ ### Orthoses::Sort
173
+
174
+ Sort signatures by class/module.
175
+
176
+ ## Orthoses::Trace
177
+
178
+ Trace the argument and return value objects when the method is actually called and determine the type.
179
+
172
180
  ## Development
173
181
 
174
182
  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,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rack"
4
+ gem "rake"
5
+ gem "cgi"
6
+ gem "minitest"
7
+ gem "minitest-global_expectations"
8
+ gem "orthoses", path: "../../"
@@ -0,0 +1,30 @@
1
+ PATH
2
+ remote: ../..
3
+ specs:
4
+ orthoses (1.4.0)
5
+ rbs (~> 2.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ cgi (0.3.6)
11
+ minitest (5.16.3)
12
+ minitest-global_expectations (1.0.1)
13
+ minitest (> 5)
14
+ rack (3.0.2)
15
+ rake (13.0.6)
16
+ rbs (2.8.1)
17
+
18
+ PLATFORMS
19
+ arm64-darwin-21
20
+
21
+ DEPENDENCIES
22
+ cgi
23
+ minitest
24
+ minitest-global_expectations
25
+ orthoses!
26
+ rack
27
+ rake
28
+
29
+ BUNDLED WITH
30
+ 2.3.16
@@ -0,0 +1,7 @@
1
+ file :src do
2
+ sh "git clone --depth 1 https://github.com/rack/rack-test.git src"
3
+ end
4
+
5
+ task :generate => :src do
6
+ load "generate.rb"
7
+ end
@@ -0,0 +1,31 @@
1
+ require 'pathname'
2
+ require 'orthoses'
3
+ require 'fileutils'
4
+
5
+ include FileUtils
6
+
7
+ out = Pathname('out')
8
+ out.rmtree rescue nil
9
+ Orthoses.logger.level = :warn
10
+ Orthoses::Builder.new do
11
+ use Orthoses::CreateFileByName,
12
+ base_dir: out.to_s
13
+ # use Orthoses::Sort
14
+ use Orthoses::Filter do |name, content|
15
+ name.start_with?("Rack::Test")
16
+ end
17
+ use Orthoses::Trace,
18
+ patterns: ['Rack::Test*']
19
+ run ->(){
20
+ cd "src" do
21
+ load "spec/all.rb"
22
+ Minitest.run
23
+ # avoid to run on at_exit
24
+ module ::Minitest
25
+ def self.run args = []
26
+ 0
27
+ end
28
+ end
29
+ end
30
+ }
31
+ end.call
@@ -25,13 +25,13 @@ module Orthoses
25
25
  else
26
26
  hash[name] = tp.binding.local_variable_get(name).then do |var|
27
27
  case var
28
- when Module, Thread::Backtrace::Location
28
+ when Module, Thread::Backtrace::Location, IO, Encoding
29
29
  var
30
30
  else
31
31
  var.dup
32
32
  end
33
33
  rescue => err
34
- warn("#dup fail (#{err.class}) #{err.message}")
34
+ warn("#{var.class}#dup failed with #{err.class}:#{err.message}")
35
35
  var
36
36
  end
37
37
  end
@@ -60,12 +60,17 @@ module Orthoses
60
60
  end
61
61
 
62
62
  def uniq!
63
- out = ArrayIO.new
64
- writer = RBS::Writer.new(out: out)
65
- to_decl.members.each do |member|
66
- writer.write_member(member)
67
- end
68
- @body.replace(out.to_a)
63
+ lines = decl_to_lines(to_decl)
64
+ @body.replace(lines)
65
+ end
66
+
67
+ def sort!
68
+ require 'rbs/sorter'
69
+ sorter = ::RBS::Sorter.new(nil, stdout: nil)
70
+ decl = to_decl
71
+ sorter.sort_decl!(decl)
72
+ lines = decl_to_lines(decl)
73
+ @body.replace(lines)
69
74
  end
70
75
 
71
76
  def original_rbs
@@ -93,6 +98,15 @@ module Orthoses
93
98
  end
94
99
  end
95
100
 
101
+ def decl_to_lines(decl)
102
+ out = ArrayIO.new
103
+ writer = RBS::Writer.new(out: out)
104
+ decl.members.each do |member|
105
+ writer.write_member(member)
106
+ end
107
+ out.to_a
108
+ end
109
+
96
110
  def uniqed_body_string
97
111
  out = StringIO.new
98
112
  writer = RBS::Writer.new(out: out)
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orthoses
4
+ # use Orthoses::Sort
5
+ class Sort
6
+ def initialize(loader)
7
+ @loader = loader
8
+ end
9
+
10
+ def call
11
+ @loader.call.tap do |store|
12
+ store.each do |name, content|
13
+ content.sort!
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orthoses
4
+ class Trace
5
+ class Attribute
6
+ include Targetable
7
+
8
+ def initialize(loader, patterns:)
9
+ @loader = loader
10
+ @patterns = patterns
11
+
12
+ @captured_dict = Hash.new { |h, k| h[k] = Hash.new { |hh, kk| hh[kk] = [] } }
13
+ end
14
+
15
+ def call
16
+ ::Module.prepend(Orthoses::Attribute::Hook)
17
+ store = nil
18
+ build_trace_hook.enable(target: Orthoses::Attribute::Hook.instance_method(:attr)) do
19
+ build_trace_hook.enable(target: Orthoses::Attribute::Hook.instance_method(:attr_accessor)) do
20
+ build_trace_hook.enable(target: Orthoses::Attribute::Hook.instance_method(:attr_reader)) do
21
+ build_trace_hook.enable(target: Orthoses::Attribute::Hook.instance_method(:attr_writer)) do
22
+ store = @loader.call
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ @captured_dict.each do |mod_name, captures|
29
+ captures.each do |(kind, prefix, name), types|
30
+ injected = Utils::TypeList.new(types).inject
31
+ store[mod_name] << "#{kind} #{prefix}#{name}: #{injected}"
32
+ end
33
+ end
34
+
35
+ store
36
+ end
37
+
38
+ private
39
+
40
+ def build_trace_hook
41
+ TracePoint.new(:call) do |tp1|
42
+ mod_name = Orthoses::Utils.module_name(tp1.self)
43
+ if m = tp1.self.to_s.match(/#<Class:([\w:]+)>/)
44
+ mod_name = m[1]
45
+ end
46
+ next unless mod_name
47
+ next unless target?(mod_name)
48
+ is_singleton = tp1.self.singleton_class?
49
+ prefix = is_singleton ? "self." : ""
50
+ kind = tp1.method_id
51
+
52
+ tp1.binding.local_variable_get(:names).each do |name|
53
+ attr_module = Module.new{
54
+ if [:attr_accessor, :attr_reader, :attr].include?(kind)
55
+ define_method(name) do
56
+ super()
57
+ end
58
+ end
59
+ if [:attr_accessor, :attr_writer, :attr].include?(kind)
60
+ define_method("#{name}=") do |object|
61
+ super(object)
62
+ end
63
+ end
64
+ }
65
+
66
+ tp1.self.prepend attr_module
67
+
68
+ if [:attr_accessor, :attr_reader, :attr].include?(kind)
69
+ TracePoint.new(:return) do |tp2|
70
+ type = Utils.object_to_rbs(tp2.return_value)
71
+ @captured_dict[mod_name][[kind, prefix, name]] << type
72
+ end.enable(target: attr_module.instance_method(name))
73
+ end
74
+ if [:attr_accessor, :attr_writer, :attr].include?(kind)
75
+ TracePoint.new(:call) do |tp2|
76
+ type = Utils.object_to_rbs(tp2.binding.local_variable_get(:object))
77
+ @captured_dict[mod_name][[kind, prefix, name]] << type
78
+ end.enable(target: attr_module.instance_method("#{name}="))
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orthoses
4
+ class Trace
5
+ class Method
6
+ # internal
7
+ Info = Struct.new(:key, :op_name_types, :raised, keyword_init: true)
8
+ include Targetable
9
+
10
+ def initialize(loader, patterns:)
11
+ @loader = loader
12
+ @patterns = patterns
13
+
14
+ @stack = []
15
+ @args_return_map = Hash.new { |h, k| h[k] = [] }
16
+ @alias_map = {}
17
+ end
18
+
19
+ def call
20
+ build_trace_point.enable do
21
+ @loader.call
22
+ end.tap do |store|
23
+ build_members.each do |(mod_name, member)|
24
+ out = StringIO.new
25
+ writer = ::RBS::Writer.new(out: out)
26
+ writer.write_member(member)
27
+ store[mod_name] << out.string
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def build_trace_point
35
+ TracePoint.new(:call, :return, :raise) do |tp|
36
+ case tp.event
37
+ when :call
38
+ if tp.defined_class.singleton_class?
39
+ # e.g. `Minitest::Spec::DSL#to_s`` may return `nil` with `#to_s`
40
+ m = tp.defined_class.to_s&.match(/#<Class:([\w:]+)>/) or next
41
+ mod_name = m[1] or next
42
+ kind = :singleton
43
+ else
44
+ mod_name = Utils.module_name(tp.defined_class) or next
45
+ kind = :instance
46
+ end
47
+
48
+ next unless target?(mod_name)
49
+
50
+ visibility = tp.self.private_methods.include?(tp.method_id) ? :private : nil
51
+ key = [mod_name, kind, visibility, tp.method_id]
52
+ op_name_types = tp.parameters.map do |op, name|
53
+ case name
54
+ when nil, :*, :**, :&
55
+ [op, name, 'untyped']
56
+ else
57
+ type = Utils.object_to_rbs(tp.binding.local_variable_get(name))
58
+ [op, name, type]
59
+ end
60
+ end
61
+
62
+ @alias_map[[mod_name, kind, tp.method_id]] = tp.callee_id if tp.method_id != tp.callee_id
63
+ @stack.push(Info.new(key: key, op_name_types: op_name_types, raised: false))
64
+ when :raise
65
+ @stack.last&.raised = true
66
+ when :return
67
+ info = @stack.pop
68
+ if info && !info.raised
69
+ @args_return_map[info.key] << [info.op_name_types, Utils.object_to_rbs(tp.return_value)]
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ def build_members
76
+ build_method_definitions.concat(build_aliases)
77
+ end
78
+
79
+ def build_method_definitions
80
+ untyped = ::RBS::Types::Bases::Any.new(location: nil)
81
+
82
+ @args_return_map.map do |(mod_name, kind, visibility, method_id), type_samples|
83
+ type_samples.uniq!
84
+ method_types = type_samples.map do |(op_name_types, return_type)|
85
+ required_positionals = []
86
+ optional_positionals = []
87
+ rest = nil
88
+ trailing_positionals = []
89
+ required_keywords = {}
90
+ optional_keywords = {}
91
+ rest_keywords = nil
92
+
93
+ requireds = required_positionals
94
+
95
+ block = nil
96
+
97
+ op_name_types.each do |op, name, string_type|
98
+ type = ::RBS::Parser.parse_type(string_type)
99
+
100
+ case op
101
+ when :req
102
+ requireds << ::RBS::Types::Function::Param.new(name: name, type: type)
103
+ when :opt
104
+ requireds = trailing_positionals
105
+ optional_positionals << ::RBS::Types::Function::Param.new(name: name, type: type)
106
+ when :rest
107
+ requireds = trailing_positionals
108
+ name = nil if name == :* # For `def f(...) end` syntax
109
+ rest = ::RBS::Types::Function::Param.new(name: name, type: type)
110
+ when :keyreq
111
+ required_keywords[name] = ::RBS::Types::Function::Param.new(name: nil, type: type)
112
+ when :key
113
+ optional_keywords[name] = ::RBS::Types::Function::Param.new(name: nil, type: type)
114
+ when :keyrest
115
+ rest_keywords = ::RBS::Types::Function::Param.new(name: nil, type: type)
116
+ when :block
117
+ block = ::RBS::Types::Block.new(
118
+ type: ::RBS::Types::Function.empty(untyped).update(rest_positionals: ::RBS::Types::Function::Param.new(name: nil, type: untyped)),
119
+ required: false,
120
+ self_type: nil
121
+ )
122
+ end
123
+ end
124
+
125
+ return_type = if method_id == :initialize
126
+ ::RBS::Types::Bases::Void.new(location: nil)
127
+ else
128
+ ::RBS::Parser.parse_type(return_type)
129
+ end
130
+
131
+ ::RBS::MethodType.new(
132
+ location: nil,
133
+ type_params: [],
134
+ type: ::RBS::Types::Function.new(
135
+ required_positionals: required_positionals,
136
+ optional_positionals: optional_positionals,
137
+ rest_positionals: rest,
138
+ trailing_positionals: trailing_positionals,
139
+ required_keywords: required_keywords,
140
+ optional_keywords: optional_keywords,
141
+ rest_keywords: rest_keywords,
142
+ return_type: return_type,
143
+ ),
144
+ block: block
145
+ )
146
+ end
147
+
148
+ # from:
149
+ # def foo: () -> true
150
+ # | () -> false
151
+ # | (Integer) -> Integer
152
+ # to:
153
+ # def foo: () -> bool
154
+ # | (Integer) -> Integer
155
+ functions_without_return_type_map = method_types.group_by do |method_type|
156
+ method_type.type.with_return_type(untyped)
157
+ end
158
+ types = functions_without_return_type_map.map do |func, method_types_by_arg|
159
+ injected = Utils::TypeList.new(method_types_by_arg.map(&:type).map(&:return_type)).inject
160
+ method_type = method_types_by_arg.first
161
+ method_type.update(type: method_type.type.with_return_type(injected))
162
+ end
163
+
164
+ [
165
+ mod_name,
166
+ RBS::AST::Members::MethodDefinition.new(
167
+ annotations: [],
168
+ comment: nil,
169
+ kind: kind,
170
+ location: nil,
171
+ name: method_id,
172
+ overload: false,
173
+ types: types,
174
+ visibility: visibility
175
+ )
176
+ ]
177
+ end
178
+ end
179
+
180
+ def build_aliases
181
+ @alias_map.map do |(mod_name, kind, method_id), callee_id|
182
+ [
183
+ mod_name,
184
+ RBS::AST::Members::Alias.new(
185
+ new_name: callee_id,
186
+ old_name: method_id,
187
+ kind: kind,
188
+ annotations: [],
189
+ location: nil,
190
+ comment: nil,
191
+ )
192
+ ]
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orthoses
4
+ class Trace
5
+ module Targetable
6
+ def target?(name)
7
+ @patterns.any? do |pattern|
8
+ if pattern.end_with?("*")
9
+ (name || "").start_with?(pattern.chop)
10
+ else
11
+ name == pattern
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module Orthoses
2
+ # Collect argument and return types during code running
3
+ # use Orthoses::Trace,
4
+ # patterns: ['Foo::Bar*']
5
+ class Trace
6
+ autoload :Attribute, 'orthoses/trace/attribute'
7
+ autoload :Method, 'orthoses/trace/method'
8
+ autoload :Targetable, 'orthoses/trace/targetable'
9
+
10
+ def initialize(loader, patterns:)
11
+ @loader = loader
12
+ @patterns = patterns
13
+ end
14
+
15
+ def call
16
+ @loader = Trace::Attribute.new(@loader, patterns: @patterns)
17
+ @loader = Trace::Method.new(@loader, patterns: @patterns)
18
+ @loader.call
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orthoses
4
+ module Utils
5
+ # internal
6
+ class TypeList
7
+ UNTYPED = ::RBS::Types::Bases::Any.new(location: nil)
8
+ NIL_TYPE = ::RBS::Types::Bases::Nil.new(location: nil)
9
+ TRUE_TYPE = ::RBS::Types::Literal.new(literal: true, location: nil)
10
+ FALSE_TYPE = ::RBS::Types::Literal.new(literal: false, location: nil)
11
+
12
+ def initialize(types)
13
+ @types = types.map do |type|
14
+ case type
15
+ when String
16
+ ::RBS::Parser.parse_type(type)
17
+ else
18
+ type
19
+ end
20
+ end
21
+ end
22
+
23
+ def inject
24
+ uniqed = @types.uniq
25
+
26
+ return UNTYPED if uniqed.find { |t| t == UNTYPED }
27
+
28
+ has_true = uniqed.delete(TRUE_TYPE)
29
+ has_false = uniqed.delete(FALSE_TYPE)
30
+ if has_true || has_false
31
+ uniqed << ::RBS::Types::Bases::Bool.new(location: nil)
32
+ end
33
+
34
+ return UNTYPED if uniqed.empty?
35
+ return uniqed.first if uniqed.length == 1
36
+
37
+ args_or_other = uniqed.group_by do |type|
38
+ type.respond_to?(:args) && !type.args.empty?
39
+ end
40
+ if args_or_other[true]
41
+ # { Array => [Array[Intger], Array[String]], Hash => [Hash[untyped, untyped]], ... }
42
+ type_by_name = args_or_other[true].group_by do |type|
43
+ type.name
44
+ end
45
+ type_by_name.each do |name, types|
46
+ if with_untyped_type = types.find { |type| type.args.include?(UNTYPED) }
47
+ types.replace([with_untyped_type])
48
+ end
49
+ end
50
+ args_injected = type_by_name.values.flatten
51
+ args_injected.concat(args_or_other[false]) if args_or_other[false]
52
+ uniqed = args_injected
53
+ end
54
+
55
+ after_optional = uniqed.delete(NIL_TYPE)
56
+ injected = uniqed.inject do |r, type|
57
+ case r
58
+ when ::RBS::Types::Union
59
+ r.tap { r.types << type }
60
+ else
61
+ ::RBS::Types::Union.new(types: [r, type], location: nil)
62
+ end
63
+ end
64
+
65
+ if after_optional
66
+ return ::RBS::Types::Optional.new(type: injected, location: nil)
67
+ end
68
+
69
+ injected
70
+ end
71
+ end
72
+ end
73
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Orthoses
4
4
  module Utils
5
+ autoload :TypeList, "orthoses/utils/type_list"
5
6
  autoload :Underscore, "orthoses/utils/underscore"
6
7
 
7
8
  def self.unautoload!
@@ -101,7 +102,7 @@ module Orthoses
101
102
  end
102
103
  end
103
104
 
104
- def self.object_to_rbs(object, strict:)
105
+ def self.object_to_rbs(object, strict: false)
105
106
  case object
106
107
  when Class, Module
107
108
  if name = module_name(object)
@@ -115,8 +116,14 @@ module Orthoses
115
116
  else
116
117
  module_name(object.class) || 'untyped'
117
118
  end
118
- when true, false, nil
119
- object.inspect
119
+ when true, false
120
+ if strict
121
+ object.inspect
122
+ else
123
+ "bool"
124
+ end
125
+ when nil
126
+ "nil"
120
127
  when Set
121
128
  if object.empty?
122
129
  "Set[untyped]"
@@ -136,7 +143,7 @@ module Orthoses
136
143
  if strict
137
144
  "[#{ary.join(', ')}]"
138
145
  else
139
- "Array[#{ary.uniq.join(' | ')}]"
146
+ "Array[#{TypeList.new(ary).inject}]"
140
147
  end
141
148
  end
142
149
  when Hash
@@ -146,9 +153,9 @@ module Orthoses
146
153
  if strict && object.keys.all? { |key| key.is_a?(Symbol) && /\A\w+\z/.match?(key) }
147
154
  "{ #{object.map { |k, v| "#{k}: #{object_to_rbs(v, strict: strict)}" }.join(', ')} }"
148
155
  else
149
- keys = object.keys.map { |k| object_to_rbs(k, strict: strict) }.uniq
150
- values = object.values.map { |v| object_to_rbs(v, strict: strict) }.uniq
151
- "Hash[#{keys.join(' | ')}, #{values.join(' | ')}]"
156
+ keys = object.keys.map { |k| object_to_rbs(k, strict: strict) }
157
+ values = object.values.map { |v| object_to_rbs(v, strict: strict) }
158
+ "Hash[#{TypeList.new(keys).inject}, #{TypeList.new(values).inject}]"
152
159
  end
153
160
  end
154
161
  when Range
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Orthoses
4
- VERSION = "1.4.0"
4
+ VERSION = "1.5.0"
5
5
  end
data/lib/orthoses.rb CHANGED
@@ -3,6 +3,8 @@
3
3
  require 'rbs'
4
4
  require 'pathname'
5
5
 
6
+ require 'orthoses/utils'
7
+
6
8
  module Orthoses
7
9
  autoload :Attribute, 'orthoses/attribute'
8
10
  autoload :Builder, 'orthoses/builder'
@@ -21,10 +23,11 @@ module Orthoses
21
23
  autoload :PP, 'orthoses/pp'
22
24
  autoload :RBSPrototypeRB, 'orthoses/rbs_prototype_rb'
23
25
  autoload :RBSPrototypeRuntime, 'orthoses/rbs_prototype_runtime'
26
+ autoload :Sort, 'orthoses/sort'
24
27
  autoload :Store, 'orthoses/store'
25
28
  autoload :Tap, 'orthoses/tap'
29
+ autoload :Trace, 'orthoses/trace'
26
30
  autoload :Autoload, 'orthoses/autoload'
27
- autoload :Utils, 'orthoses/utils'
28
31
  autoload :VERSION, 'orthoses/version'
29
32
  autoload :Walk, 'orthoses/walk'
30
33
  autoload :Writer, 'orthoses/writer'
@@ -10,7 +10,9 @@ class Orthoses::Content
10
10
  def to_rbs: () -> String
11
11
  def to_decl: () -> untyped
12
12
  def uniq!: () -> untyped
13
+ def sort!: () -> untyped
13
14
  def original_rbs: () -> untyped
15
+ private def decl_to_lines: (untyped decl) -> untyped
14
16
  private def uniqed_body_string: () -> String
15
17
  private def uniqed_body_decl: () -> RBS::AST::Declarations::t
16
18
  private def auto_header: () -> (nil | untyped)
@@ -0,0 +1,6 @@
1
+ # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
+
3
+ class Orthoses::Sort
4
+ def initialize: (untyped loader) -> void
5
+ def call: () -> untyped
6
+ end
@@ -0,0 +1,8 @@
1
+ # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
+
3
+ class Orthoses::Trace::Attribute
4
+ def initialize: (untyped loader, patterns: untyped) -> void
5
+ def call: () -> untyped
6
+ private def build_trace_hook: () -> untyped
7
+ include Orthoses::Trace::Targetable
8
+ end
@@ -0,0 +1,4 @@
1
+ # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
+
3
+ class Orthoses::Trace::Method::Info < ::Struct[untyped]
4
+ end
@@ -0,0 +1,11 @@
1
+ # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
+
3
+ class Orthoses::Trace::Method
4
+ def initialize: (untyped loader, patterns: untyped) -> void
5
+ def call: () -> untyped
6
+ private def build_trace_point: () -> untyped
7
+ private def build_members: () -> untyped
8
+ private def build_method_definitions: () -> untyped
9
+ private def build_aliases: () -> untyped
10
+ include Orthoses::Trace::Targetable
11
+ end
@@ -0,0 +1,5 @@
1
+ # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
+
3
+ module Orthoses::Trace::Targetable
4
+ def target?: (untyped name) -> untyped
5
+ end
@@ -0,0 +1,6 @@
1
+ # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
+
3
+ class Orthoses::Trace
4
+ def initialize: (untyped loader, patterns: untyped) -> void
5
+ def call: () -> untyped
6
+ end
@@ -0,0 +1,10 @@
1
+ # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
+
3
+ class Orthoses::Utils::TypeList
4
+ def initialize: (untyped types) -> void
5
+ def inject: () -> untyped
6
+ FALSE_TYPE: RBS::Types::Literal
7
+ NIL_TYPE: RBS::Types::Bases::Nil
8
+ TRUE_TYPE: RBS::Types::Literal
9
+ UNTYPED: RBS::Types::Bases::Any
10
+ end
@@ -13,7 +13,7 @@ module Orthoses::Utils
13
13
 
14
14
  def self.rbs_environment: (?library: String | Array[String] | nil, ?collection: boolish, ?cache: boolish) -> RBS::Environment
15
15
 
16
- def self.object_to_rbs: (untyped object, strict: bool) -> String
16
+ def self.object_to_rbs: (untyped object, ?strict: bool) -> String
17
17
 
18
18
  def self.module_name: (Module mod) -> String?
19
19
 
data/sig/orthoses.rbs CHANGED
@@ -1,7 +1,7 @@
1
1
  # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
2
 
3
3
  module Orthoses
4
- VERSION: "1.4.0"
4
+ VERSION: "1.5.0"
5
5
 
6
6
  attr_accessor self.logger: ::Logger
7
7
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orthoses
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-22 00:00:00.000000000 Z
11
+ date: 2023-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbs
@@ -37,6 +37,10 @@ files:
37
37
  - LICENSE.txt
38
38
  - README.md
39
39
  - examples/minitest/Rakefile
40
+ - examples/rack-test/Gemfile
41
+ - examples/rack-test/Gemfile.lock
42
+ - examples/rack-test/Rakefile
43
+ - examples/rack-test/generate.rb
40
44
  - examples/simple_middleware.rb
41
45
  - examples/simple_middleware.rbs
42
46
  - lib/orthoses.rb
@@ -66,9 +70,15 @@ files:
66
70
  - lib/orthoses/pp.rb
67
71
  - lib/orthoses/rbs_prototype_rb.rb
68
72
  - lib/orthoses/rbs_prototype_runtime.rb
73
+ - lib/orthoses/sort.rb
69
74
  - lib/orthoses/store.rb
70
75
  - lib/orthoses/tap.rb
76
+ - lib/orthoses/trace.rb
77
+ - lib/orthoses/trace/attribute.rb
78
+ - lib/orthoses/trace/method.rb
79
+ - lib/orthoses/trace/targetable.rb
71
80
  - lib/orthoses/utils.rb
81
+ - lib/orthoses/utils/type_list.rb
72
82
  - lib/orthoses/utils/underscore.rb
73
83
  - lib/orthoses/version.rb
74
84
  - lib/orthoses/walk.rb
@@ -112,9 +122,16 @@ files:
112
122
  - sig/orthoses/pp.rbs
113
123
  - sig/orthoses/rbs_prototype_rb.rbs
114
124
  - sig/orthoses/rbs_prototype_runtime.rbs
125
+ - sig/orthoses/sort.rbs
115
126
  - sig/orthoses/store.rbs
116
127
  - sig/orthoses/tap.rbs
128
+ - sig/orthoses/trace.rbs
129
+ - sig/orthoses/trace/attribute.rbs
130
+ - sig/orthoses/trace/method.rbs
131
+ - sig/orthoses/trace/method/info.rbs
132
+ - sig/orthoses/trace/targetable.rbs
117
133
  - sig/orthoses/utils.rbs
134
+ - sig/orthoses/utils/type_list.rbs
118
135
  - sig/orthoses/utils/underscore.rbs
119
136
  - sig/orthoses/walk.rbs
120
137
  - sig/orthoses/writer.rbs
@@ -139,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
156
  - !ruby/object:Gem::Version
140
157
  version: '0'
141
158
  requirements: []
142
- rubygems_version: 3.3.16
159
+ rubygems_version: 3.4.3
143
160
  signing_key:
144
161
  specification_version: 4
145
162
  summary: Framework for Generate RBS