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,534 @@
1
+ require "optparse"
2
+
3
+ module Ruby
4
+ module Signature
5
+ class CLI
6
+ class LibraryOptions
7
+ attr_reader :libs
8
+ attr_reader :dirs
9
+ attr_accessor :no_stdlib
10
+
11
+ def initialize()
12
+ @libs = []
13
+ @dirs = []
14
+ @no_stdlib = false
15
+ end
16
+
17
+ def setup(loader)
18
+ libs.each do |lib|
19
+ loader.add(library: lib)
20
+ end
21
+
22
+ dirs.each do |dir|
23
+ loader.add(path: Pathname(dir))
24
+ end
25
+
26
+ loader.no_builtin! nil if no_stdlib
27
+
28
+ loader
29
+ end
30
+ end
31
+
32
+ attr_reader :stdout
33
+ attr_reader :stderr
34
+
35
+ def initialize(stdout:, stderr:)
36
+ @stdout = stdout
37
+ @stderr = stderr
38
+ end
39
+
40
+ COMMANDS = [:ast, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :version]
41
+
42
+ def library_parse(opts, options:)
43
+ opts.on("-r LIBRARY") do |lib|
44
+ options.libs << lib
45
+ end
46
+
47
+ opts.on("-I DIR") do |dir|
48
+ options.dirs << dir
49
+ end
50
+
51
+ opts.on("--no-stdlib") do
52
+ options.no_stdlib = true
53
+ end
54
+
55
+ opts
56
+ end
57
+
58
+ def parse_logging_options(opts)
59
+ opts.on("--log-level=LEVEL", "Specify log level (defaults to `warn`)") do |level|
60
+ Ruby::Signature.logger_level = level
61
+ end
62
+
63
+ opts.on("--log-output=OUTPUT", "Specify the file to output log (defaults to stderr)") do |output|
64
+ Ruby::Signature.logger_output = File.open(output, "a")
65
+ end
66
+
67
+ opts
68
+ end
69
+
70
+ def run(args)
71
+ options = LibraryOptions.new
72
+
73
+ opts = OptionParser.new
74
+ opts.banner = <<~USAGE
75
+ Usage: rbs [options] COMMAND
76
+ Available commands: #{COMMANDS.join(", ")}
77
+ USAGE
78
+ library_parse(opts, options: options)
79
+ parse_logging_options(opts)
80
+
81
+ opts.order!(args)
82
+
83
+ command = args.shift&.to_sym
84
+
85
+ if COMMANDS.include?(command)
86
+ __send__ :"run_#{command}", args, options
87
+ else
88
+ stdout.puts opts.help
89
+ end
90
+ end
91
+
92
+ def run_ast(args, options)
93
+ loader = EnvironmentLoader.new()
94
+
95
+ options.setup(loader)
96
+
97
+ env = Environment.new()
98
+ loader.load(env: env)
99
+
100
+ stdout.print JSON.generate(env.declarations)
101
+ stdout.flush
102
+ end
103
+
104
+ def run_list(args, options)
105
+ list = []
106
+
107
+ OptionParser.new do |opts|
108
+ opts.on("--class") { list << :class }
109
+ opts.on("--module") { list << :module }
110
+ opts.on("--interface") { list << :interface }
111
+ end.order!(args)
112
+
113
+ list.push(:class, :module, :interface) if list.empty?
114
+
115
+ loader = EnvironmentLoader.new()
116
+
117
+ options.setup(loader)
118
+
119
+ env = Environment.new()
120
+ loader.load(env: env)
121
+
122
+ env.each_decl.sort_by {|name,| name.to_s }.each do |type_name, decl|
123
+ case decl
124
+ when AST::Declarations::Class
125
+ if list.include?(:class)
126
+ stdout.puts "#{type_name} (class)"
127
+ end
128
+ when AST::Declarations::Module
129
+ if list.include?(:module)
130
+ stdout.puts "#{type_name} (module)"
131
+ end
132
+ when AST::Declarations::Interface
133
+ if list.include?(:interface)
134
+ stdout.puts "#{type_name} (interface)"
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ def run_ancestors(args, options)
141
+ kind = :instance
142
+
143
+ OptionParser.new do |opts|
144
+ opts.on("--instance") { kind = :instance }
145
+ opts.on("--singleton") { kind = :singleton }
146
+ end.order!(args)
147
+
148
+ loader = EnvironmentLoader.new()
149
+
150
+ options.setup(loader)
151
+
152
+ env = Environment.new()
153
+ loader.load(env: env)
154
+
155
+ builder = DefinitionBuilder.new(env: env)
156
+ type_name = parse_type_name(args[0]).absolute!
157
+
158
+ if env.class?(type_name)
159
+ ancestor = case kind
160
+ when :instance
161
+ decl = env.find_class(type_name)
162
+ Definition::Ancestor::Instance.new(name: type_name,
163
+ args: Types::Variable.build(decl.type_params.each.map(&:name)))
164
+ when :singleton
165
+ Definition::Ancestor::Singleton.new(name: type_name)
166
+ end
167
+
168
+ ancestors = builder.build_ancestors(ancestor)
169
+
170
+ ancestors.each do |ancestor|
171
+ case ancestor
172
+ when Definition::Ancestor::Singleton
173
+ stdout.puts "singleton(#{ancestor.name})"
174
+ when Definition::Ancestor::ExtensionSingleton
175
+ stdout.puts "singleton(#{ancestor.name} (#{ancestor.extension_name}))"
176
+ when Definition::Ancestor::Instance
177
+ if ancestor.args.empty?
178
+ stdout.puts ancestor.name.to_s
179
+ else
180
+ stdout.puts "#{ancestor.name}[#{ancestor.args.join(", ")}]"
181
+ end
182
+ when Definition::Ancestor::ExtensionInstance
183
+ if ancestor.args.empty?
184
+ stdout.puts "#{ancestor.name} (#{ancestor.extension_name})"
185
+ else
186
+ stdout.puts "#{ancestor.name}[#{ancestor.args.join(", ")}] (#{ancestor.extension_name})"
187
+ end
188
+ end
189
+ end
190
+ else
191
+ stdout.puts "Cannot find class: #{type_name}"
192
+ end
193
+ end
194
+
195
+ def run_methods(args, options)
196
+ kind = :instance
197
+ inherit = true
198
+
199
+ OptionParser.new do |opts|
200
+ opts.on("--instance") { kind = :instance }
201
+ opts.on("--singleton") { kind = :singleton }
202
+ opts.on("--inherit") { inherit = true }
203
+ opts.on("--no-inherit") { inherit = false }
204
+ end.order!(args)
205
+
206
+ unless args.size == 1
207
+ stdout.puts "Expected one argument."
208
+ return
209
+ end
210
+
211
+ loader = EnvironmentLoader.new()
212
+
213
+ options.setup(loader)
214
+
215
+ env = Environment.new()
216
+ loader.load(env: env)
217
+
218
+ builder = DefinitionBuilder.new(env: env)
219
+ type_name = parse_type_name(args[0]).absolute!
220
+
221
+ if env.class?(type_name)
222
+ definition = case kind
223
+ when :instance
224
+ builder.build_instance(type_name)
225
+ when :singleton
226
+ builder.build_singleton(type_name)
227
+ end
228
+
229
+ definition.methods.keys.sort.each do |name|
230
+ method = definition.methods[name]
231
+ if inherit || method.implemented_in == definition.declaration
232
+ stdout.puts "#{name} (#{method.accessibility})"
233
+ end
234
+ end
235
+ else
236
+ stdout.puts "Cannot find class: #{type_name}"
237
+ end
238
+ end
239
+
240
+ def run_method(args, options)
241
+ kind = :instance
242
+
243
+ OptionParser.new do |opts|
244
+ opts.on("--instance") { kind = :instance }
245
+ opts.on("--singleton") { kind = :singleton }
246
+ end.order!(args)
247
+
248
+ unless args.size == 2
249
+ stdout.puts "Expected two arguments, but given #{args.size}."
250
+ return
251
+ end
252
+
253
+ loader = EnvironmentLoader.new()
254
+
255
+ options.setup(loader)
256
+
257
+ env = Environment.new()
258
+ loader.load(env: env)
259
+
260
+ builder = DefinitionBuilder.new(env: env)
261
+ type_name = parse_type_name(args[0]).absolute!
262
+ method_name = args[1].to_sym
263
+
264
+ unless env.class?(type_name)
265
+ stdout.puts "Cannot find class: #{type_name}"
266
+ return
267
+ end
268
+
269
+ definition = case kind
270
+ when :instance
271
+ builder.build_instance(type_name)
272
+ when :singleton
273
+ builder.build_singleton(type_name)
274
+ end
275
+
276
+ method = definition.methods[method_name]
277
+
278
+ unless method
279
+ stdout.puts "Cannot find method: #{method_name}"
280
+ return
281
+ end
282
+
283
+ stdout.puts "#{type_name}#{kind == :instance ? "#" : "."}#{method_name}"
284
+ stdout.puts " defined_in: #{method.defined_in&.name&.absolute!}"
285
+ stdout.puts " implementation: #{method.implemented_in.name.absolute!}"
286
+ stdout.puts " accessibility: #{method.accessibility}"
287
+ stdout.puts " types:"
288
+ separator = " "
289
+ for type in method.method_types
290
+ stdout.puts " #{separator} #{type}"
291
+ separator = "|"
292
+ end
293
+ end
294
+
295
+ def run_validate(args, options)
296
+ loader = EnvironmentLoader.new()
297
+
298
+ options.setup(loader)
299
+
300
+ env = Environment.new()
301
+ loader.load(env: env)
302
+
303
+ builder = DefinitionBuilder.new(env: env)
304
+
305
+ env.each_decl do |name, decl|
306
+ case decl
307
+ when AST::Declarations::Class, AST::Declarations::Module
308
+ stdout.puts "#{Location.to_string decl.location}:\tValidating class/module definition: `#{name}`..."
309
+ builder.build_instance(decl.name.absolute!).each_type do |type|
310
+ env.validate type, namespace: Namespace.root
311
+ end
312
+ builder.build_singleton(decl.name.absolute!).each_type do |type|
313
+ env.validate type, namespace: Namespace.root
314
+ end
315
+ when AST::Declarations::Interface
316
+ stdout.puts "#{Location.to_string decl.location}:\tValidating interface: `#{name}`..."
317
+ builder.build_interface(decl.name.absolute!, decl).each_type do |type|
318
+ env.validate type, namespace: Namespace.root
319
+ end
320
+ end
321
+ end
322
+
323
+ env.each_constant do |name, const|
324
+ stdout.puts "#{Location.to_string const.location}:\tValidating constant: `#{name}`..."
325
+ env.validate const.type, namespace: name.namespace
326
+ end
327
+
328
+ env.each_global do |name, global|
329
+ stdout.puts "#{Location.to_string global.location}:\tValidating global: `#{name}`..."
330
+ env.validate global.type, namespace: Namespace.root
331
+ end
332
+
333
+ env.each_alias do |name, decl|
334
+ stdout.puts "#{Location.to_string decl.location}:\tValidating alias: `#{name}`..."
335
+ env.validate decl.type, namespace: name.namespace
336
+ end
337
+ end
338
+
339
+ def run_constant(args, options)
340
+ context = nil
341
+
342
+ OptionParser.new do |opts|
343
+ opts.on("--context CONTEXT") {|c| context = c }
344
+ end.order!(args)
345
+
346
+ unless args.size == 1
347
+ stdout.puts "Expected one argument."
348
+ return
349
+ end
350
+
351
+ loader = EnvironmentLoader.new()
352
+
353
+ options.setup(loader)
354
+
355
+ env = Environment.new()
356
+ loader.load(env: env)
357
+
358
+ builder = DefinitionBuilder.new(env: env)
359
+ table = ConstantTable.new(builder: builder)
360
+
361
+ namespace = context ? Namespace.parse(context).absolute! : Namespace.root
362
+ stdout.puts "Context: #{namespace}"
363
+ name = Namespace.parse(args[0]).to_type_name
364
+ stdout.puts "Constant name: #{name}"
365
+
366
+ constant = table.resolve_constant_reference(name, context: namespace)
367
+
368
+ if constant
369
+ stdout.puts " => #{constant.name}: #{constant.type}"
370
+ else
371
+ stdout.puts " => [no constant]"
372
+ end
373
+ end
374
+
375
+ def run_version(args, options)
376
+ stdout.puts "ruby-signature #{VERSION}"
377
+ end
378
+
379
+ def run_paths(args, options)
380
+ loader = EnvironmentLoader.new()
381
+
382
+ options.setup(loader)
383
+
384
+ kind_of = -> (path) {
385
+ case
386
+ when path.file?
387
+ "file"
388
+ when path.directory?
389
+ "dir"
390
+ when !path.exist?
391
+ "absent"
392
+ else
393
+ "unknown"
394
+ end
395
+ }
396
+
397
+ if loader.stdlib_root
398
+ path = loader.stdlib_root
399
+ stdout.puts "#{path}/builtin (#{kind_of[path]}, stdlib)"
400
+ end
401
+
402
+ loader.paths.each do |path|
403
+ case path
404
+ when Pathname
405
+ stdout.puts "#{path} (#{kind_of[path]})"
406
+ when EnvironmentLoader::GemPath
407
+ stdout.puts "#{path.path} (#{kind_of[path.path]}, gem, name=#{path.name}, version=#{path.version})"
408
+ when EnvironmentLoader::LibraryPath
409
+ stdout.puts "#{path.path} (#{kind_of[path.path]}, library, name=#{path.name})"
410
+ end
411
+ end
412
+ end
413
+
414
+ def run_prototype(args, options)
415
+ format = args.shift
416
+
417
+ case format
418
+ when "rbi", "rb"
419
+ decls = run_prototype_file(format, args)
420
+ when "runtime"
421
+ require_libs = []
422
+ relative_libs = []
423
+ merge = false
424
+ owners_included = []
425
+
426
+ OptionParser.new do |opts|
427
+ opts.on("--require=[LIB]") do |lib|
428
+ require_libs << lib
429
+ end
430
+ opts.on("--require-relative=[LIB]") do |lib|
431
+ relative_libs << lib
432
+ end
433
+ opts.on("--merge") do
434
+ merge = true
435
+ end
436
+ opts.on("--method-owner=[CLASS]") do |klass|
437
+ owners_included << klass
438
+ end
439
+ end.parse!(args)
440
+
441
+ loader = EnvironmentLoader.new()
442
+
443
+ options.setup(loader)
444
+
445
+ env = Environment.new()
446
+ loader.load(env: env)
447
+
448
+ require(*require_libs) unless require_libs.empty?
449
+ require_relative(*relative_libs) unless relative_libs.empty?
450
+
451
+ decls = Prototype::Runtime.new(patterns: args, env: env, merge: merge, owners_included: owners_included).decls
452
+ else
453
+ stdout.puts "Supported formats: rbi, rb, runtime"
454
+ exit 1
455
+ end
456
+
457
+ writer = Writer.new(out: stdout)
458
+ writer.write decls
459
+ end
460
+
461
+ def run_prototype_file(format, args)
462
+ parser = case format
463
+ when "rbi"
464
+ Prototype::RBI.new()
465
+ when "rb"
466
+ Prototype::RB.new()
467
+ end
468
+
469
+ args.each do |file|
470
+ parser.parse Pathname(file).read
471
+ end
472
+
473
+ parser.decls
474
+ end
475
+
476
+ def run_vendor(args, options)
477
+ clean = false
478
+ vendor_stdlib = false
479
+ vendor_dir = Pathname("vendor/sigs")
480
+
481
+ OptionParser.new do |opts|
482
+ opts.banner = <<~EOB
483
+ Usage: rbs vendor [options] GEMS...
484
+ Vendor signatures in the project directory.
485
+ EOB
486
+
487
+ opts.on("--[no-]clean", "Clean vendor directory (default: no)") do |v|
488
+ clean = v
489
+ end
490
+
491
+ opts.on("--[no-]stdlib", "Vendor stdlib signatures or not (default: no)") do |v|
492
+ vendor_stdlib = v
493
+ end
494
+
495
+ opts.on("--vendor-dir [DIR]", "Specify the directory for vendored signatures (default: vendor/sigs)") do |path|
496
+ vendor_dir = Pathname(path)
497
+ end
498
+ end.parse!(args)
499
+
500
+ stdout.puts "Vendoring signatures to #{vendor_dir}..."
501
+
502
+ vendorer = Vendorer.new(vendor_dir: vendor_dir)
503
+
504
+ if clean
505
+ stdout.puts " Deleting #{vendor_dir}..."
506
+ vendorer.clean!
507
+ end
508
+
509
+ if vendor_stdlib
510
+ stdout.puts " Vendoring standard libraries..."
511
+ vendorer.stdlib!
512
+ end
513
+
514
+ args.each do |gem|
515
+ name, version = EnvironmentLoader.parse_library(gem)
516
+
517
+ unless EnvironmentLoader.gem_sig_path(name, version)
518
+ stdout.puts " ⚠️ Cannot find rubygem: name=#{name}, version=#{version} 🚨"
519
+ else
520
+ stdout.puts " Vendoring gem: name=#{name}, version=#{version}..."
521
+ vendorer.gem!(name, version)
522
+ end
523
+ end
524
+ end
525
+
526
+ def parse_type_name(string)
527
+ Namespace.parse(string).yield_self do |namespace|
528
+ last = namespace.path.last
529
+ TypeName.new(name: last, namespace: namespace.parent)
530
+ end
531
+ end
532
+ end
533
+ end
534
+ end