steep 0.14.0 → 0.16.3

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.
Files changed (211) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +0 -3
  3. data/CHANGELOG.md +25 -0
  4. data/Rakefile +0 -13
  5. data/bin/setup +0 -2
  6. data/bin/smoke_runner.rb +0 -1
  7. data/exe/steep +0 -1
  8. data/lib/steep.rb +18 -2
  9. data/lib/steep/annotation_parser.rb +4 -4
  10. data/lib/steep/ast/buffer.rb +11 -7
  11. data/lib/steep/ast/builtin.rb +8 -0
  12. data/lib/steep/ast/types/factory.rb +55 -55
  13. data/lib/steep/cli.rb +16 -1
  14. data/lib/steep/drivers/annotations.rb +1 -1
  15. data/lib/steep/drivers/check.rb +20 -4
  16. data/lib/steep/drivers/langserver.rb +13 -457
  17. data/lib/steep/drivers/utils/driver_helper.rb +1 -1
  18. data/lib/steep/drivers/vendor.rb +2 -2
  19. data/lib/steep/drivers/watch.rb +97 -85
  20. data/lib/steep/drivers/worker.rb +51 -0
  21. data/lib/steep/project.rb +9 -5
  22. data/lib/steep/project/completion_provider.rb +9 -13
  23. data/lib/steep/project/dsl.rb +14 -0
  24. data/lib/steep/project/file.rb +43 -46
  25. data/lib/steep/project/hover_content.rb +17 -8
  26. data/lib/steep/project/options.rb +25 -3
  27. data/lib/steep/project/target.rb +40 -24
  28. data/lib/steep/server/base_worker.rb +56 -0
  29. data/lib/steep/server/code_worker.rb +151 -0
  30. data/lib/steep/server/interaction_worker.rb +281 -0
  31. data/lib/steep/server/master.rb +196 -0
  32. data/lib/steep/server/signature_worker.rb +148 -0
  33. data/lib/steep/server/utils.rb +36 -0
  34. data/lib/steep/server/worker_process.rb +62 -0
  35. data/lib/steep/signature/errors.rb +1 -1
  36. data/lib/steep/signature/validator.rb +13 -13
  37. data/lib/steep/source.rb +1 -1
  38. data/lib/steep/type_construction.rb +996 -726
  39. data/lib/steep/type_inference/constant_env.rb +3 -11
  40. data/lib/steep/type_inference/context.rb +8 -3
  41. data/lib/steep/type_inference/context_array.rb +111 -0
  42. data/lib/steep/type_inference/local_variable_type_env.rb +226 -0
  43. data/lib/steep/type_inference/logic.rb +130 -0
  44. data/lib/steep/type_inference/type_env.rb +5 -69
  45. data/lib/steep/typing.rb +79 -22
  46. data/lib/steep/version.rb +1 -1
  47. data/smoke/alias/Steepfile +1 -0
  48. data/smoke/and/Steepfile +1 -0
  49. data/smoke/array/Steepfile +1 -0
  50. data/smoke/array/b.rb +0 -2
  51. data/smoke/block/Steepfile +1 -0
  52. data/smoke/case/Steepfile +1 -0
  53. data/smoke/class/Steepfile +1 -0
  54. data/smoke/const/Steepfile +1 -0
  55. data/smoke/dstr/Steepfile +1 -0
  56. data/smoke/ensure/Steepfile +1 -0
  57. data/smoke/enumerator/Steepfile +1 -0
  58. data/smoke/extension/Steepfile +1 -0
  59. data/smoke/extension/c.rb +1 -0
  60. data/smoke/hash/Steepfile +1 -0
  61. data/smoke/hello/Steepfile +1 -0
  62. data/smoke/if/Steepfile +1 -0
  63. data/smoke/if/a.rb +1 -1
  64. data/smoke/implements/Steepfile +1 -0
  65. data/smoke/initialize/Steepfile +1 -0
  66. data/smoke/integer/Steepfile +1 -0
  67. data/smoke/interface/Steepfile +1 -0
  68. data/smoke/kwbegin/Steepfile +1 -0
  69. data/smoke/lambda/Steepfile +1 -0
  70. data/smoke/literal/Steepfile +1 -0
  71. data/smoke/map/Steepfile +1 -0
  72. data/smoke/method/Steepfile +1 -0
  73. data/smoke/module/Steepfile +1 -0
  74. data/smoke/regexp/Steepfile +1 -0
  75. data/smoke/regression/Steepfile +1 -0
  76. data/smoke/rescue/Steepfile +1 -0
  77. data/smoke/rescue/a.rb +1 -1
  78. data/smoke/self/Steepfile +1 -0
  79. data/smoke/skip/Steepfile +1 -0
  80. data/smoke/stdout/Steepfile +1 -0
  81. data/smoke/super/Steepfile +1 -0
  82. data/smoke/type_case/Steepfile +1 -0
  83. data/smoke/yield/Steepfile +1 -0
  84. data/steep.gemspec +7 -8
  85. metadata +26 -141
  86. data/exe/rbs +0 -3
  87. data/exe/ruby-signature +0 -3
  88. data/vendor/ruby-signature/.github/workflows/ruby.yml +0 -27
  89. data/vendor/ruby-signature/.gitignore +0 -12
  90. data/vendor/ruby-signature/.rubocop.yml +0 -15
  91. data/vendor/ruby-signature/BSDL +0 -22
  92. data/vendor/ruby-signature/COPYING +0 -56
  93. data/vendor/ruby-signature/Gemfile +0 -6
  94. data/vendor/ruby-signature/README.md +0 -93
  95. data/vendor/ruby-signature/Rakefile +0 -67
  96. data/vendor/ruby-signature/bin/annotate-with-rdoc +0 -156
  97. data/vendor/ruby-signature/bin/console +0 -14
  98. data/vendor/ruby-signature/bin/query-rdoc +0 -103
  99. data/vendor/ruby-signature/bin/setup +0 -10
  100. data/vendor/ruby-signature/bin/sort +0 -88
  101. data/vendor/ruby-signature/bin/test_runner.rb +0 -17
  102. data/vendor/ruby-signature/docs/CONTRIBUTING.md +0 -97
  103. data/vendor/ruby-signature/docs/sigs.md +0 -148
  104. data/vendor/ruby-signature/docs/stdlib.md +0 -152
  105. data/vendor/ruby-signature/docs/syntax.md +0 -528
  106. data/vendor/ruby-signature/exe/rbs +0 -3
  107. data/vendor/ruby-signature/exe/ruby-signature +0 -7
  108. data/vendor/ruby-signature/lib/ruby/signature.rb +0 -64
  109. data/vendor/ruby-signature/lib/ruby/signature/ast/annotation.rb +0 -29
  110. data/vendor/ruby-signature/lib/ruby/signature/ast/comment.rb +0 -29
  111. data/vendor/ruby-signature/lib/ruby/signature/ast/declarations.rb +0 -391
  112. data/vendor/ruby-signature/lib/ruby/signature/ast/members.rb +0 -364
  113. data/vendor/ruby-signature/lib/ruby/signature/buffer.rb +0 -52
  114. data/vendor/ruby-signature/lib/ruby/signature/builtin_names.rb +0 -54
  115. data/vendor/ruby-signature/lib/ruby/signature/cli.rb +0 -555
  116. data/vendor/ruby-signature/lib/ruby/signature/constant.rb +0 -28
  117. data/vendor/ruby-signature/lib/ruby/signature/constant_table.rb +0 -152
  118. data/vendor/ruby-signature/lib/ruby/signature/definition.rb +0 -172
  119. data/vendor/ruby-signature/lib/ruby/signature/definition_builder.rb +0 -921
  120. data/vendor/ruby-signature/lib/ruby/signature/environment.rb +0 -283
  121. data/vendor/ruby-signature/lib/ruby/signature/environment_loader.rb +0 -138
  122. data/vendor/ruby-signature/lib/ruby/signature/environment_walker.rb +0 -126
  123. data/vendor/ruby-signature/lib/ruby/signature/errors.rb +0 -189
  124. data/vendor/ruby-signature/lib/ruby/signature/location.rb +0 -104
  125. data/vendor/ruby-signature/lib/ruby/signature/method_type.rb +0 -125
  126. data/vendor/ruby-signature/lib/ruby/signature/namespace.rb +0 -93
  127. data/vendor/ruby-signature/lib/ruby/signature/parser.y +0 -1344
  128. data/vendor/ruby-signature/lib/ruby/signature/prototype/rb.rb +0 -444
  129. data/vendor/ruby-signature/lib/ruby/signature/prototype/rbi.rb +0 -579
  130. data/vendor/ruby-signature/lib/ruby/signature/prototype/runtime.rb +0 -383
  131. data/vendor/ruby-signature/lib/ruby/signature/substitution.rb +0 -48
  132. data/vendor/ruby-signature/lib/ruby/signature/test.rb +0 -28
  133. data/vendor/ruby-signature/lib/ruby/signature/test/errors.rb +0 -63
  134. data/vendor/ruby-signature/lib/ruby/signature/test/hook.rb +0 -290
  135. data/vendor/ruby-signature/lib/ruby/signature/test/setup.rb +0 -58
  136. data/vendor/ruby-signature/lib/ruby/signature/test/spy.rb +0 -327
  137. data/vendor/ruby-signature/lib/ruby/signature/test/test_helper.rb +0 -185
  138. data/vendor/ruby-signature/lib/ruby/signature/test/type_check.rb +0 -256
  139. data/vendor/ruby-signature/lib/ruby/signature/type_name.rb +0 -72
  140. data/vendor/ruby-signature/lib/ruby/signature/types.rb +0 -932
  141. data/vendor/ruby-signature/lib/ruby/signature/variance_calculator.rb +0 -140
  142. data/vendor/ruby-signature/lib/ruby/signature/vendorer.rb +0 -49
  143. data/vendor/ruby-signature/lib/ruby/signature/version.rb +0 -5
  144. data/vendor/ruby-signature/lib/ruby/signature/writer.rb +0 -271
  145. data/vendor/ruby-signature/ruby-signature.gemspec +0 -45
  146. data/vendor/ruby-signature/stdlib/abbrev/abbrev.rbs +0 -3
  147. data/vendor/ruby-signature/stdlib/base64/base64.rbs +0 -15
  148. data/vendor/ruby-signature/stdlib/builtin/array.rbs +0 -1997
  149. data/vendor/ruby-signature/stdlib/builtin/basic_object.rbs +0 -280
  150. data/vendor/ruby-signature/stdlib/builtin/binding.rbs +0 -177
  151. data/vendor/ruby-signature/stdlib/builtin/builtin.rbs +0 -35
  152. data/vendor/ruby-signature/stdlib/builtin/class.rbs +0 -145
  153. data/vendor/ruby-signature/stdlib/builtin/comparable.rbs +0 -116
  154. data/vendor/ruby-signature/stdlib/builtin/complex.rbs +0 -400
  155. data/vendor/ruby-signature/stdlib/builtin/constants.rbs +0 -37
  156. data/vendor/ruby-signature/stdlib/builtin/data.rbs +0 -5
  157. data/vendor/ruby-signature/stdlib/builtin/deprecated.rbs +0 -2
  158. data/vendor/ruby-signature/stdlib/builtin/dir.rbs +0 -419
  159. data/vendor/ruby-signature/stdlib/builtin/encoding.rbs +0 -606
  160. data/vendor/ruby-signature/stdlib/builtin/enumerable.rbs +0 -404
  161. data/vendor/ruby-signature/stdlib/builtin/enumerator.rbs +0 -260
  162. data/vendor/ruby-signature/stdlib/builtin/errno.rbs +0 -781
  163. data/vendor/ruby-signature/stdlib/builtin/errors.rbs +0 -582
  164. data/vendor/ruby-signature/stdlib/builtin/exception.rbs +0 -193
  165. data/vendor/ruby-signature/stdlib/builtin/false_class.rbs +0 -40
  166. data/vendor/ruby-signature/stdlib/builtin/fiber.rbs +0 -68
  167. data/vendor/ruby-signature/stdlib/builtin/fiber_error.rbs +0 -12
  168. data/vendor/ruby-signature/stdlib/builtin/file.rbs +0 -476
  169. data/vendor/ruby-signature/stdlib/builtin/file_test.rbs +0 -59
  170. data/vendor/ruby-signature/stdlib/builtin/float.rbs +0 -696
  171. data/vendor/ruby-signature/stdlib/builtin/gc.rbs +0 -121
  172. data/vendor/ruby-signature/stdlib/builtin/hash.rbs +0 -1029
  173. data/vendor/ruby-signature/stdlib/builtin/integer.rbs +0 -710
  174. data/vendor/ruby-signature/stdlib/builtin/io.rbs +0 -683
  175. data/vendor/ruby-signature/stdlib/builtin/kernel.rbs +0 -574
  176. data/vendor/ruby-signature/stdlib/builtin/marshal.rbs +0 -135
  177. data/vendor/ruby-signature/stdlib/builtin/match_data.rbs +0 -271
  178. data/vendor/ruby-signature/stdlib/builtin/math.rbs +0 -66
  179. data/vendor/ruby-signature/stdlib/builtin/method.rbs +0 -182
  180. data/vendor/ruby-signature/stdlib/builtin/module.rbs +0 -248
  181. data/vendor/ruby-signature/stdlib/builtin/nil_class.rbs +0 -82
  182. data/vendor/ruby-signature/stdlib/builtin/numeric.rbs +0 -409
  183. data/vendor/ruby-signature/stdlib/builtin/object.rbs +0 -824
  184. data/vendor/ruby-signature/stdlib/builtin/proc.rbs +0 -426
  185. data/vendor/ruby-signature/stdlib/builtin/process.rbs +0 -354
  186. data/vendor/ruby-signature/stdlib/builtin/random.rbs +0 -93
  187. data/vendor/ruby-signature/stdlib/builtin/range.rbs +0 -226
  188. data/vendor/ruby-signature/stdlib/builtin/rational.rbs +0 -424
  189. data/vendor/ruby-signature/stdlib/builtin/rb_config.rbs +0 -10
  190. data/vendor/ruby-signature/stdlib/builtin/regexp.rbs +0 -1083
  191. data/vendor/ruby-signature/stdlib/builtin/ruby_vm.rbs +0 -14
  192. data/vendor/ruby-signature/stdlib/builtin/signal.rbs +0 -55
  193. data/vendor/ruby-signature/stdlib/builtin/string.rbs +0 -1894
  194. data/vendor/ruby-signature/stdlib/builtin/string_io.rbs +0 -13
  195. data/vendor/ruby-signature/stdlib/builtin/struct.rbs +0 -40
  196. data/vendor/ruby-signature/stdlib/builtin/symbol.rbs +0 -230
  197. data/vendor/ruby-signature/stdlib/builtin/thread.rbs +0 -1112
  198. data/vendor/ruby-signature/stdlib/builtin/thread_group.rbs +0 -23
  199. data/vendor/ruby-signature/stdlib/builtin/time.rbs +0 -739
  200. data/vendor/ruby-signature/stdlib/builtin/trace_point.rbs +0 -91
  201. data/vendor/ruby-signature/stdlib/builtin/true_class.rbs +0 -46
  202. data/vendor/ruby-signature/stdlib/builtin/unbound_method.rbs +0 -159
  203. data/vendor/ruby-signature/stdlib/builtin/warning.rbs +0 -17
  204. data/vendor/ruby-signature/stdlib/erb/erb.rbs +0 -18
  205. data/vendor/ruby-signature/stdlib/find/find.rbs +0 -44
  206. data/vendor/ruby-signature/stdlib/pathname/pathname.rbs +0 -21
  207. data/vendor/ruby-signature/stdlib/prime/integer-extension.rbs +0 -23
  208. data/vendor/ruby-signature/stdlib/prime/prime.rbs +0 -188
  209. data/vendor/ruby-signature/stdlib/securerandom/securerandom.rbs +0 -9
  210. data/vendor/ruby-signature/stdlib/set/set.rbs +0 -77
  211. data/vendor/ruby-signature/stdlib/tmpdir/tmpdir.rbs +0 -53
@@ -1,63 +0,0 @@
1
- module Ruby
2
- module Signature
3
- module Test
4
- module Errors
5
- ArgumentTypeError =
6
- Struct.new(:klass, :method_name, :method_type, :param, :value, keyword_init: true)
7
- BlockArgumentTypeError =
8
- Struct.new(:klass, :method_name, :method_type, :param, :value, keyword_init: true)
9
- ArgumentError =
10
- Struct.new(:klass, :method_name, :method_type, keyword_init: true)
11
- BlockArgumentError =
12
- Struct.new(:klass, :method_name, :method_type, keyword_init: true)
13
- ReturnTypeError =
14
- Struct.new(:klass, :method_name, :method_type, :type, :value, keyword_init: true)
15
- BlockReturnTypeError =
16
- Struct.new(:klass, :method_name, :method_type, :type, :value, keyword_init: true)
17
-
18
- UnexpectedBlockError = Struct.new(:klass, :method_name, :method_type, keyword_init: true)
19
- MissingBlockError = Struct.new(:klass, :method_name, :method_type, keyword_init: true)
20
-
21
- UnresolvedOverloadingError = Struct.new(:klass, :method_name, :method_types, keyword_init: true)
22
-
23
- def self.format_param(param)
24
- if param.name
25
- "`#{param.type}` (#{param.name})"
26
- else
27
- "`#{param.type}`"
28
- end
29
- end
30
-
31
- def self.inspect_(obj)
32
- Hook.inspect_(obj)
33
- end
34
-
35
- def self.to_string(error)
36
- method = "#{error.klass.name}#{error.method_name}"
37
- case error
38
- when ArgumentTypeError
39
- "[#{method}] ArgumentTypeError: expected #{format_param error.param} but given `#{inspect_(error.value)}`"
40
- when BlockArgumentTypeError
41
- "[#{method}] BlockArgumentTypeError: expected #{format_param error.param} but given `#{inspect_(error.value)}`"
42
- when ArgumentError
43
- "[#{method}] ArgumentError: expected method type #{error.method_type}"
44
- when BlockArgumentError
45
- "[#{method}] BlockArgumentError: expected method type #{error.method_type}"
46
- when ReturnTypeError
47
- "[#{method}] ReturnTypeError: expected `#{error.type}` but returns `#{inspect_(error.value)}`"
48
- when BlockReturnTypeError
49
- "[#{method}] BlockReturnTypeError: expected `#{error.type}` but returns `#{inspect_(error.value)}`"
50
- when UnexpectedBlockError
51
- "[#{method}] UnexpectedBlockError: unexpected block is given for `#{error.method_type}`"
52
- when MissingBlockError
53
- "[#{method}] MissingBlockError: required block is missing for `#{error.method_type}`"
54
- when UnresolvedOverloadingError
55
- "[#{method}] UnresolvedOverloadingError: couldn't find a suitable overloading"
56
- else
57
- raise "Unexpected error: #{inspect_(error)}"
58
- end
59
- end
60
- end
61
- end
62
- end
63
- end
@@ -1,290 +0,0 @@
1
- require "ruby/signature"
2
- require "pp"
3
-
4
- module Ruby
5
- module Signature
6
- module Test
7
- class Hook
8
- class Error < Exception
9
- attr_reader :errors
10
-
11
- def initialize(errors)
12
- @errors = errors
13
- super "Type error detected: [#{errors.map {|e| Errors.to_string(e) }.join(", ")}]"
14
- end
15
- end
16
-
17
- attr_reader :env
18
- attr_reader :logger
19
-
20
- attr_reader :instance_module
21
- attr_reader :instance_methods
22
- attr_reader :singleton_module
23
- attr_reader :singleton_methods
24
-
25
- attr_reader :klass
26
- attr_reader :errors
27
-
28
- def builder
29
- @builder ||= DefinitionBuilder.new(env: env)
30
- end
31
-
32
- def typecheck
33
- @typecheck ||= TypeCheck.new(self_class: klass, builder: builder)
34
- end
35
-
36
- def initialize(env, klass, logger:, raise_on_error: false)
37
- @env = env
38
- @logger = logger
39
- @klass = klass
40
-
41
- @instance_module = Module.new
42
- @instance_methods = []
43
-
44
- @singleton_module = Module.new
45
- @singleton_methods = []
46
-
47
- @errors = []
48
-
49
- @raise_on_error = raise_on_error
50
- end
51
-
52
- def raise_on_error!(error = true)
53
- @raise_on_error = error
54
- self
55
- end
56
-
57
- def raise_on_error?
58
- @raise_on_error
59
- end
60
-
61
- def prepend!
62
- klass.prepend @instance_module
63
- klass.singleton_class.prepend @singleton_module
64
-
65
- if block_given?
66
- yield
67
- disable
68
- end
69
-
70
- self
71
- end
72
-
73
- def self.install(env, klass, logger:)
74
- new(env, klass, logger: logger).prepend!
75
- end
76
-
77
- def refinement
78
- klass = self.klass
79
- instance_module = self.instance_module
80
- singleton_module = self.singleton_module
81
-
82
- Module.new do
83
- refine klass do
84
- prepend instance_module
85
- end
86
-
87
- refine klass.singleton_class do
88
- prepend singleton_module
89
- end
90
- end
91
- end
92
-
93
- def verify_all
94
- type_name = Namespace.parse(klass.name).to_type_name.absolute!
95
-
96
- builder.build_instance(type_name).tap do |definition|
97
- definition.methods.each do |name, method|
98
- if method.defined_in.name.absolute! == type_name
99
- unless method.annotations.any? {|a| a.string == "rbs:test:skip" }
100
- logger.info "Installing a hook on #{type_name}##{name}: #{method.method_types.join(" | ")}"
101
- verify instance_method: name, types: method.method_types
102
- else
103
- logger.info "Skipping test of #{type_name}##{name}"
104
- end
105
- end
106
- end
107
- end
108
-
109
- builder.build_singleton(type_name).tap do |definition|
110
- definition.methods.each do |name, method|
111
- if method.defined_in&.name&.absolute! == type_name || name == :new
112
- unless method.annotations.any? {|a| a.string == "rbs:test:skip" }
113
- logger.info "Installing a hook on #{type_name}.#{name}: #{method.method_types.join(" | ")}"
114
- verify singleton_method: name, types: method.method_types
115
- else
116
- logger.info "Skipping test of #{type_name}.#{name}"
117
- end
118
- end
119
- end
120
- end
121
-
122
- self
123
- end
124
-
125
- def delegation(name, method_types, method_name)
126
- hook = self
127
-
128
- -> (*args, &block) do
129
- hook.logger.debug { "#{method_name} receives arguments: #{hook.inspect_(args)}" }
130
-
131
- block_calls = []
132
-
133
- if block
134
- original_block = block
135
-
136
- block = hook.call(Object.new, INSTANCE_EVAL) do |fresh_obj|
137
- ->(*as) do
138
- hook.logger.debug { "#{method_name} receives block arguments: #{hook.inspect_(as)}" }
139
-
140
- ret = if self.equal?(fresh_obj)
141
- original_block[*as]
142
- else
143
- hook.call(self, INSTANCE_EXEC, *as, &original_block)
144
- end
145
-
146
- block_calls << ArgumentsReturn.new(
147
- arguments: as,
148
- return_value: ret,
149
- exception: nil
150
- )
151
-
152
- hook.logger.debug { "#{method_name} returns from block: #{hook.inspect_(ret)}" }
153
-
154
- ret
155
- end.ruby2_keywords
156
- end
157
- end
158
-
159
- method = hook.call(self, METHOD, name)
160
- klass = hook.call(self, CLASS)
161
- singleton_klass = begin
162
- hook.call(self, SINGLETON_CLASS)
163
- rescue TypeError
164
- nil
165
- end
166
- prepended = klass.ancestors.include?(hook.instance_module) || singleton_klass&.ancestors&.include?(hook.singleton_module)
167
- result = if prepended
168
- method.super_method.call(*args, &block)
169
- else
170
- # Using refinement
171
- method.call(*args, &block)
172
- end
173
-
174
- hook.logger.debug { "#{method_name} returns: #{hook.inspect_(result)}" }
175
-
176
- call = CallTrace.new(method_call: ArgumentsReturn.new(arguments: args, return_value: result, exception: nil),
177
- block_calls: block_calls,
178
- block_given: block != nil)
179
-
180
- method_type_errors = method_types.map do |method_type|
181
- hook.typecheck.method_call(method_name, method_type, call, errors: [])
182
- end
183
-
184
- new_errors = []
185
-
186
- if method_type_errors.none?(&:empty?)
187
- if (best_errors = hook.find_best_errors(method_type_errors))
188
- new_errors.push(*best_errors)
189
- else
190
- new_errors << Errors::UnresolvedOverloadingError.new(
191
- klass: hook.klass,
192
- method_name: method_name,
193
- method_types: method_types
194
- )
195
- end
196
- end
197
-
198
- unless new_errors.empty?
199
- new_errors.each do |error|
200
- hook.logger.error Errors.to_string(error)
201
- end
202
-
203
- hook.errors.push(*new_errors)
204
-
205
- if hook.raise_on_error?
206
- raise Error.new(new_errors)
207
- end
208
- end
209
-
210
- result
211
- end.ruby2_keywords
212
- end
213
-
214
- def verify(instance_method: nil, singleton_method: nil, types:)
215
- method_types = types.map do |type|
216
- case type
217
- when String
218
- Parser.parse_method_type(type)
219
- else
220
- type
221
- end
222
- end
223
-
224
- case
225
- when instance_method
226
- instance_methods << instance_method
227
- call(self.instance_module, DEFINE_METHOD, instance_method, &delegation(instance_method, method_types, "##{instance_method}"))
228
- when singleton_method
229
- call(self.singleton_module, DEFINE_METHOD, singleton_method, &delegation(singleton_method, method_types, ".#{singleton_method}"))
230
- end
231
-
232
- self
233
- end
234
-
235
- def find_best_errors(errorss)
236
- if errorss.size == 1
237
- errorss[0]
238
- else
239
- no_arity_errors = errorss.select do |errors|
240
- errors.none? do |error|
241
- error.is_a?(Errors::ArgumentError) ||
242
- error.is_a?(Errors::BlockArgumentError) ||
243
- error.is_a?(Errors::MissingBlockError) ||
244
- error.is_a?(Errors::UnexpectedBlockError)
245
- end
246
- end
247
-
248
- unless no_arity_errors.empty?
249
- # Choose a error set which doesn't include arity error
250
- return no_arity_errors[0] if no_arity_errors.size == 1
251
- end
252
- end
253
- end
254
-
255
- def self.backtrace(skip: 2)
256
- raise
257
- rescue => exn
258
- exn.backtrace.drop(skip)
259
- end
260
-
261
- def run
262
- yield
263
- self
264
- ensure
265
- disable
266
- end
267
-
268
- def call(receiver, method, *args, &block)
269
- method.bind(receiver).call(*args, &block)
270
- end
271
-
272
- def inspect_(obj)
273
- Hook.inspect_(obj)
274
- end
275
-
276
- def self.inspect_(obj)
277
- obj.inspect
278
- rescue
279
- INSPECT.bind(obj).call()
280
- end
281
-
282
- def disable
283
- self.instance_module.remove_method(*instance_methods)
284
- self.singleton_module.remove_method(*singleton_methods)
285
- self
286
- end
287
- end
288
- end
289
- end
290
- end
@@ -1,58 +0,0 @@
1
- require "ruby/signature"
2
- require "ruby/signature/test"
3
-
4
- require "optparse"
5
- require "shellwords"
6
-
7
- logger = Logger.new(STDERR)
8
-
9
- begin
10
- opts = Shellwords.shellsplit(ENV["RBS_TEST_OPT"] || "-I sig")
11
- filter = ENV.fetch("RBS_TEST_TARGET").split(",")
12
- skips = (ENV["RBS_TEST_SKIP"] || "").split(",")
13
- logger.level = (ENV["RBS_TEST_LOGLEVEL"] || "info")
14
- raise_on_error = ENV["RBS_TEST_RAISE"]
15
- rescue
16
- STDERR.puts "ruby/signature/test/setup handles the following environment variables:"
17
- STDERR.puts " [REQUIRED] RBS_TEST_TARGET: test target class name, `Foo::Bar,Foo::Baz` for each class or `Foo::*` for all classes under `Foo`"
18
- STDERR.puts " [OPTIONAL] RBS_TEST_SKIP: skip testing classes"
19
- STDERR.puts " [OPTIONAL] RBS_TEST_OPT: options for signatures (`-r` for libraries or `-I` for signatures)"
20
- STDERR.puts " [OPTIONAL] RBS_TEST_LOGLEVEL: one of debug|info|warn|error|fatal (defaults to info)"
21
- STDERR.puts " [OPTIONAL] RBS_TEST_RAISE: specify any value to raise an exception when type error is detected"
22
- exit 1
23
- end
24
-
25
- hooks = []
26
-
27
- env = Ruby::Signature::Environment.new
28
-
29
- loader = Ruby::Signature::EnvironmentLoader.new
30
- OptionParser.new do |opts|
31
- opts.on("-r [LIB]") do |name| loader.add(library: name) end
32
- opts.on("-I [DIR]") do |dir| loader.add(path: Pathname(dir)) end
33
- end.parse!(opts)
34
- loader.load(env: env)
35
-
36
- def match(filter, name)
37
- if filter.end_with?("*")
38
- name.start_with?(filter[0, filter.size - 1]) || name == filter[0, filter.size-3]
39
- else
40
- filter == name
41
- end
42
- end
43
-
44
- TracePoint.trace :end do |tp|
45
- class_name = tp.self.name
46
-
47
- if class_name
48
- if filter.any? {|f| match(f, class_name) } && skips.none? {|f| match(f, class_name) }
49
- type_name = Ruby::Signature::Namespace.parse(class_name).absolute!.to_type_name
50
- if hooks.none? {|hook| hook.klass == tp.self }
51
- if env.find_class(type_name)
52
- logger.info "Setting up hooks for #{class_name}"
53
- hooks << Ruby::Signature::Test::Hook.install(env, tp.self, logger: logger).verify_all.raise_on_error!(raise_on_error)
54
- end
55
- end
56
- end
57
- end
58
- end
@@ -1,327 +0,0 @@
1
- module Ruby
2
- module Signature
3
- module Test
4
- module Spy
5
- def self.singleton_method(object, method_name)
6
- spy = SingletonSpy.new(object: object, method_name: method_name)
7
-
8
- if block_given?
9
- begin
10
- spy.setup
11
- yield spy
12
- ensure
13
- spy.reset
14
- end
15
- else
16
- spy
17
- end
18
- end
19
-
20
- def self.instance_method(mod, method_name)
21
- spy = InstanceSpy.new(mod: mod, method_name: method_name)
22
-
23
- if block_given?
24
- begin
25
- spy.setup
26
- yield spy
27
- ensure
28
- spy.reset
29
- end
30
- else
31
- spy
32
- end
33
- end
34
-
35
- def self.wrap(object, method_name)
36
- spy = WrapSpy.new(object: object, method_name: method_name)
37
-
38
- if block_given?
39
- begin
40
- yield spy, spy.wrapped_object
41
- end
42
- else
43
- spy
44
- end
45
- end
46
-
47
- class SingletonSpy
48
- attr_accessor :callback
49
- attr_reader :method_name
50
- attr_reader :object
51
-
52
- def initialize(object:, method_name:)
53
- @object = object
54
- @method_name = method_name
55
- @callback = -> (_) { }
56
- end
57
-
58
- def setup
59
- spy = self
60
-
61
- object.singleton_class.class_eval do
62
- remove_method spy.method_name
63
- define_method spy.method_name, spy.spy()
64
- end
65
- end
66
-
67
- def spy()
68
- spy = self
69
-
70
- -> (*args, &block) do
71
- return_value = nil
72
- exception = nil
73
- block_calls = []
74
-
75
- spy_block = if block
76
- Object.new.instance_eval do |fresh|
77
- -> (*block_args) do
78
- block_exn = nil
79
- block_return = nil
80
-
81
- begin
82
- block_return = if self.equal?(fresh)
83
- # no instance eval
84
- block.call(*block_args)
85
- else
86
- self.instance_exec(*block_args, &block)
87
- end
88
- rescue Exception => exn
89
- block_exn = exn
90
- end
91
-
92
- block_calls << ArgumentsReturn.new(
93
- arguments: block_args,
94
- return_value: block_return,
95
- exception: block_exn
96
- )
97
-
98
- if block_exn
99
- raise block_exn
100
- else
101
- block_return
102
- end
103
- end.ruby2_keywords
104
- end
105
- end
106
-
107
- begin
108
- return_value = super(*args, &spy_block)
109
- rescue Exception => exn
110
- exception = exn
111
- end
112
-
113
- trace = CallTrace.new(
114
- method_name: spy.method_name,
115
- method_call: ArgumentsReturn.new(
116
- arguments: args,
117
- return_value: return_value,
118
- exception: exception,
119
- ),
120
- block_calls: block_calls,
121
- block_given: block != nil
122
- )
123
-
124
- spy.callback.call(trace)
125
-
126
- if exception
127
- raise exception
128
- else
129
- return_value
130
- end
131
- end.ruby2_keywords
132
- end
133
-
134
- def reset
135
- if object.singleton_class.methods.include?(method_name)
136
- object.singleton_class.remove_method method_name
137
- end
138
- end
139
- end
140
-
141
- class InstanceSpy
142
- attr_accessor :callback
143
- attr_reader :mod
144
- attr_reader :method_name
145
- attr_reader :original_method
146
-
147
- def initialize(mod:, method_name:)
148
- @mod = mod
149
- @method_name = method_name
150
- @original_method = mod.instance_method(method_name)
151
- @callback = -> (_) { }
152
- end
153
-
154
- def setup
155
- spy = self
156
-
157
- mod.class_eval do
158
- remove_method spy.method_name
159
- define_method spy.method_name, spy.spy()
160
- end
161
- end
162
-
163
- def reset
164
- spy = self
165
-
166
- mod.class_eval do
167
- remove_method spy.method_name
168
- define_method spy.method_name, spy.original_method
169
- end
170
- end
171
-
172
- def spy
173
- spy = self
174
-
175
- -> (*args, &block) do
176
- return_value = nil
177
- exception = nil
178
- block_calls = []
179
-
180
- spy_block = if block
181
- Object.new.instance_eval do |fresh|
182
- -> (*block_args) do
183
- block_exn = nil
184
- block_return = nil
185
-
186
- begin
187
- block_return = if self.equal?(fresh)
188
- # no instance eval
189
- block.call(*block_args)
190
- else
191
- self.instance_exec(*block_args, &block)
192
- end
193
- rescue Exception => exn
194
- block_exn = exn
195
- end
196
-
197
- block_calls << ArgumentsReturn.new(
198
- arguments: block_args,
199
- return_value: block_return,
200
- exception: block_exn
201
- )
202
-
203
- if block_exn
204
- raise block_exn
205
- else
206
- block_return
207
- end
208
- end.ruby2_keywords
209
- end
210
- end
211
-
212
- begin
213
- return_value = spy.original_method.bind_call(self, *args, &spy_block)
214
- rescue Exception => exn
215
- exception = exn
216
- end
217
-
218
- trace = CallTrace.new(
219
- method_name: spy.method_name,
220
- method_call: ArgumentsReturn.new(
221
- arguments: args,
222
- return_value: return_value,
223
- exception: exception,
224
- ),
225
- block_calls: block_calls,
226
- block_given: block != nil
227
- )
228
-
229
- spy.callback.call(trace)
230
-
231
- if exception
232
- raise exception
233
- else
234
- return_value
235
- end
236
- end.ruby2_keywords
237
- end
238
- end
239
-
240
- class WrapSpy
241
- attr_accessor :callback
242
- attr_reader :object
243
- attr_reader :method_name
244
-
245
- def initialize(object:, method_name:)
246
- @callback = -> (_) { }
247
- @object = object
248
- @method_name = method_name
249
- end
250
-
251
- def wrapped_object
252
- spy = self
253
-
254
- Class.new(BasicObject) do
255
- define_method(:method_missing) do |name, *args, &block|
256
- spy.object.__send__(name, *args, &block)
257
- end
258
-
259
- define_method(spy.method_name, -> (*args, &block) {
260
- return_value = nil
261
- exception = nil
262
- block_calls = []
263
-
264
- spy_block = if block
265
- Object.new.instance_eval do |fresh|
266
- -> (*block_args) do
267
- block_exn = nil
268
- block_return = nil
269
-
270
- begin
271
- block_return = if self.equal?(fresh)
272
- # no instance eval
273
- block.call(*block_args)
274
- else
275
- self.instance_exec(*block_args, &block)
276
- end
277
- rescue Exception => exn
278
- block_exn = exn
279
- end
280
-
281
- block_calls << ArgumentsReturn.new(
282
- arguments: block_args,
283
- return_value: block_return,
284
- exception: block_exn
285
- )
286
-
287
- if block_exn
288
- raise block_exn
289
- else
290
- block_return
291
- end
292
- end.ruby2_keywords
293
- end
294
- end
295
-
296
- begin
297
- return_value = spy.object.__send__(spy.method_name, *args, &spy_block)
298
- rescue ::Exception => exn
299
- exception = exn
300
- end
301
-
302
- trace = CallTrace.new(
303
- method_name: spy.method_name,
304
- method_call: ArgumentsReturn.new(
305
- arguments: args,
306
- return_value: return_value,
307
- exception: exception,
308
- ),
309
- block_calls: block_calls,
310
- block_given: block != nil
311
- )
312
-
313
- spy.callback.call(trace)
314
-
315
- if exception
316
- spy.object.__send__(:raise, exception)
317
- else
318
- return_value
319
- end
320
- }.ruby2_keywords)
321
- end.new()
322
- end
323
- end
324
- end
325
- end
326
- end
327
- end