steep 0.13.0 → 0.16.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +0 -3
  3. data/CHANGELOG.md +28 -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 +33 -1
  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 +124 -89
  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/init.rb +5 -5
  17. data/lib/steep/drivers/langserver.rb +13 -287
  18. data/lib/steep/drivers/utils/driver_helper.rb +1 -1
  19. data/lib/steep/drivers/vendor.rb +2 -2
  20. data/lib/steep/drivers/watch.rb +97 -85
  21. data/lib/steep/drivers/worker.rb +51 -0
  22. data/lib/steep/project.rb +9 -5
  23. data/lib/steep/project/completion_provider.rb +298 -0
  24. data/lib/steep/project/dsl.rb +14 -0
  25. data/lib/steep/project/file.rb +54 -47
  26. data/lib/steep/project/hover_content.rb +17 -8
  27. data/lib/steep/project/options.rb +25 -3
  28. data/lib/steep/project/target.rb +40 -24
  29. data/lib/steep/server/base_worker.rb +56 -0
  30. data/lib/steep/server/code_worker.rb +151 -0
  31. data/lib/steep/server/interaction_worker.rb +281 -0
  32. data/lib/steep/server/master.rb +196 -0
  33. data/lib/steep/server/signature_worker.rb +148 -0
  34. data/lib/steep/server/utils.rb +36 -0
  35. data/lib/steep/server/worker_process.rb +62 -0
  36. data/lib/steep/signature/errors.rb +1 -1
  37. data/lib/steep/signature/validator.rb +13 -13
  38. data/lib/steep/source.rb +1 -1
  39. data/lib/steep/type_construction.rb +1004 -727
  40. data/lib/steep/type_inference/constant_env.rb +3 -11
  41. data/lib/steep/type_inference/context.rb +8 -3
  42. data/lib/steep/type_inference/context_array.rb +111 -0
  43. data/lib/steep/type_inference/local_variable_type_env.rb +226 -0
  44. data/lib/steep/type_inference/logic.rb +130 -0
  45. data/lib/steep/type_inference/type_env.rb +5 -69
  46. data/lib/steep/typing.rb +91 -23
  47. data/lib/steep/version.rb +1 -1
  48. data/smoke/alias/Steepfile +1 -0
  49. data/smoke/alias/a.rb +1 -1
  50. data/smoke/and/Steepfile +1 -0
  51. data/smoke/array/Steepfile +1 -0
  52. data/smoke/array/b.rb +0 -2
  53. data/smoke/block/Steepfile +1 -0
  54. data/smoke/case/Steepfile +1 -0
  55. data/smoke/class/Steepfile +1 -0
  56. data/smoke/const/Steepfile +1 -0
  57. data/smoke/dstr/Steepfile +1 -0
  58. data/smoke/ensure/Steepfile +1 -0
  59. data/smoke/enumerator/Steepfile +1 -0
  60. data/smoke/extension/Steepfile +1 -0
  61. data/smoke/extension/c.rb +1 -0
  62. data/smoke/hash/Steepfile +1 -0
  63. data/smoke/hello/Steepfile +1 -0
  64. data/smoke/if/Steepfile +1 -0
  65. data/smoke/if/a.rb +1 -1
  66. data/smoke/implements/Steepfile +1 -0
  67. data/smoke/initialize/Steepfile +1 -0
  68. data/smoke/integer/Steepfile +1 -0
  69. data/smoke/interface/Steepfile +1 -0
  70. data/smoke/kwbegin/Steepfile +1 -0
  71. data/smoke/lambda/Steepfile +1 -0
  72. data/smoke/literal/Steepfile +1 -0
  73. data/smoke/map/Steepfile +1 -0
  74. data/smoke/method/Steepfile +1 -0
  75. data/smoke/module/Steepfile +1 -0
  76. data/smoke/regexp/Steepfile +1 -0
  77. data/smoke/regexp/b.rb +4 -4
  78. data/smoke/regression/Steepfile +1 -0
  79. data/smoke/rescue/Steepfile +1 -0
  80. data/smoke/rescue/a.rb +1 -1
  81. data/smoke/self/Steepfile +1 -0
  82. data/smoke/skip/Steepfile +1 -0
  83. data/smoke/stdout/Steepfile +1 -0
  84. data/smoke/super/Steepfile +1 -0
  85. data/smoke/type_case/Steepfile +1 -0
  86. data/smoke/yield/Steepfile +1 -0
  87. data/steep.gemspec +8 -8
  88. metadata +38 -138
  89. data/exe/rbs +0 -3
  90. data/exe/ruby-signature +0 -3
  91. data/vendor/ruby-signature/.github/workflows/ruby.yml +0 -27
  92. data/vendor/ruby-signature/.gitignore +0 -12
  93. data/vendor/ruby-signature/.rubocop.yml +0 -15
  94. data/vendor/ruby-signature/BSDL +0 -22
  95. data/vendor/ruby-signature/COPYING +0 -56
  96. data/vendor/ruby-signature/Gemfile +0 -6
  97. data/vendor/ruby-signature/README.md +0 -93
  98. data/vendor/ruby-signature/Rakefile +0 -66
  99. data/vendor/ruby-signature/bin/annotate-with-rdoc +0 -156
  100. data/vendor/ruby-signature/bin/console +0 -14
  101. data/vendor/ruby-signature/bin/query-rdoc +0 -103
  102. data/vendor/ruby-signature/bin/setup +0 -10
  103. data/vendor/ruby-signature/bin/sort +0 -88
  104. data/vendor/ruby-signature/bin/test_runner.rb +0 -17
  105. data/vendor/ruby-signature/docs/CONTRIBUTING.md +0 -97
  106. data/vendor/ruby-signature/docs/sigs.md +0 -148
  107. data/vendor/ruby-signature/docs/stdlib.md +0 -152
  108. data/vendor/ruby-signature/docs/syntax.md +0 -528
  109. data/vendor/ruby-signature/exe/rbs +0 -3
  110. data/vendor/ruby-signature/exe/ruby-signature +0 -7
  111. data/vendor/ruby-signature/lib/ruby/signature.rb +0 -64
  112. data/vendor/ruby-signature/lib/ruby/signature/ast/annotation.rb +0 -29
  113. data/vendor/ruby-signature/lib/ruby/signature/ast/comment.rb +0 -29
  114. data/vendor/ruby-signature/lib/ruby/signature/ast/declarations.rb +0 -391
  115. data/vendor/ruby-signature/lib/ruby/signature/ast/members.rb +0 -364
  116. data/vendor/ruby-signature/lib/ruby/signature/buffer.rb +0 -52
  117. data/vendor/ruby-signature/lib/ruby/signature/builtin_names.rb +0 -54
  118. data/vendor/ruby-signature/lib/ruby/signature/cli.rb +0 -534
  119. data/vendor/ruby-signature/lib/ruby/signature/constant.rb +0 -28
  120. data/vendor/ruby-signature/lib/ruby/signature/constant_table.rb +0 -152
  121. data/vendor/ruby-signature/lib/ruby/signature/definition.rb +0 -172
  122. data/vendor/ruby-signature/lib/ruby/signature/definition_builder.rb +0 -921
  123. data/vendor/ruby-signature/lib/ruby/signature/environment.rb +0 -283
  124. data/vendor/ruby-signature/lib/ruby/signature/environment_loader.rb +0 -138
  125. data/vendor/ruby-signature/lib/ruby/signature/environment_walker.rb +0 -126
  126. data/vendor/ruby-signature/lib/ruby/signature/errors.rb +0 -189
  127. data/vendor/ruby-signature/lib/ruby/signature/location.rb +0 -104
  128. data/vendor/ruby-signature/lib/ruby/signature/method_type.rb +0 -125
  129. data/vendor/ruby-signature/lib/ruby/signature/namespace.rb +0 -93
  130. data/vendor/ruby-signature/lib/ruby/signature/parser.y +0 -1343
  131. data/vendor/ruby-signature/lib/ruby/signature/prototype/rb.rb +0 -441
  132. data/vendor/ruby-signature/lib/ruby/signature/prototype/rbi.rb +0 -579
  133. data/vendor/ruby-signature/lib/ruby/signature/prototype/runtime.rb +0 -383
  134. data/vendor/ruby-signature/lib/ruby/signature/substitution.rb +0 -48
  135. data/vendor/ruby-signature/lib/ruby/signature/test.rb +0 -28
  136. data/vendor/ruby-signature/lib/ruby/signature/test/errors.rb +0 -63
  137. data/vendor/ruby-signature/lib/ruby/signature/test/hook.rb +0 -290
  138. data/vendor/ruby-signature/lib/ruby/signature/test/setup.rb +0 -58
  139. data/vendor/ruby-signature/lib/ruby/signature/test/spy.rb +0 -324
  140. data/vendor/ruby-signature/lib/ruby/signature/test/test_helper.rb +0 -185
  141. data/vendor/ruby-signature/lib/ruby/signature/test/type_check.rb +0 -256
  142. data/vendor/ruby-signature/lib/ruby/signature/type_name.rb +0 -72
  143. data/vendor/ruby-signature/lib/ruby/signature/types.rb +0 -932
  144. data/vendor/ruby-signature/lib/ruby/signature/variance_calculator.rb +0 -140
  145. data/vendor/ruby-signature/lib/ruby/signature/vendorer.rb +0 -49
  146. data/vendor/ruby-signature/lib/ruby/signature/version.rb +0 -5
  147. data/vendor/ruby-signature/lib/ruby/signature/writer.rb +0 -271
  148. data/vendor/ruby-signature/ruby-signature.gemspec +0 -45
  149. data/vendor/ruby-signature/stdlib/abbrev/abbrev.rbs +0 -3
  150. data/vendor/ruby-signature/stdlib/base64/base64.rbs +0 -15
  151. data/vendor/ruby-signature/stdlib/builtin/array.rbs +0 -1997
  152. data/vendor/ruby-signature/stdlib/builtin/basic_object.rbs +0 -280
  153. data/vendor/ruby-signature/stdlib/builtin/binding.rbs +0 -177
  154. data/vendor/ruby-signature/stdlib/builtin/builtin.rbs +0 -35
  155. data/vendor/ruby-signature/stdlib/builtin/class.rbs +0 -145
  156. data/vendor/ruby-signature/stdlib/builtin/comparable.rbs +0 -116
  157. data/vendor/ruby-signature/stdlib/builtin/complex.rbs +0 -400
  158. data/vendor/ruby-signature/stdlib/builtin/constants.rbs +0 -37
  159. data/vendor/ruby-signature/stdlib/builtin/data.rbs +0 -5
  160. data/vendor/ruby-signature/stdlib/builtin/deprecated.rbs +0 -2
  161. data/vendor/ruby-signature/stdlib/builtin/dir.rbs +0 -419
  162. data/vendor/ruby-signature/stdlib/builtin/encoding.rbs +0 -606
  163. data/vendor/ruby-signature/stdlib/builtin/enumerable.rbs +0 -404
  164. data/vendor/ruby-signature/stdlib/builtin/enumerator.rbs +0 -260
  165. data/vendor/ruby-signature/stdlib/builtin/errno.rbs +0 -781
  166. data/vendor/ruby-signature/stdlib/builtin/errors.rbs +0 -582
  167. data/vendor/ruby-signature/stdlib/builtin/exception.rbs +0 -193
  168. data/vendor/ruby-signature/stdlib/builtin/false_class.rbs +0 -40
  169. data/vendor/ruby-signature/stdlib/builtin/fiber.rbs +0 -68
  170. data/vendor/ruby-signature/stdlib/builtin/fiber_error.rbs +0 -12
  171. data/vendor/ruby-signature/stdlib/builtin/file.rbs +0 -476
  172. data/vendor/ruby-signature/stdlib/builtin/file_test.rbs +0 -59
  173. data/vendor/ruby-signature/stdlib/builtin/float.rbs +0 -696
  174. data/vendor/ruby-signature/stdlib/builtin/gc.rbs +0 -121
  175. data/vendor/ruby-signature/stdlib/builtin/hash.rbs +0 -1029
  176. data/vendor/ruby-signature/stdlib/builtin/integer.rbs +0 -710
  177. data/vendor/ruby-signature/stdlib/builtin/io.rbs +0 -683
  178. data/vendor/ruby-signature/stdlib/builtin/kernel.rbs +0 -574
  179. data/vendor/ruby-signature/stdlib/builtin/marshal.rbs +0 -135
  180. data/vendor/ruby-signature/stdlib/builtin/match_data.rbs +0 -141
  181. data/vendor/ruby-signature/stdlib/builtin/math.rbs +0 -66
  182. data/vendor/ruby-signature/stdlib/builtin/method.rbs +0 -182
  183. data/vendor/ruby-signature/stdlib/builtin/module.rbs +0 -248
  184. data/vendor/ruby-signature/stdlib/builtin/nil_class.rbs +0 -82
  185. data/vendor/ruby-signature/stdlib/builtin/numeric.rbs +0 -409
  186. data/vendor/ruby-signature/stdlib/builtin/object.rbs +0 -824
  187. data/vendor/ruby-signature/stdlib/builtin/proc.rbs +0 -426
  188. data/vendor/ruby-signature/stdlib/builtin/process.rbs +0 -354
  189. data/vendor/ruby-signature/stdlib/builtin/random.rbs +0 -93
  190. data/vendor/ruby-signature/stdlib/builtin/range.rbs +0 -226
  191. data/vendor/ruby-signature/stdlib/builtin/rational.rbs +0 -424
  192. data/vendor/ruby-signature/stdlib/builtin/rb_config.rbs +0 -10
  193. data/vendor/ruby-signature/stdlib/builtin/regexp.rbs +0 -131
  194. data/vendor/ruby-signature/stdlib/builtin/ruby_vm.rbs +0 -14
  195. data/vendor/ruby-signature/stdlib/builtin/signal.rbs +0 -55
  196. data/vendor/ruby-signature/stdlib/builtin/string.rbs +0 -770
  197. data/vendor/ruby-signature/stdlib/builtin/string_io.rbs +0 -13
  198. data/vendor/ruby-signature/stdlib/builtin/struct.rbs +0 -40
  199. data/vendor/ruby-signature/stdlib/builtin/symbol.rbs +0 -230
  200. data/vendor/ruby-signature/stdlib/builtin/thread.rbs +0 -1112
  201. data/vendor/ruby-signature/stdlib/builtin/thread_group.rbs +0 -23
  202. data/vendor/ruby-signature/stdlib/builtin/time.rbs +0 -739
  203. data/vendor/ruby-signature/stdlib/builtin/trace_point.rbs +0 -91
  204. data/vendor/ruby-signature/stdlib/builtin/true_class.rbs +0 -46
  205. data/vendor/ruby-signature/stdlib/builtin/unbound_method.rbs +0 -159
  206. data/vendor/ruby-signature/stdlib/builtin/warning.rbs +0 -17
  207. data/vendor/ruby-signature/stdlib/erb/erb.rbs +0 -18
  208. data/vendor/ruby-signature/stdlib/find/find.rbs +0 -44
  209. data/vendor/ruby-signature/stdlib/pathname/pathname.rbs +0 -21
  210. data/vendor/ruby-signature/stdlib/prime/integer-extension.rbs +0 -23
  211. data/vendor/ruby-signature/stdlib/prime/prime.rbs +0 -188
  212. data/vendor/ruby-signature/stdlib/securerandom/securerandom.rbs +0 -9
  213. data/vendor/ruby-signature/stdlib/set/set.rbs +0 -77
  214. 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,324 +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
- define_method spy.method_name, spy.spy()
63
- end
64
- end
65
-
66
- def spy()
67
- spy = self
68
-
69
- -> (*args, &block) do
70
- return_value = nil
71
- exception = nil
72
- block_calls = []
73
-
74
- spy_block = if block
75
- Object.new.instance_eval do |fresh|
76
- -> (*block_args) do
77
- block_exn = nil
78
- block_return = nil
79
-
80
- begin
81
- block_return = if self.equal?(fresh)
82
- # no instance eval
83
- block.call(*block_args)
84
- else
85
- self.instance_exec(*block_args, &block)
86
- end
87
- rescue Exception => exn
88
- block_exn = exn
89
- end
90
-
91
- block_calls << ArgumentsReturn.new(
92
- arguments: block_args,
93
- return_value: block_return,
94
- exception: block_exn
95
- )
96
-
97
- if block_exn
98
- raise block_exn
99
- else
100
- block_return
101
- end
102
- end.ruby2_keywords
103
- end
104
- end
105
-
106
- begin
107
- return_value = super(*args, &spy_block)
108
- rescue Exception => exn
109
- exception = exn
110
- end
111
-
112
- trace = CallTrace.new(
113
- method_name: spy.method_name,
114
- method_call: ArgumentsReturn.new(
115
- arguments: args,
116
- return_value: return_value,
117
- exception: exception,
118
- ),
119
- block_calls: block_calls,
120
- block_given: block != nil
121
- )
122
-
123
- spy.callback.call(trace)
124
-
125
- if exception
126
- raise exception
127
- else
128
- return_value
129
- end
130
- end.ruby2_keywords
131
- end
132
-
133
- def reset
134
- if object.singleton_class.methods.include?(method_name)
135
- object.singleton_class.remove_method method_name
136
- end
137
- end
138
- end
139
-
140
- class InstanceSpy
141
- attr_accessor :callback
142
- attr_reader :mod
143
- attr_reader :method_name
144
- attr_reader :original_method
145
-
146
- def initialize(mod:, method_name:)
147
- @mod = mod
148
- @method_name = method_name
149
- @original_method = mod.instance_method(method_name)
150
- @callback = -> (_) { }
151
- end
152
-
153
- def setup
154
- spy = self
155
-
156
- mod.class_eval do
157
- define_method spy.method_name, spy.spy()
158
- end
159
- end
160
-
161
- def reset
162
- spy = self
163
-
164
- mod.class_eval do
165
- define_method spy.method_name, spy.original_method
166
- end
167
- end
168
-
169
- def spy
170
- spy = self
171
-
172
- -> (*args, &block) do
173
- return_value = nil
174
- exception = nil
175
- block_calls = []
176
-
177
- spy_block = if block
178
- Object.new.instance_eval do |fresh|
179
- -> (*block_args) do
180
- block_exn = nil
181
- block_return = nil
182
-
183
- begin
184
- block_return = if self.equal?(fresh)
185
- # no instance eval
186
- block.call(*block_args)
187
- else
188
- self.instance_exec(*block_args, &block)
189
- end
190
- rescue Exception => exn
191
- block_exn = exn
192
- end
193
-
194
- block_calls << ArgumentsReturn.new(
195
- arguments: block_args,
196
- return_value: block_return,
197
- exception: block_exn
198
- )
199
-
200
- if block_exn
201
- raise block_exn
202
- else
203
- block_return
204
- end
205
- end.ruby2_keywords
206
- end
207
- end
208
-
209
- begin
210
- return_value = spy.original_method.bind_call(self, *args, &spy_block)
211
- rescue Exception => exn
212
- exception = exn
213
- end
214
-
215
- trace = CallTrace.new(
216
- method_name: spy.method_name,
217
- method_call: ArgumentsReturn.new(
218
- arguments: args,
219
- return_value: return_value,
220
- exception: exception,
221
- ),
222
- block_calls: block_calls,
223
- block_given: block != nil
224
- )
225
-
226
- spy.callback.call(trace)
227
-
228
- if exception
229
- raise exception
230
- else
231
- return_value
232
- end
233
- end.ruby2_keywords
234
- end
235
- end
236
-
237
- class WrapSpy
238
- attr_accessor :callback
239
- attr_reader :object
240
- attr_reader :method_name
241
-
242
- def initialize(object:, method_name:)
243
- @callback = -> (_) { }
244
- @object = object
245
- @method_name = method_name
246
- end
247
-
248
- def wrapped_object
249
- spy = self
250
-
251
- Class.new(BasicObject) do
252
- define_method(:method_missing) do |name, *args, &block|
253
- spy.object.__send__(name, *args, &block)
254
- end
255
-
256
- define_method(spy.method_name, -> (*args, &block) {
257
- return_value = nil
258
- exception = nil
259
- block_calls = []
260
-
261
- spy_block = if block
262
- Object.new.instance_eval do |fresh|
263
- -> (*block_args) do
264
- block_exn = nil
265
- block_return = nil
266
-
267
- begin
268
- block_return = if self.equal?(fresh)
269
- # no instance eval
270
- block.call(*block_args)
271
- else
272
- self.instance_exec(*block_args, &block)
273
- end
274
- rescue Exception => exn
275
- block_exn = exn
276
- end
277
-
278
- block_calls << ArgumentsReturn.new(
279
- arguments: block_args,
280
- return_value: block_return,
281
- exception: block_exn
282
- )
283
-
284
- if block_exn
285
- raise block_exn
286
- else
287
- block_return
288
- end
289
- end.ruby2_keywords
290
- end
291
- end
292
-
293
- begin
294
- return_value = spy.object.__send__(spy.method_name, *args, &spy_block)
295
- rescue ::Exception => exn
296
- exception = exn
297
- end
298
-
299
- trace = CallTrace.new(
300
- method_name: spy.method_name,
301
- method_call: ArgumentsReturn.new(
302
- arguments: args,
303
- return_value: return_value,
304
- exception: exception,
305
- ),
306
- block_calls: block_calls,
307
- block_given: block != nil
308
- )
309
-
310
- spy.callback.call(trace)
311
-
312
- if exception
313
- spy.object.__send__(:raise, exception)
314
- else
315
- return_value
316
- end
317
- }.ruby2_keywords)
318
- end.new()
319
- end
320
- end
321
- end
322
- end
323
- end
324
- end