steep 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (299) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +27 -0
  3. data/.gitmodules +3 -0
  4. data/CHANGELOG.md +5 -0
  5. data/README.md +48 -90
  6. data/Rakefile +10 -6
  7. data/Steepfile +1 -0
  8. data/bin/setup +1 -0
  9. data/bin/smoke_runner.rb +9 -14
  10. data/exe/rbs +3 -0
  11. data/exe/ruby-signature +3 -0
  12. data/exe/steep +1 -0
  13. data/lib/steep.rb +32 -26
  14. data/lib/steep/annotation_parser.rb +167 -0
  15. data/lib/steep/ast/annotation/collection.rb +7 -7
  16. data/lib/steep/ast/types.rb +60 -0
  17. data/lib/steep/ast/types/any.rb +1 -1
  18. data/lib/steep/ast/types/factory.rb +535 -0
  19. data/lib/steep/ast/types/name.rb +3 -3
  20. data/lib/steep/ast/types/var.rb +1 -1
  21. data/lib/steep/cli.rb +56 -240
  22. data/lib/steep/drivers/annotations.rb +36 -19
  23. data/lib/steep/drivers/check.rb +55 -91
  24. data/lib/steep/drivers/init.rb +54 -0
  25. data/lib/steep/drivers/langserver.rb +241 -150
  26. data/lib/steep/drivers/print_project.rb +56 -0
  27. data/lib/steep/drivers/signature_error_printer.rb +25 -0
  28. data/lib/steep/drivers/trace_printer.rb +25 -0
  29. data/lib/steep/drivers/utils/driver_helper.rb +26 -0
  30. data/lib/steep/drivers/validate.rb +18 -38
  31. data/lib/steep/drivers/vendor.rb +46 -0
  32. data/lib/steep/drivers/watch.rb +78 -140
  33. data/lib/steep/errors.rb +22 -13
  34. data/lib/steep/interface/interface.rb +91 -0
  35. data/lib/steep/interface/method.rb +0 -4
  36. data/lib/steep/interface/method_type.rb +362 -2
  37. data/lib/steep/interface/substitution.rb +22 -0
  38. data/lib/steep/project.rb +25 -233
  39. data/lib/steep/project/dsl.rb +132 -0
  40. data/lib/steep/project/file.rb +93 -76
  41. data/lib/steep/project/file_loader.rb +63 -0
  42. data/lib/steep/project/options.rb +7 -0
  43. data/lib/steep/project/target.rb +190 -0
  44. data/lib/steep/signature/errors.rb +25 -77
  45. data/lib/steep/signature/validator.rb +122 -0
  46. data/lib/steep/source.rb +12 -7
  47. data/lib/steep/subtyping/check.rb +357 -633
  48. data/lib/steep/subtyping/constraints.rb +2 -2
  49. data/lib/steep/subtyping/trace.rb +23 -0
  50. data/lib/steep/type_construction.rb +509 -455
  51. data/lib/steep/type_inference/constant_env.rb +16 -24
  52. data/lib/steep/type_inference/type_env.rb +26 -18
  53. data/lib/steep/version.rb +1 -1
  54. data/sample/Steepfile +6 -0
  55. data/sample/lib/conference.rb +12 -0
  56. data/sample/sig/conference.rbs +6 -0
  57. data/smoke/alias/Steepfile +4 -0
  58. data/smoke/alias/a.rb +2 -2
  59. data/smoke/alias/{a.rbi → a.rbs} +1 -1
  60. data/smoke/and/Steepfile +4 -0
  61. data/smoke/array/Steepfile +4 -0
  62. data/smoke/array/a.rb +2 -2
  63. data/smoke/array/b.rb +4 -4
  64. data/smoke/array/c.rb +2 -2
  65. data/smoke/block/Steepfile +5 -0
  66. data/smoke/block/{a.rbi → a.rbs} +1 -1
  67. data/smoke/block/{c.rbi → c.rbs} +0 -0
  68. data/smoke/block/d.rb +6 -6
  69. data/smoke/case/Steepfile +4 -0
  70. data/smoke/case/a.rb +4 -3
  71. data/smoke/class/Steepfile +4 -0
  72. data/smoke/class/a.rb +1 -4
  73. data/smoke/class/a.rbs +24 -0
  74. data/smoke/class/h.rb +6 -2
  75. data/smoke/class/{h.rbi → h.rbs} +1 -2
  76. data/smoke/class/i.rb +1 -2
  77. data/smoke/class/i.rbs +9 -0
  78. data/smoke/const/Steepfile +4 -0
  79. data/smoke/dstr/Steepfile +4 -0
  80. data/smoke/ensure/Steepfile +4 -0
  81. data/smoke/ensure/a.rb +1 -1
  82. data/smoke/enumerator/Steepfile +4 -0
  83. data/smoke/enumerator/a.rb +7 -7
  84. data/smoke/enumerator/b.rb +6 -6
  85. data/smoke/extension/Steepfile +4 -0
  86. data/smoke/extension/{a.rbi → a.rbs} +2 -2
  87. data/smoke/extension/{e.rbi → e.rbs} +2 -2
  88. data/smoke/hash/Steepfile +4 -0
  89. data/smoke/hash/{a.rbi → a.rbs} +0 -0
  90. data/smoke/hash/b.rb +2 -2
  91. data/smoke/hash/c.rb +1 -1
  92. data/smoke/hash/e.rbs +3 -0
  93. data/smoke/hash/f.rb +1 -1
  94. data/smoke/hello/Steepfile +4 -0
  95. data/smoke/hello/hello.rbs +7 -0
  96. data/smoke/if/Steepfile +4 -0
  97. data/smoke/implements/Steepfile +4 -0
  98. data/smoke/implements/a.rbs +6 -0
  99. data/smoke/initialize/Steepfile +4 -0
  100. data/smoke/initialize/a.rbs +3 -0
  101. data/smoke/integer/Steepfile +4 -0
  102. data/smoke/integer/a.rb +5 -3
  103. data/smoke/interface/Steepfile +4 -0
  104. data/smoke/interface/{a.rbi → a.rbs} +0 -0
  105. data/smoke/kwbegin/Steepfile +4 -0
  106. data/smoke/lambda/Steepfile +4 -0
  107. data/smoke/lambda/a.rb +9 -2
  108. data/smoke/literal/Steepfile +4 -0
  109. data/smoke/literal/{literal_methods.rbi → literal_methods.rbs} +0 -0
  110. data/smoke/map/Steepfile +4 -0
  111. data/smoke/map/a.rb +1 -1
  112. data/smoke/method/Steepfile +4 -0
  113. data/smoke/method/{a.rbi → a.rbs} +0 -0
  114. data/smoke/method/b.rb +1 -4
  115. data/smoke/method/d.rb +1 -0
  116. data/smoke/method/d.rbs +3 -0
  117. data/smoke/module/Steepfile +4 -0
  118. data/smoke/module/a.rb +1 -1
  119. data/smoke/module/a.rbs +16 -0
  120. data/smoke/module/c.rb +1 -1
  121. data/smoke/regexp/Steepfile +4 -0
  122. data/smoke/regexp/a.rb +2 -2
  123. data/smoke/regexp/b.rb +16 -16
  124. data/smoke/regression/Steepfile +5 -0
  125. data/smoke/regression/array.rb +2 -2
  126. data/smoke/regression/hash.rb +2 -2
  127. data/smoke/regression/poly_new.rb +2 -0
  128. data/smoke/regression/poly_new.rbs +4 -0
  129. data/smoke/regression/set_divide.rb +2 -2
  130. data/smoke/rescue/Steepfile +4 -0
  131. data/smoke/rescue/a.rb +1 -1
  132. data/smoke/self/Steepfile +4 -0
  133. data/smoke/self/a.rbs +4 -0
  134. data/smoke/skip/Steepfile +4 -0
  135. data/smoke/stdout/Steepfile +4 -0
  136. data/smoke/stdout/{a.rbi → a.rbs} +1 -1
  137. data/smoke/super/Steepfile +4 -0
  138. data/smoke/super/a.rbs +10 -0
  139. data/smoke/type_case/Steepfile +4 -0
  140. data/smoke/type_case/a.rb +1 -1
  141. data/smoke/yield/Steepfile +4 -0
  142. data/smoke/yield/a.rb +2 -2
  143. data/steep.gemspec +14 -7
  144. data/vendor/ruby-signature/.github/workflows/ruby.yml +27 -0
  145. data/vendor/ruby-signature/.gitignore +12 -0
  146. data/vendor/ruby-signature/.rubocop.yml +15 -0
  147. data/vendor/ruby-signature/BSDL +22 -0
  148. data/vendor/ruby-signature/COPYING +56 -0
  149. data/vendor/ruby-signature/Gemfile +6 -0
  150. data/vendor/ruby-signature/README.md +93 -0
  151. data/vendor/ruby-signature/Rakefile +66 -0
  152. data/vendor/ruby-signature/bin/annotate-with-rdoc +156 -0
  153. data/vendor/ruby-signature/bin/console +14 -0
  154. data/vendor/ruby-signature/bin/query-rdoc +103 -0
  155. data/vendor/ruby-signature/bin/setup +10 -0
  156. data/vendor/ruby-signature/bin/sort +88 -0
  157. data/vendor/ruby-signature/bin/test_runner.rb +17 -0
  158. data/vendor/ruby-signature/docs/CONTRIBUTING.md +97 -0
  159. data/vendor/ruby-signature/docs/sigs.md +148 -0
  160. data/vendor/ruby-signature/docs/stdlib.md +152 -0
  161. data/vendor/ruby-signature/docs/syntax.md +528 -0
  162. data/vendor/ruby-signature/exe/rbs +3 -0
  163. data/vendor/ruby-signature/exe/ruby-signature +7 -0
  164. data/vendor/ruby-signature/lib/ruby/signature.rb +64 -0
  165. data/vendor/ruby-signature/lib/ruby/signature/ast/annotation.rb +29 -0
  166. data/vendor/ruby-signature/lib/ruby/signature/ast/comment.rb +29 -0
  167. data/vendor/ruby-signature/lib/ruby/signature/ast/declarations.rb +391 -0
  168. data/vendor/ruby-signature/lib/ruby/signature/ast/members.rb +364 -0
  169. data/vendor/ruby-signature/lib/ruby/signature/buffer.rb +52 -0
  170. data/vendor/ruby-signature/lib/ruby/signature/builtin_names.rb +54 -0
  171. data/vendor/ruby-signature/lib/ruby/signature/cli.rb +534 -0
  172. data/vendor/ruby-signature/lib/ruby/signature/constant.rb +28 -0
  173. data/vendor/ruby-signature/lib/ruby/signature/constant_table.rb +152 -0
  174. data/vendor/ruby-signature/lib/ruby/signature/definition.rb +172 -0
  175. data/vendor/ruby-signature/lib/ruby/signature/definition_builder.rb +921 -0
  176. data/vendor/ruby-signature/lib/ruby/signature/environment.rb +283 -0
  177. data/vendor/ruby-signature/lib/ruby/signature/environment_loader.rb +138 -0
  178. data/vendor/ruby-signature/lib/ruby/signature/environment_walker.rb +126 -0
  179. data/vendor/ruby-signature/lib/ruby/signature/errors.rb +189 -0
  180. data/vendor/ruby-signature/lib/ruby/signature/location.rb +104 -0
  181. data/vendor/ruby-signature/lib/ruby/signature/method_type.rb +125 -0
  182. data/vendor/ruby-signature/lib/ruby/signature/namespace.rb +93 -0
  183. data/vendor/ruby-signature/lib/ruby/signature/parser.y +1343 -0
  184. data/vendor/ruby-signature/lib/ruby/signature/prototype/rb.rb +441 -0
  185. data/vendor/ruby-signature/lib/ruby/signature/prototype/rbi.rb +579 -0
  186. data/vendor/ruby-signature/lib/ruby/signature/prototype/runtime.rb +383 -0
  187. data/vendor/ruby-signature/lib/ruby/signature/substitution.rb +48 -0
  188. data/vendor/ruby-signature/lib/ruby/signature/test.rb +28 -0
  189. data/vendor/ruby-signature/lib/ruby/signature/test/errors.rb +63 -0
  190. data/vendor/ruby-signature/lib/ruby/signature/test/hook.rb +290 -0
  191. data/vendor/ruby-signature/lib/ruby/signature/test/setup.rb +58 -0
  192. data/vendor/ruby-signature/lib/ruby/signature/test/spy.rb +324 -0
  193. data/vendor/ruby-signature/lib/ruby/signature/test/test_helper.rb +185 -0
  194. data/vendor/ruby-signature/lib/ruby/signature/test/type_check.rb +256 -0
  195. data/vendor/ruby-signature/lib/ruby/signature/type_name.rb +72 -0
  196. data/vendor/ruby-signature/lib/ruby/signature/types.rb +932 -0
  197. data/vendor/ruby-signature/lib/ruby/signature/variance_calculator.rb +140 -0
  198. data/vendor/ruby-signature/lib/ruby/signature/vendorer.rb +49 -0
  199. data/vendor/ruby-signature/lib/ruby/signature/version.rb +5 -0
  200. data/vendor/ruby-signature/lib/ruby/signature/writer.rb +271 -0
  201. data/vendor/ruby-signature/ruby-signature.gemspec +45 -0
  202. data/vendor/ruby-signature/stdlib/abbrev/abbrev.rbs +3 -0
  203. data/vendor/ruby-signature/stdlib/base64/base64.rbs +15 -0
  204. data/vendor/ruby-signature/stdlib/builtin/array.rbs +1997 -0
  205. data/vendor/ruby-signature/stdlib/builtin/basic_object.rbs +280 -0
  206. data/vendor/ruby-signature/stdlib/builtin/binding.rbs +177 -0
  207. data/vendor/ruby-signature/stdlib/builtin/builtin.rbs +35 -0
  208. data/vendor/ruby-signature/stdlib/builtin/class.rbs +145 -0
  209. data/vendor/ruby-signature/stdlib/builtin/comparable.rbs +116 -0
  210. data/vendor/ruby-signature/stdlib/builtin/complex.rbs +400 -0
  211. data/vendor/ruby-signature/stdlib/builtin/constants.rbs +37 -0
  212. data/vendor/ruby-signature/stdlib/builtin/data.rbs +5 -0
  213. data/vendor/ruby-signature/stdlib/builtin/deprecated.rbs +2 -0
  214. data/vendor/ruby-signature/stdlib/builtin/dir.rbs +419 -0
  215. data/vendor/ruby-signature/stdlib/builtin/encoding.rbs +606 -0
  216. data/vendor/ruby-signature/stdlib/builtin/enumerable.rbs +404 -0
  217. data/vendor/ruby-signature/stdlib/builtin/enumerator.rbs +260 -0
  218. data/vendor/ruby-signature/stdlib/builtin/errno.rbs +781 -0
  219. data/vendor/ruby-signature/stdlib/builtin/errors.rbs +582 -0
  220. data/vendor/ruby-signature/stdlib/builtin/exception.rbs +193 -0
  221. data/vendor/ruby-signature/stdlib/builtin/false_class.rbs +40 -0
  222. data/vendor/ruby-signature/stdlib/builtin/fiber.rbs +68 -0
  223. data/vendor/ruby-signature/stdlib/builtin/fiber_error.rbs +12 -0
  224. data/vendor/ruby-signature/stdlib/builtin/file.rbs +476 -0
  225. data/vendor/ruby-signature/stdlib/builtin/file_test.rbs +59 -0
  226. data/vendor/ruby-signature/stdlib/builtin/float.rbs +696 -0
  227. data/vendor/ruby-signature/stdlib/builtin/gc.rbs +121 -0
  228. data/vendor/ruby-signature/stdlib/builtin/hash.rbs +1029 -0
  229. data/vendor/ruby-signature/stdlib/builtin/integer.rbs +710 -0
  230. data/vendor/ruby-signature/stdlib/builtin/io.rbs +683 -0
  231. data/vendor/ruby-signature/stdlib/builtin/kernel.rbs +574 -0
  232. data/vendor/ruby-signature/stdlib/builtin/marshal.rbs +135 -0
  233. data/vendor/ruby-signature/stdlib/builtin/match_data.rbs +141 -0
  234. data/vendor/ruby-signature/stdlib/builtin/math.rbs +66 -0
  235. data/vendor/ruby-signature/stdlib/builtin/method.rbs +182 -0
  236. data/vendor/ruby-signature/stdlib/builtin/module.rbs +248 -0
  237. data/vendor/ruby-signature/stdlib/builtin/nil_class.rbs +82 -0
  238. data/vendor/ruby-signature/stdlib/builtin/numeric.rbs +409 -0
  239. data/vendor/ruby-signature/stdlib/builtin/object.rbs +824 -0
  240. data/vendor/ruby-signature/stdlib/builtin/proc.rbs +426 -0
  241. data/vendor/ruby-signature/stdlib/builtin/process.rbs +354 -0
  242. data/vendor/ruby-signature/stdlib/builtin/random.rbs +93 -0
  243. data/vendor/ruby-signature/stdlib/builtin/range.rbs +226 -0
  244. data/vendor/ruby-signature/stdlib/builtin/rational.rbs +424 -0
  245. data/vendor/ruby-signature/stdlib/builtin/rb_config.rbs +10 -0
  246. data/vendor/ruby-signature/stdlib/builtin/regexp.rbs +131 -0
  247. data/vendor/ruby-signature/stdlib/builtin/ruby_vm.rbs +14 -0
  248. data/vendor/ruby-signature/stdlib/builtin/signal.rbs +55 -0
  249. data/vendor/ruby-signature/stdlib/builtin/string.rbs +770 -0
  250. data/vendor/ruby-signature/stdlib/builtin/string_io.rbs +13 -0
  251. data/vendor/ruby-signature/stdlib/builtin/struct.rbs +40 -0
  252. data/vendor/ruby-signature/stdlib/builtin/symbol.rbs +230 -0
  253. data/vendor/ruby-signature/stdlib/builtin/thread.rbs +1112 -0
  254. data/vendor/ruby-signature/stdlib/builtin/thread_group.rbs +23 -0
  255. data/vendor/ruby-signature/stdlib/builtin/time.rbs +739 -0
  256. data/vendor/ruby-signature/stdlib/builtin/trace_point.rbs +91 -0
  257. data/vendor/ruby-signature/stdlib/builtin/true_class.rbs +46 -0
  258. data/vendor/ruby-signature/stdlib/builtin/unbound_method.rbs +159 -0
  259. data/vendor/ruby-signature/stdlib/builtin/warning.rbs +17 -0
  260. data/vendor/ruby-signature/stdlib/erb/erb.rbs +18 -0
  261. data/vendor/ruby-signature/stdlib/find/find.rbs +44 -0
  262. data/vendor/ruby-signature/stdlib/pathname/pathname.rbs +21 -0
  263. data/vendor/ruby-signature/stdlib/prime/integer-extension.rbs +23 -0
  264. data/vendor/ruby-signature/stdlib/prime/prime.rbs +188 -0
  265. data/vendor/ruby-signature/stdlib/securerandom/securerandom.rbs +9 -0
  266. data/vendor/ruby-signature/stdlib/set/set.rbs +77 -0
  267. data/vendor/ruby-signature/stdlib/tmpdir/tmpdir.rbs +53 -0
  268. metadata +244 -54
  269. data/.travis.yml +0 -7
  270. data/lib/steep/ast/signature/alias.rb +0 -19
  271. data/lib/steep/ast/signature/class.rb +0 -33
  272. data/lib/steep/ast/signature/const.rb +0 -17
  273. data/lib/steep/ast/signature/env.rb +0 -138
  274. data/lib/steep/ast/signature/extension.rb +0 -21
  275. data/lib/steep/ast/signature/gvar.rb +0 -17
  276. data/lib/steep/ast/signature/interface.rb +0 -31
  277. data/lib/steep/ast/signature/members.rb +0 -115
  278. data/lib/steep/ast/signature/module.rb +0 -21
  279. data/lib/steep/drivers/print_interface.rb +0 -94
  280. data/lib/steep/drivers/scaffold.rb +0 -321
  281. data/lib/steep/drivers/utils/each_signature.rb +0 -31
  282. data/lib/steep/interface/abstract.rb +0 -68
  283. data/lib/steep/interface/builder.rb +0 -637
  284. data/lib/steep/interface/instantiated.rb +0 -163
  285. data/lib/steep/interface/ivar_chain.rb +0 -26
  286. data/lib/steep/parser.y +0 -1278
  287. data/lib/steep/project/listener.rb +0 -53
  288. data/smoke/class/a.rbi +0 -24
  289. data/smoke/class/d.rb +0 -9
  290. data/smoke/class/e.rb +0 -12
  291. data/smoke/class/i.rbi +0 -9
  292. data/smoke/hash/e.rbi +0 -3
  293. data/smoke/hello/hello.rbi +0 -7
  294. data/smoke/implements/a.rbi +0 -6
  295. data/smoke/initialize/a.rbi +0 -3
  296. data/smoke/module/a.rbi +0 -16
  297. data/smoke/self/a.rbi +0 -4
  298. data/smoke/super/a.rbi +0 -10
  299. data/stdlib/builtin.rbi +0 -787
@@ -0,0 +1,185 @@
1
+ module Ruby
2
+ module Signature
3
+ module Test
4
+ module TypeAssertions
5
+ module ClassMethods
6
+ attr_reader :target
7
+
8
+ def library(*libs)
9
+ @libs = libs
10
+ @env = nil
11
+ @target = nil
12
+ end
13
+
14
+ def env
15
+ @env ||= begin
16
+ loader = Ruby::Signature::EnvironmentLoader.new
17
+ (@libs || []).each do |lib|
18
+ loader.add library: lib
19
+ end
20
+
21
+ Ruby::Signature::Environment.new.tap do |env|
22
+ loader.load(env: env)
23
+ end
24
+ end
25
+ end
26
+
27
+ def builder
28
+ @builder ||= DefinitionBuilder.new(env: env)
29
+ end
30
+
31
+ def testing(type_or_string)
32
+ type = case type_or_string
33
+ when String
34
+ Ruby::Signature::Parser.parse_type(type_or_string, variables: [])
35
+ else
36
+ type_or_string
37
+ end
38
+
39
+ definition = case type
40
+ when Types::ClassInstance
41
+ builder.build_instance(type.name)
42
+ when Types::ClassSingleton
43
+ builder.build_singleton(type.name)
44
+ else
45
+ raise "Test target should be class instance or class singleton: #{type}"
46
+ end
47
+
48
+ @target = [type, definition]
49
+ end
50
+ end
51
+
52
+ def self.included(base)
53
+ base.extend ClassMethods
54
+ end
55
+
56
+ def env
57
+ self.class.env
58
+ end
59
+
60
+ def builder
61
+ self.class.builder
62
+ end
63
+
64
+ def targets
65
+ @targets ||= []
66
+ end
67
+
68
+ def target
69
+ targets.last || self.class.target
70
+ end
71
+
72
+ def testing(type_or_string)
73
+ type = case type_or_string
74
+ when String
75
+ Ruby::Signature::Parser.parse_type(type_or_string, variables: [])
76
+ else
77
+ type_or_string
78
+ end
79
+
80
+ definition = case type
81
+ when Types::ClassInstance
82
+ builder.build_instance(type.name)
83
+ when Types::ClassSingleton
84
+ builder.build_singleton(type.name)
85
+ else
86
+ raise "Test target should be class instance or class singleton: #{type}"
87
+ end
88
+
89
+ targets.push [type, definition]
90
+
91
+ if block_given?
92
+ begin
93
+ yield
94
+ ensure
95
+ targets.pop
96
+ end
97
+ else
98
+ [type, definition]
99
+ end
100
+ end
101
+
102
+ ruby2_keywords def assert_send_type(method_type, receiver, method, *args, &block)
103
+ trace = []
104
+ spy = Spy.wrap(receiver, method)
105
+ spy.callback = -> (result) { trace << result }
106
+
107
+ exception = nil
108
+
109
+ begin
110
+ spy.wrapped_object.__send__(method, *args, &block)
111
+ rescue => exn
112
+ exception = exn
113
+ end
114
+
115
+ mt = case method_type
116
+ when String
117
+ Ruby::Signature::Parser.parse_method_type(method_type, variables: [])
118
+ when Ruby::Signature::MethodType
119
+ method_type
120
+ end
121
+
122
+ typecheck = TypeCheck.new(self_class: receiver.class, builder: builder)
123
+ errors = typecheck.method_call(method, mt, trace.last, errors: [])
124
+
125
+ assert_empty errors.map {|x| Ruby::Signature::Test::Errors.to_string(x) }, "Call trace does not match with given method type: #{trace.last.inspect}"
126
+
127
+ type, definition = target
128
+ method_types = case
129
+ when definition.instance_type?
130
+ subst = Substitution.build(definition.declaration.type_params.each.map(&:name),
131
+ type.args)
132
+ definition.methods[method].method_types.map do |method_type|
133
+ method_type.sub(subst)
134
+ end
135
+ when definition.class_type?
136
+ definition.methods[method].method_types
137
+ end
138
+
139
+ all_errors = method_types.map {|t| typecheck.method_call(method, t, trace.last, errors: []) }
140
+ assert all_errors.any? {|es| es.empty? }, "Call trace does not match one of method definitions:\n #{trace.last.inspect}\n #{method_types.join(" | ")}"
141
+
142
+ if exception
143
+ raise exception
144
+ end
145
+ end
146
+
147
+ ruby2_keywords def refute_send_type(method_type, receiver, method, *args, &block)
148
+ trace = []
149
+ spy = Spy.wrap(receiver, method)
150
+ spy.callback = -> (result) { trace << result }
151
+
152
+ exception = nil
153
+ begin
154
+ spy.wrapped_object.__send__(method, *args, &block)
155
+ rescue Exception => exn
156
+ exception = exn
157
+ end
158
+
159
+ mt = case method_type
160
+ when String
161
+ Ruby::Signature::Parser.parse_method_type(method_type, variables: [])
162
+ when Ruby::Signature::MethodType
163
+ method_type
164
+ end
165
+
166
+ mt = mt.update(block: if mt.block
167
+ MethodType::Block.new(
168
+ type: mt.block.type.with_return_type(Types::Bases::Any.new(location: nil)),
169
+ required: mt.block.required
170
+ )
171
+ end,
172
+ type: mt.type.with_return_type(Types::Bases::Any.new(location: nil)))
173
+
174
+ typecheck = TypeCheck.new(self_class: receiver.class, builder: builder)
175
+ errors = typecheck.method_call(method, mt, trace.last, errors: [])
176
+
177
+ assert_operator exception, :is_a?, ::Exception
178
+ assert_empty errors.map {|x| Ruby::Signature::Test::Errors.to_string(x) }
179
+
180
+ exception
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,256 @@
1
+ module Ruby
2
+ module Signature
3
+ module Test
4
+ class TypeCheck
5
+ attr_reader :self_class
6
+ attr_reader :builder
7
+
8
+ def initialize(self_class:, builder:)
9
+ @self_class = self_class
10
+ @builder = builder
11
+ end
12
+
13
+ def method_call(method_name, method_type, call, errors:)
14
+ args(method_name, method_type, method_type.type, call.method_call, errors, type_error: Errors::ArgumentTypeError, argument_error: Errors::ArgumentError)
15
+ self.return(method_name, method_type, method_type.type, call.method_call, errors, return_error: Errors::ReturnTypeError)
16
+
17
+ if method_type.block
18
+ case
19
+ when !call.block_calls.empty?
20
+ call.block_calls.each do |block_call|
21
+ args(method_name, method_type, method_type.block.type, block_call, errors, type_error: Errors::BlockArgumentTypeError, argument_error: Errors::BlockArgumentError)
22
+ self.return(method_name, method_type, method_type.block.type, block_call, errors, return_error: Errors::BlockReturnTypeError)
23
+ end
24
+ when !call.block_given
25
+ # Block is not given
26
+ if method_type.block.required
27
+ errors << Errors::MissingBlockError.new(klass: self_class, method_name: method_name, method_type: method_type)
28
+ end
29
+ else
30
+ # Block is given, but not yielded
31
+ end
32
+ else
33
+ if call.block_given
34
+ errors << Errors::UnexpectedBlockError.new(klass: self_class, method_name: method_name, method_type: method_type)
35
+ end
36
+ end
37
+
38
+ errors
39
+ end
40
+
41
+ def args(method_name, method_type, fun, call, errors, type_error:, argument_error:)
42
+ test = zip_args(call.arguments, fun) do |val, param|
43
+ unless self.value(val, param.type)
44
+ errors << type_error.new(klass: self_class,
45
+ method_name: method_name,
46
+ method_type: method_type,
47
+ param: param,
48
+ value: val)
49
+ end
50
+ end
51
+
52
+ unless test
53
+ errors << argument_error.new(klass: self_class,
54
+ method_name: method_name,
55
+ method_type: method_type)
56
+ end
57
+ end
58
+
59
+ def return(method_name, method_type, fun, call, errors, return_error:)
60
+ unless call.exception
61
+ unless value(call.return_value, fun.return_type)
62
+ errors << return_error.new(klass: self_class,
63
+ method_name: method_name,
64
+ method_type: method_type,
65
+ type: fun.return_type,
66
+ value: call.return_value)
67
+ end
68
+ end
69
+ end
70
+
71
+ def zip_keyword_args(hash, fun)
72
+ fun.required_keywords.each do |name, param|
73
+ if hash.key?(name)
74
+ yield(hash[name], param)
75
+ else
76
+ return false
77
+ end
78
+ end
79
+
80
+ fun.optional_keywords.each do |name, param|
81
+ if hash.key?(name)
82
+ yield(hash[name], param)
83
+ end
84
+ end
85
+
86
+ hash.each do |name, value|
87
+ next if fun.required_keywords.key?(name)
88
+ next if fun.optional_keywords.key?(name)
89
+
90
+ if fun.rest_keywords
91
+ yield value, fun.rest_keywords
92
+ else
93
+ return false
94
+ end
95
+ end
96
+
97
+ true
98
+ end
99
+
100
+ def keyword?(value)
101
+ value.is_a?(Hash) && value.keys.all? {|key| key.is_a?(Symbol) }
102
+ end
103
+
104
+ def zip_args(args, fun, &block)
105
+ case
106
+ when args.empty?
107
+ if fun.required_positionals.empty? && fun.trailing_positionals.empty? && fun.required_keywords.empty?
108
+ true
109
+ else
110
+ false
111
+ end
112
+ when !fun.required_positionals.empty?
113
+ yield_self do
114
+ param, fun_ = fun.drop_head
115
+ yield(args.first, param)
116
+ zip_args(args.drop(1), fun_, &block)
117
+ end
118
+ when fun.has_keyword?
119
+ yield_self do
120
+ hash = args.last
121
+ if keyword?(hash)
122
+ zip_keyword_args(hash, fun, &block) &&
123
+ zip_args(args.take(args.size - 1),
124
+ fun.update(required_keywords: {}, optional_keywords: {}, rest_keywords: nil),
125
+ &block)
126
+ else
127
+ fun.required_keywords.empty? &&
128
+ zip_args(args,
129
+ fun.update(required_keywords: {}, optional_keywords: {}, rest_keywords: nil),
130
+ &block)
131
+ end
132
+ end
133
+ when !fun.trailing_positionals.empty?
134
+ yield_self do
135
+ param, fun_ = fun.drop_tail
136
+ yield(args.last, param)
137
+ zip_args(args.take(args.size - 1), fun_, &block)
138
+ end
139
+ when !fun.optional_positionals.empty?
140
+ yield_self do
141
+ param, fun_ = fun.drop_head
142
+ yield(args.first, param)
143
+ zip_args(args.drop(1), fun_, &block)
144
+ end
145
+ when fun.rest_positionals
146
+ yield_self do
147
+ yield(args.first, fun.rest_positionals)
148
+ zip_args(args.drop(1), fun, &block)
149
+ end
150
+ else
151
+ false
152
+ end
153
+ end
154
+
155
+ def value(val, type)
156
+ case type
157
+ when Types::Bases::Any
158
+ true
159
+ when Types::Bases::Bool
160
+ true
161
+ when Types::Bases::Top
162
+ true
163
+ when Types::Bases::Bottom
164
+ false
165
+ when Types::Bases::Void
166
+ true
167
+ when Types::Bases::Self
168
+ Test.call(val, IS_AP, self_class)
169
+ when Types::Bases::Nil
170
+ Test.call(val, IS_AP, ::NilClass)
171
+ when Types::Bases::Class
172
+ Test.call(val, IS_AP, Class)
173
+ when Types::Bases::Instance
174
+ Test.call(val, IS_AP, self_class)
175
+ when Types::ClassInstance
176
+ klass = Object.const_get(type.name.to_s)
177
+ case
178
+ when klass == ::Array
179
+ Test.call(val, IS_AP, klass) && val.all? {|v| value(v, type.args[0]) }
180
+ when klass == ::Hash
181
+ Test.call(val, IS_AP, klass) && val.all? {|k, v| value(k, type.args[0]) && value(v, type.args[1]) }
182
+ when klass == ::Range
183
+ Test.call(val, IS_AP, klass) && value(val.begin, type.args[0]) && value(val.end, type.args[0])
184
+ when klass == ::Enumerator
185
+ if Test.call(val, IS_AP, klass)
186
+ case val.size
187
+ when Float::INFINITY
188
+ values = []
189
+ ret = self
190
+ val.lazy.take(10).each do |*args|
191
+ values << args
192
+ nil
193
+ end
194
+ else
195
+ values = []
196
+ ret = val.each do |*args|
197
+ values << args
198
+ nil
199
+ end
200
+ end
201
+
202
+ values.all? do |v|
203
+ if v.size == 1
204
+ # Only one block argument.
205
+ value(v[0], type.args[0]) || value(v, type.args[0])
206
+ else
207
+ value(v, type.args[0])
208
+ end
209
+ end &&
210
+ if ret.equal?(self)
211
+ type.args[1].is_a?(Types::Bases::Bottom)
212
+ else
213
+ value(ret, type.args[1])
214
+ end
215
+ end
216
+ else
217
+ Test.call(val, IS_AP, klass)
218
+ end
219
+ when Types::ClassSingleton
220
+ klass = Object.const_get(type.name.to_s)
221
+ val == klass
222
+ when Types::Interface
223
+ methods = Set.new(Test.call(val, METHODS))
224
+ decl = builder.env.find_class(type.name)
225
+ if (definition = builder.build_interface(type.name, decl))
226
+ definition.methods.each_key.all? do |method_name|
227
+ methods.member?(method_name)
228
+ end
229
+ end
230
+ when Types::Variable
231
+ true
232
+ when Types::Literal
233
+ val == type.literal
234
+ when Types::Union
235
+ type.types.any? {|type| value(val, type) }
236
+ when Types::Intersection
237
+ type.types.all? {|type| value(val, type) }
238
+ when Types::Optional
239
+ Test.call(val, IS_AP, ::NilClass) || value(val, type.type)
240
+ when Types::Alias
241
+ value(val, builder.expand_alias(type.name))
242
+ when Types::Tuple
243
+ Test.call(val, IS_AP, ::Array) &&
244
+ type.types.map.with_index {|ty, index| value(val[index], ty) }.all?
245
+ when Types::Record
246
+ Test::call(val, IS_AP, ::Hash)
247
+ when Types::Proc
248
+ Test::call(val, IS_AP, ::Proc)
249
+ else
250
+ false
251
+ end
252
+ end
253
+ end
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,72 @@
1
+ module Ruby
2
+ module Signature
3
+ class TypeName
4
+ attr_reader :namespace
5
+ attr_reader :name
6
+ attr_reader :kind
7
+
8
+ def initialize(namespace:, name:)
9
+ @namespace = namespace
10
+ @name = name
11
+ @kind = case name.to_s[0,1]
12
+ when /[A-Z]/
13
+ :class
14
+ when /[a-z]/
15
+ :alias
16
+ when "_"
17
+ :interface
18
+ end
19
+ end
20
+
21
+ def ==(other)
22
+ other.is_a?(self.class) && other.namespace == namespace && other.name == name
23
+ end
24
+
25
+ alias eql? ==
26
+
27
+ def hash
28
+ self.class.hash ^ namespace.hash ^ name.hash
29
+ end
30
+
31
+ def to_s
32
+ "#{namespace.to_s}#{name}"
33
+ end
34
+
35
+ def to_json(*a)
36
+ to_s.to_json(*a)
37
+ end
38
+
39
+ def to_namespace
40
+ namespace.append(self.name)
41
+ end
42
+
43
+ def class?
44
+ kind == :class
45
+ end
46
+
47
+ def alias?
48
+ kind == :alias
49
+ end
50
+
51
+ def absolute!
52
+ self.class.new(namespace: namespace.absolute!, name: name)
53
+ end
54
+
55
+ def absolute?
56
+ namespace.absolute?
57
+ end
58
+
59
+ def relative!
60
+ self.class.new(namespace: namespace.relative!, name: name)
61
+ end
62
+
63
+ def interface?
64
+ kind == :interface
65
+ end
66
+
67
+ def with_prefix(namespace)
68
+ self.class.new(namespace: namespace + self.namespace, name: name)
69
+ end
70
+ end
71
+ end
72
+ end