raap 0.3.0 → 0.5.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/.rubocop.yml +31 -0
- data/README.md +32 -3
- data/Rakefile +10 -1
- data/exe/raap +4 -1
- data/lib/raap/bind_call.rb +21 -7
- data/lib/raap/cli.rb +211 -125
- data/lib/raap/function_type.rb +14 -10
- data/lib/raap/method_property.rb +60 -28
- data/lib/raap/method_type.rb +13 -6
- data/lib/raap/minitest.rb +9 -3
- data/lib/raap/rbs.rb +19 -0
- data/lib/raap/result.rb +84 -8
- data/lib/raap/sized.rb +2 -0
- data/lib/raap/symbolic_caller.rb +38 -26
- data/lib/raap/type.rb +111 -115
- data/lib/raap/type_substitution.rb +5 -1
- data/lib/raap/value/bottom.rb +2 -0
- data/lib/raap/value/interface.rb +61 -27
- data/lib/raap/value/intersection.rb +26 -21
- data/lib/raap/value/module.rb +50 -7
- data/lib/raap/value/top.rb +2 -0
- data/lib/raap/value/variable.rb +12 -1
- data/lib/raap/value/void.rb +2 -0
- data/lib/raap/version.rb +1 -1
- data/lib/raap.rb +3 -2
- data/public/jacket.webp +0 -0
- data/rbs_collection.lock.yaml +61 -1
- data/rbs_collection.yaml +0 -1
- data/sig/raap.rbs +63 -34
- data/sig/shims.rbs +4 -0
- metadata +10 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94f0ec4ff924c5089f8e307002dd5f3cd778f04e686acd8b46466139c3c1aebd
|
4
|
+
data.tar.gz: e9a06fb3c71cfc6cd605031fe8cb899a123dc82a94ef00586d39e8329c45beac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed0d647fefa8591c0a03981232c84d64bf7c70bcf9207d2dd6471a9f3369747b5dd3adcc3cd60a8e1d65f0e1543ed7a5f5108eef6523c7d306cfc399d0bc63e4
|
7
|
+
data.tar.gz: 537c5dfbb65bb12064e46c47fb75a60321ee0f16296f1272ef27d68927f4f9f3d5875ea6f3ac2225c76a2d274fbe393bff20f573b8d138b52a6ced8027528e1f
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 3.3
|
3
|
+
NewCops: enable
|
4
|
+
Include:
|
5
|
+
- 'lib/**/*.rb'
|
6
|
+
|
7
|
+
Lint:
|
8
|
+
Enabled: true
|
9
|
+
Lint/EmptyBlock:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
Style:
|
13
|
+
Enabled: false
|
14
|
+
Style/HashSyntax:
|
15
|
+
EnforcedShorthandSyntax: always
|
16
|
+
Enabled: true
|
17
|
+
Style/FrozenStringLiteralComment:
|
18
|
+
Enabled: true
|
19
|
+
|
20
|
+
Metrics:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
Layout:
|
24
|
+
Enabled: true
|
25
|
+
Layout/FirstArrayElementIndentation:
|
26
|
+
EnforcedStyle: consistent
|
27
|
+
Layout/LineLength:
|
28
|
+
Max: 150
|
29
|
+
|
30
|
+
Naming:
|
31
|
+
Enabled: false
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# RaaP
|
2
2
|
|
3
|
+
<img src="https://raw.githubusercontent.com/ksss/raap/main/public/jacket.webp" width=400/>
|
4
|
+
|
3
5
|
## RBS as a Property
|
4
6
|
|
5
7
|
RaaP is a property based testing tool.
|
@@ -55,7 +57,7 @@ Finally, you get the perfect RBS!
|
|
55
57
|
|
56
58
|
Install the gem and add to the application's Gemfile by executing:
|
57
59
|
|
58
|
-
$ bundle add raap
|
60
|
+
$ bundle add raap --require false
|
59
61
|
|
60
62
|
If bundler is not being used to manage dependencies, install the gem by executing:
|
61
63
|
|
@@ -68,6 +70,15 @@ $ raap 'MyClass' # Run only RBS of MyClass
|
|
68
70
|
$ raap 'MyClass::*' # Run each class under MyClass
|
69
71
|
$ raap 'MyClass.singleton_method' # Run only MyClass.singleton_method
|
70
72
|
$ raap 'MyClass#instance_method' # Run only MyClass#instance_method
|
73
|
+
$ raap 'MyClass' '!MyClass#skip' # Run method MyClass without #skip
|
74
|
+
```
|
75
|
+
|
76
|
+
```
|
77
|
+
$ cat test/raap.txt
|
78
|
+
MyClass
|
79
|
+
!MyClass#skip
|
80
|
+
|
81
|
+
$ raap $(cat test/raap.txt) # You can manage the methods to be tested in a file
|
71
82
|
```
|
72
83
|
|
73
84
|
## Size
|
@@ -101,11 +112,15 @@ You can specify to load specify PATH as RBS.
|
|
101
112
|
|
102
113
|
### `--library lib`
|
103
114
|
|
104
|
-
You can specify to load RBS library
|
115
|
+
You can specify to load RBS library.
|
105
116
|
|
106
117
|
### `--require lib`
|
107
118
|
|
108
|
-
You can specify require Ruby library
|
119
|
+
You can specify require Ruby library.
|
120
|
+
|
121
|
+
### `--log-level level`
|
122
|
+
|
123
|
+
You can specify log level (debug, info, warn or error).
|
109
124
|
|
110
125
|
### `--timeout sec`
|
111
126
|
|
@@ -123,6 +138,15 @@ You can specify size of end.
|
|
123
138
|
|
124
139
|
You can specify size of step like `Integer#step: (to: Integer, by: Integer)`.
|
125
140
|
|
141
|
+
### `--allow-private`
|
142
|
+
|
143
|
+
By default, raap only validates public methods.
|
144
|
+
However, by setting this option, it is possible to intentionally validate private methods in the RBS.
|
145
|
+
|
146
|
+
## First support is CLI
|
147
|
+
|
148
|
+
In RaaP, usage through the CLI is the primary support focus, and efforts are made to maintain compatibility. The use of the library's code (such as `RaaP::Type`) does not guarantee compatibility.
|
149
|
+
|
126
150
|
## Achievements
|
127
151
|
|
128
152
|
RaaP has already found many RBS mistakes and bug in CRuby during the development phase.
|
@@ -134,6 +158,11 @@ RaaP has already found many RBS mistakes and bug in CRuby during the development
|
|
134
158
|
* https://github.com/ruby/rbs/pull/1769
|
135
159
|
* https://github.com/ruby/rbs/pull/1770
|
136
160
|
* https://github.com/ruby/rbs/pull/1771
|
161
|
+
* https://github.com/ruby/rbs/pull/1779
|
162
|
+
* https://github.com/ruby/rbs/pull/1783
|
163
|
+
* https://github.com/ruby/rbs/pull/1789
|
164
|
+
* https://github.com/ruby/rbs/pull/1790
|
165
|
+
* https://github.com/ruby/rbs/pull/1793
|
137
166
|
|
138
167
|
## Development
|
139
168
|
|
data/Rakefile
CHANGED
@@ -2,7 +2,16 @@
|
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
require "minitest/test_task"
|
5
|
+
require "rubocop/rake_task"
|
5
6
|
|
6
7
|
Minitest::TestTask.create
|
7
8
|
|
8
|
-
|
9
|
+
RuboCop::RakeTask.new
|
10
|
+
|
11
|
+
namespace :steep do
|
12
|
+
task :check do
|
13
|
+
sh "bundle exec steep check"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
task default: [:test, :rubocop, 'steep:check']
|
data/exe/raap
CHANGED
data/lib/raap/bind_call.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RaaP
|
2
4
|
module BindCall
|
3
5
|
class << self
|
4
|
-
def
|
6
|
+
def define_method(...) = ::Module.instance_method(:define_method).bind_call(...)
|
5
7
|
def respond_to?(...) = ::Kernel.instance_method(:respond_to?).bind_call(...)
|
6
8
|
def instance_of?(...) = ::Kernel.instance_method(:instance_of?).bind_call(...)
|
7
9
|
def is_a?(...) = ::Kernel.instance_method(:is_a?).bind_call(...)
|
@@ -11,19 +13,31 @@ module RaaP
|
|
11
13
|
def public_send(...) = ::Kernel.instance_method(:public_send).bind_call(...)
|
12
14
|
|
13
15
|
def class(obj)
|
14
|
-
if
|
15
|
-
obj.class
|
16
|
-
else
|
16
|
+
if instance_of?(obj, BasicObject)
|
17
17
|
::Kernel.instance_method(:class).bind_call(obj)
|
18
|
+
else
|
19
|
+
obj.class
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
21
23
|
def inspect(obj)
|
22
|
-
if
|
23
|
-
obj.inspect
|
24
|
-
else
|
24
|
+
if instance_of?(obj, BasicObject)
|
25
25
|
::Kernel.instance_method(:inspect).bind_call(obj)
|
26
|
+
else
|
27
|
+
case obj
|
28
|
+
when Hash
|
29
|
+
body = obj.map do |k, v|
|
30
|
+
"#{inspect(k)} => #{inspect(v)}"
|
31
|
+
end
|
32
|
+
"{#{body.join(', ')}}"
|
33
|
+
when Array
|
34
|
+
"[#{obj.map { |o| inspect(o) }.join(', ')}]"
|
35
|
+
else
|
36
|
+
obj.inspect
|
37
|
+
end
|
26
38
|
end
|
39
|
+
rescue NoMethodError
|
40
|
+
"#<#{self.class(obj)}>"
|
27
41
|
end
|
28
42
|
end
|
29
43
|
end
|
data/lib/raap/cli.rb
CHANGED
@@ -2,12 +2,7 @@
|
|
2
2
|
|
3
3
|
module RaaP
|
4
4
|
# $ raap Integer#pow
|
5
|
-
# $ raap -I sig RaaP::Type
|
6
5
|
class CLI
|
7
|
-
class << self
|
8
|
-
attr_accessor :option
|
9
|
-
end
|
10
|
-
|
11
6
|
Option = Struct.new(
|
12
7
|
:dirs,
|
13
8
|
:requires,
|
@@ -20,60 +15,80 @@ module RaaP
|
|
20
15
|
keyword_init: true
|
21
16
|
)
|
22
17
|
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
18
|
+
# Should skip methods has side effects
|
19
|
+
DEFAULT_SKIP = Set.new
|
20
|
+
%i[
|
21
|
+
fork system exec spawn `
|
22
|
+
abort exit exit! raise fail
|
23
|
+
load require require_relative
|
24
|
+
gem
|
25
|
+
].each do |kernel_method|
|
26
|
+
DEFAULT_SKIP << "::Kernel##{kernel_method}"
|
27
|
+
DEFAULT_SKIP << "::Kernel.#{kernel_method}"
|
28
|
+
end
|
29
|
+
%i[
|
30
|
+
delete unlink chmod lchmod chown lchown
|
31
|
+
link mkfifo new open rename truncate
|
32
|
+
].each { |m| DEFAULT_SKIP << "::File.#{m}" }
|
33
|
+
%i[flock truncate].each { |m| DEFAULT_SKIP << "::File##{m}" }
|
34
|
+
|
35
|
+
attr_accessor :option, :argv, :skip, :results
|
34
36
|
|
35
37
|
def initialize(argv)
|
38
|
+
# defaults
|
39
|
+
@option = Option.new(
|
40
|
+
dirs: [],
|
41
|
+
requires: [],
|
42
|
+
libraries: [],
|
43
|
+
timeout: 3,
|
44
|
+
size_from: 0,
|
45
|
+
size_to: 99,
|
46
|
+
size_by: 1,
|
47
|
+
allow_private: false,
|
48
|
+
)
|
36
49
|
@argv = argv
|
50
|
+
@skip = DEFAULT_SKIP.dup
|
51
|
+
@results = []
|
37
52
|
end
|
38
53
|
|
39
54
|
def load
|
40
55
|
OptionParser.new do |o|
|
41
56
|
o.on('-I', '--include PATH') do |path|
|
42
|
-
|
57
|
+
@option.dirs << path
|
43
58
|
end
|
44
59
|
o.on('--library lib', 'load rbs library') do |lib|
|
45
|
-
|
60
|
+
@option.libraries << lib
|
46
61
|
end
|
47
62
|
o.on('--require lib', 'require ruby library') do |lib|
|
48
|
-
|
63
|
+
@option.requires << lib
|
49
64
|
end
|
50
|
-
o.on('--log-level level', "default:
|
65
|
+
o.on('--log-level level', "default: info") do |arg|
|
51
66
|
RaaP.logger.level = arg
|
52
67
|
end
|
53
|
-
o.on('--timeout sec',
|
54
|
-
|
68
|
+
o.on('--timeout sec', Float, "default: #{@option.timeout}") do |arg|
|
69
|
+
@option.timeout = arg
|
55
70
|
end
|
56
|
-
o.on('--size-from int', Integer, "default: #{
|
57
|
-
|
71
|
+
o.on('--size-from int', Integer, "default: #{@option.size_from}") do |arg|
|
72
|
+
@option.size_from = arg
|
58
73
|
end
|
59
|
-
o.on('--size-to int', Integer, "default: #{
|
60
|
-
|
74
|
+
o.on('--size-to int', Integer, "default: #{@option.size_to}") do |arg|
|
75
|
+
@option.size_to = arg
|
61
76
|
end
|
62
|
-
o.on('--size-by int', Integer, "default: #{
|
63
|
-
|
77
|
+
o.on('--size-by int', Integer, "default: #{@option.size_by}") do |arg|
|
78
|
+
@option.size_by = arg
|
64
79
|
end
|
65
|
-
o.on('--allow-private', "default: #{
|
66
|
-
|
80
|
+
o.on('--allow-private', "default: #{@option.allow_private}") do
|
81
|
+
@option.allow_private = true
|
67
82
|
end
|
68
83
|
end.parse!(@argv)
|
69
84
|
|
70
|
-
|
85
|
+
@option.dirs.each do |dir|
|
71
86
|
RaaP::RBS.loader.add(path: Pathname(dir))
|
72
87
|
end
|
73
|
-
|
88
|
+
@option.libraries.each do |lib|
|
74
89
|
RaaP::RBS.loader.add(library: lib, version: nil)
|
75
90
|
end
|
76
|
-
|
91
|
+
@option.requires.each do |lib|
|
77
92
|
require lib
|
78
93
|
end
|
79
94
|
|
@@ -81,137 +96,195 @@ module RaaP
|
|
81
96
|
end
|
82
97
|
|
83
98
|
def run
|
84
|
-
|
99
|
+
Signal.trap(:INT) do
|
100
|
+
puts "Interrupted by SIGINT"
|
101
|
+
report
|
102
|
+
exit 1
|
103
|
+
end
|
104
|
+
|
105
|
+
# Search skip tag
|
106
|
+
@argv.each do |tag|
|
107
|
+
if tag.start_with?('!') && (tag.include?('#') || tag.include?('.'))
|
108
|
+
t = tag[1..] or raise
|
109
|
+
t = "::#{t}" unless t.start_with?('::')
|
110
|
+
t or raise
|
111
|
+
@skip << t
|
112
|
+
end
|
113
|
+
end
|
114
|
+
@skip.freeze
|
115
|
+
|
116
|
+
@argv.each do |tag|
|
117
|
+
next if tag.start_with?('!')
|
118
|
+
|
85
119
|
case
|
86
120
|
when tag.include?('#')
|
87
|
-
|
121
|
+
run_by(kind: :instance, tag:)
|
88
122
|
when tag.include?('.')
|
89
|
-
|
123
|
+
run_by(kind: :singleton, tag:)
|
90
124
|
when tag.end_with?('*')
|
91
125
|
run_by_type_name_with_search(tag:)
|
92
126
|
else
|
93
127
|
run_by_type_name(tag:)
|
94
128
|
end
|
95
|
-
end.each do |ret|
|
96
|
-
ret.each do |methods|
|
97
|
-
methods.each do |status, method_name, method_type|
|
98
|
-
if status == 1
|
99
|
-
puts "Fail:"
|
100
|
-
puts "def #{method_name}: #{method_type}"
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
129
|
end
|
105
130
|
|
106
|
-
|
131
|
+
report
|
107
132
|
end
|
108
133
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
134
|
+
private
|
135
|
+
|
136
|
+
def report
|
137
|
+
i = 0
|
138
|
+
exit_status = 0
|
139
|
+
@results.each do |ret|
|
140
|
+
ret => { method:, properties: }
|
141
|
+
properties.select { |status,| status == 1 }.each do |_, method_name, method_type, reason|
|
142
|
+
i += 1
|
143
|
+
location = if method.alias_of
|
144
|
+
alias_decl = RBS.find_alias_decl(method.defined_in, method_name) or raise "alias decl not found: #{method_name}"
|
145
|
+
alias_decl.location
|
146
|
+
else
|
147
|
+
method_type.location
|
148
|
+
end
|
149
|
+
prefix = method.defs.first.member.kind == :instance ? '' : 'self.'
|
150
|
+
|
151
|
+
puts "\e[41m\e[1m#\e[m\e[1m #{i}) Failure:\e[m"
|
152
|
+
puts
|
153
|
+
puts "def #{prefix}#{method_name}: #{method_type}"
|
154
|
+
puts " in #{location}"
|
155
|
+
puts
|
156
|
+
puts "## Reason"
|
157
|
+
puts
|
158
|
+
puts reason&.string
|
159
|
+
puts
|
160
|
+
exit_status = 1
|
127
161
|
end
|
128
|
-
|
162
|
+
end
|
163
|
+
exit_status
|
129
164
|
end
|
130
165
|
|
131
|
-
def
|
132
|
-
|
166
|
+
def run_by(kind:, tag:)
|
167
|
+
split = kind == :instance ? '#' : '.'
|
168
|
+
t, m = tag.split(split, 2)
|
133
169
|
t or raise
|
134
170
|
m or raise
|
135
171
|
type = RBS.parse_type(t)
|
136
172
|
raise "cannot specified #{type.class}" unless type.respond_to?(:name)
|
173
|
+
|
137
174
|
type = __skip__ = type
|
138
|
-
|
175
|
+
type_name = type.name.absolute!
|
176
|
+
type_to_s = type.to_s.start_with?('::') ? type.to_s : "::#{type}"
|
177
|
+
receiver_type = if kind == :instance
|
178
|
+
Type.new(type_to_s)
|
179
|
+
else
|
180
|
+
Type.new("singleton(#{type_name})")
|
181
|
+
end
|
139
182
|
method_name = m.to_sym
|
140
|
-
definition =
|
183
|
+
definition = if kind == :instance
|
184
|
+
RBS.builder.build_instance(type_name)
|
185
|
+
else
|
186
|
+
RBS.builder.build_singleton(type_name)
|
187
|
+
end
|
188
|
+
|
141
189
|
method = definition.methods[method_name]
|
142
|
-
type_params_decl = definition.type_params_decl
|
143
190
|
raise "`#{tag}` not found" unless method
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
191
|
+
|
192
|
+
if @skip.include?("#{type_name}#{split}#{method_name}")
|
193
|
+
raise "`#{type_name}#{split}#{method_name}` is a method to be skipped"
|
194
|
+
end
|
195
|
+
|
196
|
+
type_params_decl = definition.type_params_decl
|
197
|
+
type_args = type.args
|
198
|
+
|
199
|
+
RaaP.logger.info("# #{type}")
|
200
|
+
@results << {
|
201
|
+
method:,
|
202
|
+
properties: method.method_types.map do |method_type|
|
203
|
+
property(receiver_type:, type_params_decl:, type_args:, method_type:, method_name:)
|
149
204
|
end
|
150
|
-
|
205
|
+
}
|
151
206
|
end
|
152
207
|
|
153
208
|
def run_by_type_name_with_search(tag:)
|
154
209
|
first, _last = tag.split('::')
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
210
|
+
RBS.env.class_decls.each do |name, _entry|
|
211
|
+
if ['', '::'].any? { |pre| name.to_s.start_with?("#{pre}#{first}") }
|
212
|
+
if @skip.include?(name.to_s)
|
213
|
+
RaaP.logger.info("Skip #{name}")
|
214
|
+
next
|
215
|
+
end
|
216
|
+
run_by_type_name(tag: name.to_s)
|
159
217
|
end
|
160
218
|
end
|
161
|
-
ret.flatten(1)
|
162
219
|
end
|
163
220
|
|
164
221
|
def run_by_type_name(tag:)
|
165
222
|
type = RBS.parse_type(tag)
|
166
223
|
type = __skip__ = type
|
167
224
|
raise "cannot specified #{type.class}" unless type.respond_to?(:name)
|
168
|
-
type_name = type.name.absolute!
|
169
225
|
|
170
|
-
|
226
|
+
type_name = type.name.absolute!
|
227
|
+
type_args = type.args
|
171
228
|
|
172
229
|
definition = RBS.builder.build_singleton(type_name)
|
173
230
|
type_params_decl = definition.type_params_decl
|
174
|
-
definition.methods.
|
231
|
+
definition.methods.each do |method_name, method|
|
232
|
+
if @skip.include?("#{type_name.absolute!}.#{method_name}")
|
233
|
+
RaaP.logger.info("Skip #{"#{type_name.absolute!}.#{method_name}"}")
|
234
|
+
next
|
235
|
+
end
|
175
236
|
next unless method.accessibility == :public
|
176
237
|
next if method.defined_in != type_name
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
238
|
+
|
239
|
+
RaaP.logger.info("# #{type_name}.#{method_name}")
|
240
|
+
@results << {
|
241
|
+
method:,
|
242
|
+
properties: method.method_types.map do |method_type|
|
243
|
+
property(receiver_type: Type.new("singleton(#{type.name})"), type_params_decl:, type_args:, method_type:, method_name:)
|
244
|
+
end
|
245
|
+
}
|
183
246
|
end
|
184
247
|
|
185
248
|
definition = RBS.builder.build_instance(type_name)
|
186
249
|
type_params_decl = definition.type_params_decl
|
187
|
-
definition.methods.
|
250
|
+
definition.methods.each do |method_name, method|
|
251
|
+
if @skip.include?("#{type_name.absolute!}##{method_name}")
|
252
|
+
RaaP.logger.info("Skip #{"#{type_name.absolute!}.#{method_name}"}")
|
253
|
+
next
|
254
|
+
end
|
188
255
|
next unless method.accessibility == :public
|
189
256
|
next if method.defined_in != type_name
|
190
|
-
next if method_name == :fork || method_name == :spawn # TODO: skip solution
|
191
|
-
puts "# #{type_name}##{method_name}"
|
192
|
-
puts
|
193
|
-
ret << method.method_types.map do |method_type|
|
194
|
-
property(receiver_type: Type.new(type.to_s), type_params_decl:, method_type:, method_name:)
|
195
|
-
end
|
196
|
-
end
|
197
257
|
|
198
|
-
|
258
|
+
RaaP.logger.info("# #{type_name}##{method_name}")
|
259
|
+
@results << {
|
260
|
+
method:,
|
261
|
+
properties: method.method_types.map do |method_type|
|
262
|
+
property(receiver_type: Type.new(type.name), type_params_decl:, type_args:, method_type:, method_name:)
|
263
|
+
end
|
264
|
+
}
|
265
|
+
end
|
199
266
|
end
|
200
267
|
|
201
|
-
def property(receiver_type:, type_params_decl:, method_type:, method_name:)
|
268
|
+
def property(receiver_type:, type_params_decl:, type_args:, method_type:, method_name:)
|
202
269
|
rtype = __skip__ = receiver_type.type
|
203
270
|
if receiver_type.type.instance_of?(::RBS::Types::ClassSingleton)
|
204
271
|
prefix = 'self.'
|
205
|
-
type_args = []
|
206
272
|
else
|
207
273
|
prefix = ''
|
208
|
-
type_args = rtype.args
|
209
274
|
end
|
210
|
-
|
275
|
+
|
276
|
+
# type_args delegate to self_type
|
277
|
+
type_params_decl.each_with_index do |param, i|
|
278
|
+
if rtype.instance_of?(::RBS::Types::ClassInstance)
|
279
|
+
rtype.args[i] = type_args[i] || param.upper_bound || ::RBS::Types::Bases::Any.new(location: nil)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
RaaP.logger.info("## def #{prefix}#{method_name}: #{method_type}")
|
211
283
|
status = 0
|
212
|
-
|
284
|
+
reason = nil
|
285
|
+
prop = MethodProperty.new(
|
213
286
|
receiver_type:,
|
214
|
-
method_name
|
287
|
+
method_name:,
|
215
288
|
method_type: MethodType.new(
|
216
289
|
method_type,
|
217
290
|
type_params_decl:,
|
@@ -220,46 +293,59 @@ module RaaP
|
|
220
293
|
instance_type: ::RBS::Types::ClassInstance.new(name: rtype.name, args: type_args, location: nil),
|
221
294
|
class_type: ::RBS::Types::ClassSingleton.new(name: rtype.name, location: nil),
|
222
295
|
),
|
223
|
-
size_step:
|
224
|
-
timeout:
|
225
|
-
allow_private:
|
226
|
-
)
|
296
|
+
size_step: @option.size_from.step(to: @option.size_to, by: @option.size_by),
|
297
|
+
timeout: @option.timeout,
|
298
|
+
allow_private: @option.allow_private,
|
299
|
+
)
|
300
|
+
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
301
|
+
stats = prop.run do |called|
|
227
302
|
case called
|
228
303
|
in Result::Success => s
|
229
304
|
print '.'
|
230
305
|
RaaP.logger.debug { "Success: #{s.called_str}" }
|
231
306
|
in Result::Failure => f
|
232
307
|
puts 'F'
|
233
|
-
|
234
|
-
|
235
|
-
RaaP.logger.debug {
|
308
|
+
if (e = f.exception)
|
309
|
+
RaaP.logger.info { "Failure: [#{e.class}] #{e.message}" }
|
310
|
+
RaaP.logger.debug { e.backtrace.join("\n") }
|
236
311
|
end
|
237
|
-
puts
|
238
312
|
RaaP.logger.debug { PP.pp(f.symbolic_call, ''.dup) }
|
239
|
-
|
240
|
-
puts
|
241
|
-
puts
|
242
|
-
puts
|
243
|
-
puts
|
313
|
+
reason = StringIO.new
|
314
|
+
reason.puts "Failed in case of `#{f.called_str}`"
|
315
|
+
reason.puts
|
316
|
+
reason.puts "### Repro"
|
317
|
+
reason.puts
|
318
|
+
reason.puts "```rb"
|
319
|
+
reason.puts SymbolicCaller.new(f.symbolic_call).to_lines.join("\n")
|
320
|
+
reason.puts "```"
|
244
321
|
status = 1
|
245
322
|
throw :break
|
246
323
|
in Result::Skip => s
|
247
324
|
print 'S'
|
248
|
-
RaaP.logger.debug {
|
249
|
-
RaaP.logger.debug("Skip:
|
325
|
+
RaaP.logger.debug { "\n```\n#{SymbolicCaller.new(s.symbolic_call).to_lines.join("\n")}\n```" }
|
326
|
+
RaaP.logger.debug("Skip: #{s.exception.detailed_message}")
|
250
327
|
RaaP.logger.debug(s.exception.backtrace.join("\n"))
|
251
328
|
in Result::Exception => e
|
252
329
|
print 'E'
|
253
|
-
RaaP.logger.debug {
|
254
|
-
RaaP.logger.debug("Exception:
|
330
|
+
RaaP.logger.debug { "\n```\n#{SymbolicCaller.new(e.symbolic_call).to_lines.join("\n")}\n```" }
|
331
|
+
RaaP.logger.debug("Exception: #{e.exception.detailed_message}")
|
255
332
|
RaaP.logger.debug(e.exception.backtrace.join("\n"))
|
256
333
|
end
|
257
334
|
end
|
335
|
+
end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
258
336
|
puts
|
259
|
-
|
260
|
-
|
337
|
+
time_diff = end_time - start_time
|
338
|
+
time = ", time: #{(time_diff * 1000).round}ms"
|
339
|
+
stats_log = "success: #{stats.success}, skip: #{stats.skip}, exception: #{stats.exception}#{time}"
|
340
|
+
RaaP.logger.info(stats_log)
|
341
|
+
|
342
|
+
if status == 0 && stats.success.zero? && !stats.break
|
343
|
+
status = 1
|
344
|
+
reason = StringIO.new
|
345
|
+
reason.puts "Never succeeded => #{stats_log}"
|
346
|
+
end
|
261
347
|
|
262
|
-
[status, method_name, method_type]
|
348
|
+
[status, method_name, method_type, reason]
|
263
349
|
end
|
264
350
|
end
|
265
351
|
end
|