steep 0.11.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,140 @@
1
+ module Ruby
2
+ module Signature
3
+ class VarianceCalculator
4
+ class Result
5
+ attr_reader :result
6
+
7
+ def initialize(variables:)
8
+ @result = {}
9
+ variables.each do |x|
10
+ result[x] = :unused
11
+ end
12
+ end
13
+
14
+ def covariant(x)
15
+ case result[x]
16
+ when :unused
17
+ result[x] = :covariant
18
+ when :contravariant
19
+ result[x] = :invariant
20
+ end
21
+ end
22
+
23
+ def contravariant(x)
24
+ case result[x]
25
+ when :unused
26
+ result[x] = :contravariant
27
+ when :covariant
28
+ result[x] = :invariant
29
+ end
30
+ end
31
+
32
+ def invariant(x)
33
+ result[x] = :invariant
34
+ end
35
+
36
+ def each(&block)
37
+ result.each(&block)
38
+ end
39
+
40
+ def include?(name)
41
+ result.key?(name)
42
+ end
43
+
44
+ def compatible?(var, with_annotation:)
45
+ variance = result[var]
46
+
47
+ case
48
+ when variance == :unused
49
+ true
50
+ when with_annotation == :invariant
51
+ true
52
+ when variance == with_annotation
53
+ true
54
+ else
55
+ false
56
+ end
57
+ end
58
+ end
59
+
60
+ attr_reader :builder
61
+
62
+ def initialize(builder:)
63
+ @builder = builder
64
+ end
65
+
66
+ def env
67
+ builder.env
68
+ end
69
+
70
+ def in_method_type(method_type:, variables:)
71
+ result = Result.new(variables: variables)
72
+
73
+ method_type.type.each_param do |param|
74
+ type(param.type, result: result, context: :contravariant)
75
+ end
76
+
77
+ if method_type.block
78
+ method_type.block.type.each_param do |param|
79
+ type(param.type, result: result, context: :covariant)
80
+ end
81
+ type(method_type.block.type.return_type, result: result, context: :contravariant)
82
+ end
83
+
84
+ type(method_type.type.return_type, result: result, context: :covariant)
85
+
86
+ result
87
+ end
88
+
89
+ def in_inherit(name:, args:, variables:)
90
+ type = Types::ClassInstance.new(name: name, args: args, location: nil)
91
+
92
+ Result.new(variables: variables).tap do |result|
93
+ type(type, result: result, context: :covariant)
94
+ end
95
+ end
96
+
97
+ def type(type, result:, context:)
98
+ case type
99
+ when Types::Variable
100
+ if result.include?(type.name)
101
+ case context
102
+ when :covariant
103
+ result.covariant(type.name)
104
+ when :contravariant
105
+ result.contravariant(type.name)
106
+ when :invariant
107
+ result.invariant(type.name)
108
+ end
109
+ end
110
+ when Types::ClassInstance, Types::Interface
111
+ decl = env.find_class(type.name)
112
+ type.args.each.with_index do |ty, i|
113
+ var = decl.type_params.params[i]
114
+ case var.variance
115
+ when :invariant
116
+ type(ty, result: result, context: :invariant)
117
+ when :covariant
118
+ type(ty, result: result, context: context)
119
+ when :contravariant
120
+ con = case context
121
+ when :invariant
122
+ :invariant
123
+ when :covariant
124
+ :contravariant
125
+ when :contravariant
126
+ :covariant
127
+ end
128
+ type(ty, result: result, context: con)
129
+ end
130
+ end
131
+ when Types::Tuple, Types::Record, Types::Union, Types::Intersection
132
+ # Covariant types
133
+ type.each_type do |ty|
134
+ type(ty, result: result, context: context)
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,49 @@
1
+ module Ruby
2
+ module Signature
3
+ class Vendorer
4
+ attr_reader :vendor_dir
5
+
6
+ def initialize(vendor_dir:)
7
+ @vendor_dir = vendor_dir
8
+ end
9
+
10
+ def ensure_dir
11
+ unless vendor_dir.directory?
12
+ vendor_dir.mkpath
13
+ end
14
+
15
+ yield
16
+ end
17
+
18
+ def clean!
19
+ ensure_dir do
20
+ Signature.logger.info "Cleaning vendor root: #{vendor_dir}..."
21
+ vendor_dir.rmtree
22
+ end
23
+ end
24
+
25
+ def stdlib!()
26
+ ensure_dir do
27
+ Signature.logger.info "Vendoring stdlib: #{EnvironmentLoader::STDLIB_ROOT} => #{vendor_dir + "stdlib"}..."
28
+ FileUtils.copy_entry EnvironmentLoader::STDLIB_ROOT, vendor_dir + "stdlib"
29
+ end
30
+ end
31
+
32
+ def gem!(name, version)
33
+ ensure_dir do
34
+ sig_path = EnvironmentLoader.gem_sig_path(name, version)
35
+ Signature.logger.debug "Checking gem signature path: name=#{name}, version=#{version}, path=#{sig_path}"
36
+
37
+ if sig_path&.directory?
38
+ gems_dir = vendor_dir + "gems"
39
+ gems_dir.mkpath unless gems_dir.directory?
40
+
41
+ gem_dir = gems_dir + name
42
+ Signature.logger.info "Vendoring gem(#{name}:#{version}): #{sig_path} => #{gem_dir}..."
43
+ FileUtils.copy_entry sig_path, gem_dir
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,5 @@
1
+ module Ruby
2
+ module Signature
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,271 @@
1
+ module Ruby
2
+ module Signature
3
+ class Writer
4
+ attr_reader :out
5
+
6
+ def initialize(out:)
7
+ @out = out
8
+ end
9
+
10
+ def write_annotation(annotations, level:)
11
+ prefix = " " * level
12
+
13
+ annotations.each do |annotation|
14
+ string = annotation.string
15
+ case
16
+ when string !~ /\}/
17
+ out.puts "#{prefix}%a{#{string}}"
18
+ when string !~ /\)/
19
+ out.puts "#{prefix}%a(#{string})"
20
+ when string !~ /\]/
21
+ out.puts "#{prefix}%a[#{string}]"
22
+ when string !~ /\>/
23
+ out.puts "#{prefix}%a<#{string}>"
24
+ when string !~ /\|/
25
+ out.puts "#{prefix}%a|#{string}|"
26
+ end
27
+ end
28
+ end
29
+
30
+ def write_comment(comment, level:)
31
+ if comment
32
+ prefix = " " * level
33
+ comment.string.lines.each do |line|
34
+ line = " #{line}" unless line.chomp.empty?
35
+ out.puts "#{prefix}##{line}"
36
+ end
37
+ end
38
+ end
39
+
40
+ def write(decls)
41
+ [nil, *decls].each_cons(2) do |prev, decl|
42
+ preserve_empty_line(prev, decl)
43
+ write_decl decl
44
+ end
45
+ end
46
+
47
+ def write_decl(decl)
48
+ case decl
49
+ when AST::Declarations::Class
50
+ super_class = if decl.super_class
51
+ " < #{name_and_args(decl.super_class.name, decl.super_class.args)}"
52
+ end
53
+ write_comment decl.comment, level: 0
54
+ write_annotation decl.annotations, level: 0
55
+ out.puts "class #{name_and_params(decl.name, decl.type_params)}#{super_class}"
56
+
57
+ [nil, *decl.members].each_cons(2) do |prev, member|
58
+ preserve_empty_line prev, member
59
+ write_member member
60
+ end
61
+
62
+ out.puts "end"
63
+
64
+ when AST::Declarations::Module
65
+ self_type = if decl.self_type
66
+ " : #{decl.self_type}"
67
+ end
68
+
69
+ write_comment decl.comment, level: 0
70
+ write_annotation decl.annotations, level: 0
71
+ out.puts "module #{name_and_params(decl.name, decl.type_params)}#{self_type}"
72
+ decl.members.each.with_index do |member, index|
73
+ if index > 0
74
+ out.puts
75
+ end
76
+ write_member member
77
+ end
78
+ out.puts "end"
79
+ when AST::Declarations::Constant
80
+ write_comment decl.comment, level: 0
81
+ out.puts "#{decl.name}: #{decl.type}"
82
+
83
+ when AST::Declarations::Global
84
+ write_comment decl.comment, level: 0
85
+ out.puts "#{decl.name}: #{decl.type}"
86
+
87
+ when AST::Declarations::Alias
88
+ write_comment decl.comment, level: 0
89
+ write_annotation decl.annotations, level: 0
90
+ out.puts "type #{decl.name} = #{decl.type}"
91
+
92
+ when AST::Declarations::Interface
93
+ write_comment decl.comment, level: 0
94
+ write_annotation decl.annotations, level: 0
95
+ out.puts "interface #{name_and_params(decl.name, decl.type_params)}"
96
+ decl.members.each.with_index do |member, index|
97
+ if index > 0
98
+ out.puts
99
+ end
100
+ write_member member
101
+ end
102
+ out.puts "end"
103
+
104
+ when AST::Declarations::Extension
105
+ write_comment decl.comment, level: 0
106
+ write_annotation decl.annotations, level: 0
107
+ out.puts "extension #{name_and_args(decl.name, decl.type_params)} (#{decl.extension_name})"
108
+ decl.members.each.with_index do |member, index|
109
+ if index > 0
110
+ out.puts
111
+ end
112
+ write_member member
113
+ end
114
+ out.puts "end"
115
+ end
116
+ end
117
+
118
+ def name_and_params(name, params)
119
+ if params.empty?
120
+ "#{name}"
121
+ else
122
+ ps = params.each.map do |param|
123
+ s = ""
124
+ if param.skip_validation
125
+ s << "unchecked "
126
+ end
127
+ case param.variance
128
+ when :invariant
129
+ # nop
130
+ when :covariant
131
+ s << "out "
132
+ when :contravariant
133
+ s << "in "
134
+ end
135
+ s + param.name.to_s
136
+ end
137
+
138
+ "#{name}[#{ps.join(", ")}]"
139
+ end
140
+ end
141
+
142
+ def name_and_args(name, args)
143
+ if name && args
144
+ if args.empty?
145
+ "#{name}"
146
+ else
147
+ "#{name}[#{args.join(", ")}]"
148
+ end
149
+ end
150
+ end
151
+
152
+ def write_member(member)
153
+ case member
154
+ when AST::Members::Include
155
+ write_comment member.comment, level: 2
156
+ write_annotation member.annotations, level: 2
157
+ out.puts " include #{name_and_args(member.name, member.args)}"
158
+ when AST::Members::Extend
159
+ write_comment member.comment, level: 2
160
+ write_annotation member.annotations, level: 2
161
+ out.puts " extend #{name_and_args(member.name, member.args)}"
162
+ when AST::Members::Prepend
163
+ write_comment member.comment, level: 2
164
+ write_annotation member.annotations, level: 2
165
+ out.puts " prepend #{name_and_args(member.name, member.args)}"
166
+ when AST::Members::AttrAccessor
167
+ write_comment member.comment, level: 2
168
+ write_annotation member.annotations, level: 2
169
+ out.puts " #{attribute(:accessor, member)}"
170
+ when AST::Members::AttrReader
171
+ write_comment member.comment, level: 2
172
+ write_annotation member.annotations, level: 2
173
+ out.puts " #{attribute(:reader, member)}"
174
+ when AST::Members::AttrWriter
175
+ write_comment member.comment, level: 2
176
+ write_annotation member.annotations, level: 2
177
+ out.puts " #{attribute(:writer, member)}"
178
+ when AST::Members::Public
179
+ out.puts " public"
180
+ when AST::Members::Private
181
+ out.puts " private"
182
+ when AST::Members::Alias
183
+ write_comment member.comment, level: 2
184
+ write_annotation member.annotations, level: 2
185
+ new_name = member.singleton? ? "self.#{member.new_name}" : member.new_name
186
+ old_name = member.singleton? ? "self.#{member.old_name}" : member.old_name
187
+ out.puts " alias #{new_name} #{old_name}"
188
+ when AST::Members::InstanceVariable
189
+ write_comment member.comment, level: 2
190
+ out.puts " #{member.name}: #{member.type}"
191
+ when AST::Members::ClassInstanceVariable
192
+ write_comment member.comment, level: 2
193
+ out.puts " self.#{member.name}: #{member.type}"
194
+ when AST::Members::ClassVariable
195
+ write_comment member.comment, level: 2
196
+ out.puts " #{member.name}: #{member.type}"
197
+ when AST::Members::MethodDefinition
198
+ write_comment member.comment, level: 2
199
+ write_annotation member.annotations, level: 2
200
+ write_def member
201
+ end
202
+ end
203
+
204
+ def method_name(name)
205
+ s = name.to_s
206
+
207
+ if /\A#{Parser::KEYWORDS_RE}\z/.match?(s)
208
+ "`#{s}`"
209
+ else
210
+ s
211
+ end
212
+ end
213
+
214
+ def write_def(member)
215
+ name = case member.kind
216
+ when :instance
217
+ "#{method_name(member.name)}"
218
+ when :singleton_instance
219
+ "self?.#{method_name(member.name)}"
220
+ when :singleton
221
+ "self.#{method_name(member.name)}"
222
+ end
223
+
224
+ attrs = member.attributes.empty? ? "" : member.attributes.join(" ") + " "
225
+ prefix = " #{attrs}def #{name}:"
226
+ padding = " " * (prefix.size-1)
227
+
228
+ out.print prefix
229
+
230
+ member.types.each.with_index do |type, index|
231
+ if index > 0
232
+ out.print padding
233
+ out.print "|"
234
+ end
235
+ out.puts " #{type}"
236
+ end
237
+ end
238
+
239
+ def attribute(kind, attr)
240
+ var = case attr.ivar_name
241
+ when nil
242
+ ""
243
+ when false
244
+ "()"
245
+ else
246
+ "(#{attr.ivar_name})"
247
+ end
248
+ "attr_#{kind} #{attr.name}#{var}: #{attr.type}"
249
+ end
250
+
251
+ def preserve_empty_line(prev, decl)
252
+ return unless prev
253
+
254
+ decl = decl.comment if decl.respond_to?(:comment) && decl.comment
255
+
256
+ # When the signature is not constructed by the parser,
257
+ # it always inserts an empty line.
258
+ if !prev.location || !decl.location
259
+ out.puts
260
+ return
261
+ end
262
+
263
+ prev_end_line = prev.location.end_line
264
+ start_line = decl.location.start_line
265
+ if start_line - prev_end_line > 1
266
+ out.puts
267
+ end
268
+ end
269
+ end
270
+ end
271
+ end