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,63 @@
1
+ module Steep
2
+ class Project
3
+ class FileLoader
4
+ attr_reader :project
5
+
6
+ def initialize(project:)
7
+ @project = project
8
+ end
9
+
10
+ def each_path_in_patterns(patterns, ext)
11
+ patterns.each do |path|
12
+ absolute_path = project.base_dir + path
13
+
14
+ if absolute_path.file?
15
+ yield project.relative_path(absolute_path)
16
+ else
17
+ files = if absolute_path.directory?
18
+ Pathname.glob("#{absolute_path}/**/*#{ext}")
19
+ else
20
+ Pathname.glob(absolute_path)
21
+ end
22
+
23
+ files.each do |source_path|
24
+ yield project.relative_path(source_path)
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ def load_sources(command_line_patterns)
31
+ project.targets.each do |target|
32
+ Steep.logger.tagged "target=#{target.name}" do
33
+ target_patterns = command_line_patterns.empty? ? target.source_patterns : command_line_patterns
34
+
35
+ each_path_in_patterns target_patterns, ".rb" do |path|
36
+ if target.possible_source_file?(path)
37
+ unless target.source_file?(path)
38
+ Steep.logger.info { "Adding source file: #{path}" }
39
+ target.add_source path, project.absolute_path(path).read
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def load_signatures()
48
+ project.targets.each do |target|
49
+ Steep.logger.tagged "target=#{target.name}" do
50
+ each_path_in_patterns target.signature_patterns, ".rbs" do |path|
51
+ if target.possible_signature_file?(path)
52
+ unless target.signature_file?(path)
53
+ Steep.logger.info { "Adding signature file: #{path}" }
54
+ target.add_signature path, project.absolute_path(path).read
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -3,10 +3,17 @@ module Steep
3
3
  class Options
4
4
  attr_accessor :fallback_any_is_error
5
5
  attr_accessor :allow_missing_definitions
6
+ attr_accessor :vendored_stdlib_path
7
+ attr_accessor :vendored_gems_path
8
+ attr_reader :libraries
6
9
 
7
10
  def initialize
8
11
  self.fallback_any_is_error = false
9
12
  self.allow_missing_definitions = true
13
+ self.vendored_gems_path = nil
14
+ self.vendored_stdlib_path = nil
15
+
16
+ @libraries = []
10
17
  end
11
18
  end
12
19
  end
@@ -0,0 +1,190 @@
1
+ module Steep
2
+ class Project
3
+ class Target
4
+ attr_reader :name
5
+ attr_reader :options
6
+
7
+ attr_reader :source_patterns
8
+ attr_reader :ignore_patterns
9
+ attr_reader :signature_patterns
10
+
11
+ attr_reader :source_files
12
+ attr_reader :signature_files
13
+
14
+ attr_reader :status
15
+
16
+ SignatureSyntaxErrorStatus = Struct.new(:timestamp, :errors, keyword_init: true)
17
+ SignatureValidationErrorStatus = Struct.new(:timestamp, :errors, keyword_init: true)
18
+ TypeCheckStatus = Struct.new(:environment, :subtyping, :type_check_sources, :timestamp, keyword_init: true)
19
+
20
+ def initialize(name:, options:, source_patterns:, ignore_patterns:, signature_patterns:)
21
+ @name = name
22
+ @options = options
23
+ @source_patterns = source_patterns
24
+ @ignore_patterns = ignore_patterns
25
+ @signature_patterns = signature_patterns
26
+
27
+ @source_files = {}
28
+ @signature_files = {}
29
+ end
30
+
31
+ def add_source(path, content)
32
+ file = SourceFile.new(path: path)
33
+ file.content = content
34
+ source_files[path] = file
35
+ end
36
+
37
+ def remove_source(path)
38
+ source_files.delete(path)
39
+ end
40
+
41
+ def update_source(path, content)
42
+ file = source_files[path]
43
+ file.content = content
44
+ end
45
+
46
+ def add_signature(path, content)
47
+ file = SignatureFile.new(path: path)
48
+ file.content = content
49
+ signature_files[path] = file
50
+ end
51
+
52
+ def remove_signature(path)
53
+ signature_files.delete(path)
54
+ end
55
+
56
+ def update_signature(path, content)
57
+ file = signature_files[path]
58
+ file.content = content
59
+ end
60
+
61
+ def source_file?(path)
62
+ source_files.key?(path)
63
+ end
64
+
65
+ def signature_file?(path)
66
+ signature_files.key?(path)
67
+ end
68
+
69
+ def possible_source_file?(path)
70
+ self.class.test_pattern(source_patterns, path) &&
71
+ !self.class.test_pattern(ignore_patterns, path)
72
+ end
73
+
74
+ def possible_signature_file?(path)
75
+ self.class.test_pattern(signature_patterns, path)
76
+ end
77
+
78
+ def self.test_pattern(patterns, path)
79
+ patterns.any? do |pattern|
80
+ p = pattern.end_with?(File::Separator) ? pattern : pattern + File::Separator
81
+ path.to_s.start_with?(p) || File.fnmatch(pattern, path.to_s)
82
+ end
83
+ end
84
+
85
+ def type_check
86
+ load_signatures do |env, check, timestamp|
87
+ run_type_check(env, check, timestamp)
88
+ end
89
+ end
90
+
91
+ def environment
92
+ @environment ||= Ruby::Signature::Environment.new().tap do |env|
93
+ stdlib_root = options.vendored_stdlib_path || Ruby::Signature::EnvironmentLoader::STDLIB_ROOT
94
+ gem_vendor_path = options.vendored_gems_path
95
+ loader = Ruby::Signature::EnvironmentLoader.new(stdlib_root: stdlib_root, gem_vendor_path: gem_vendor_path)
96
+ options.libraries.each do |lib|
97
+ loader.add(library: lib)
98
+ end
99
+ loader.load(env: env)
100
+ end
101
+ end
102
+
103
+ def load_signatures
104
+ timestamp = case status
105
+ when TypeCheckStatus
106
+ status.timestamp
107
+ end
108
+
109
+ updated_files = []
110
+
111
+ signature_files.each_value do |file|
112
+ if !timestamp || file.content_updated_at >= timestamp
113
+ updated_files << file
114
+ file.load!()
115
+ end
116
+ end
117
+
118
+ if signature_files.each_value.all? {|file| file.status.is_a?(SignatureFile::DeclarationsStatus) }
119
+ if status.is_a?(TypeCheckStatus) && updated_files.empty?
120
+ yield status.environment, status.subtyping, status.timestamp
121
+ else
122
+ env = environment.dup
123
+
124
+ signature_files.each_value do |file|
125
+ if file.status.is_a?(SignatureFile::DeclarationsStatus)
126
+ file.status.declarations.each do |decl|
127
+ env << decl
128
+ end
129
+ end
130
+ end
131
+
132
+ definition_builder = Ruby::Signature::DefinitionBuilder.new(env: env)
133
+ factory = AST::Types::Factory.new(builder: definition_builder)
134
+ check = Subtyping::Check.new(factory: factory)
135
+
136
+ validator = Signature::Validator.new(checker: check)
137
+ validator.validate()
138
+
139
+ if validator.no_error?
140
+ yield env, check, Time.now
141
+ else
142
+ @status = SignatureValidationErrorStatus.new(
143
+ errors: validator.each_error.to_a,
144
+ timestamp: Time.now
145
+ )
146
+ end
147
+ end
148
+
149
+ else
150
+ errors = signature_files.each_value.with_object([]) do |file, errors|
151
+ if file.status.is_a?(SignatureFile::ParseErrorStatus)
152
+ errors << file.status.error
153
+ end
154
+ end
155
+
156
+ @status = SignatureSyntaxErrorStatus.new(
157
+ errors: errors,
158
+ timestamp: Time.now
159
+ )
160
+ end
161
+ end
162
+
163
+ def run_type_check(env, check, timestamp)
164
+ type_check_sources = []
165
+
166
+ source_files.each_value do |file|
167
+ if file.type_check(check, timestamp)
168
+ type_check_sources << file
169
+ end
170
+ end
171
+
172
+ @status = TypeCheckStatus.new(
173
+ environment: env,
174
+ subtyping: check,
175
+ type_check_sources: type_check_sources,
176
+ timestamp: timestamp
177
+ )
178
+ end
179
+
180
+ def errors
181
+ case status
182
+ when TypeCheckStatus
183
+ source_files.each_value.flat_map(&:errors)
184
+ else
185
+ []
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -2,102 +2,50 @@ module Steep
2
2
  module Signature
3
3
  module Errors
4
4
  class Base
5
- # @implements Steep__Signature__Error
5
+ attr_reader :location
6
6
 
7
- # @dynamic signature
8
- attr_reader :signature
9
-
10
- def initialize(signature:)
11
- @signature = signature
12
- end
13
- end
14
-
15
- class UnknownTypeName < Base
16
- # @implements Steep__Signature__Errors__UnknownTypeName
17
-
18
- # @dynamic type
19
- attr_reader :type
20
-
21
- def initialize(signature:, type:)
22
- super(signature: signature)
23
- @type = type
24
- end
25
-
26
- def puts(io)
27
- io.puts "UnknownTypeName: signature=#{signature.name}, type=#{type}"
28
- end
29
- end
30
-
31
- class IncompatibleOverride < Base
32
- # @implements Steep__Signature__Errors__IncompatibleOverride
33
-
34
- # @dynamic method_name
35
- attr_reader :method_name
36
- # @dynamic this_method
37
- attr_reader :this_method
38
- # @dynamic super_method
39
- attr_reader :super_method
40
-
41
- def initialize(signature:, method_name:, this_method:, super_method:)
42
- super(signature: signature)
43
- @method_name = method_name
44
- @this_method = this_method
45
- @super_method = super_method
7
+ def loc_to_s
8
+ Ruby::Signature::Location.to_string location
46
9
  end
47
10
 
48
- def puts(io)
49
- io.puts "IncompatibleOverride: signature=#{signature.name}, method=#{method_name}"
11
+ def to_s
12
+ StringIO.new.tap do |io|
13
+ puts io
14
+ end.string
50
15
  end
51
- end
52
-
53
- class InvalidTypeApplication < Base
54
- attr_reader :type_name
55
- attr_reader :type_args
56
16
 
57
- def initialize(signature:, type_name:, type_args:)
58
- super(signature: signature)
59
- @type_name = type_name
60
- @type_args = type_args
61
- end
62
-
63
- def puts(io)
64
- io.puts "InvalidTypeApplication: signature=#{signature.name}, type_name=#{type_name}, type_args=#{type_args}"
17
+ def path
18
+ location.buffer.name
65
19
  end
66
20
  end
67
21
 
68
- class InvalidSelfType < Base
69
- attr_reader :member
22
+ class UnknownTypeNameError < Base
23
+ attr_reader :name
70
24
 
71
- def initialize(signature:, member:)
72
- super(signature: signature)
73
- @member = member
25
+ def initialize(name:, location:)
26
+ @name = name
27
+ @location = location
74
28
  end
75
29
 
76
-
77
30
  def puts(io)
78
- io.puts "InvalidSelfType: signature=#{signature.name}, module=#{member.name}"
31
+ io.puts "#{loc_to_s}\tUnknownTypeNameError: name=#{name}"
79
32
  end
80
33
  end
81
34
 
82
- class UnexpectedTypeNameKind < Base
83
- attr_reader :type
84
- attr_reader :expected_kind
85
-
86
- def initialize(signature:, type:, expected_kind:)
87
- super(signature: signature)
88
- @type = type
89
- @expected_kind = expected_kind
90
- end
91
-
35
+ class InvalidTypeApplicationError < Base
36
+ attr_reader :name
37
+ attr_reader :args
38
+ attr_reader :params
92
39
 
93
- def puts(io)
94
- io.puts "UnexpectedTypeNameKind: signature=#{signature.name}, type=#{type}, kind=#{expected_kind}"
40
+ def initialize(name:, args:, params:, location:)
41
+ @name = name
42
+ @args = args
43
+ @params = params
44
+ @location = location
95
45
  end
96
- end
97
46
 
98
- class ConstructorNoCheck < Base
99
47
  def puts(io)
100
- io.puts "ConstructorNoCheck: signature=#{signature.name}"
48
+ io.puts "#{loc_to_s}\tInvalidTypeApplicationError: name=#{name}, expected=[#{params.join(", ")}], actual=[#{args.join(", ")}]"
101
49
  end
102
50
  end
103
51
  end
@@ -0,0 +1,122 @@
1
+ module Steep
2
+ module Signature
3
+ class Validator
4
+ Location = Ruby::Signature::Location
5
+ Declarations = Ruby::Signature::AST::Declarations
6
+
7
+ attr_reader :checker
8
+
9
+ def initialize(checker:)
10
+ @checker = checker
11
+ @errors = []
12
+ end
13
+
14
+ def has_error?
15
+ !no_error?
16
+ end
17
+
18
+ def no_error?
19
+ @errors.empty?
20
+ end
21
+
22
+ def each_error(&block)
23
+ if block_given?
24
+ @errors.each(&block)
25
+ else
26
+ enum_for :each_error
27
+ end
28
+ end
29
+
30
+ def env
31
+ checker.factory.env
32
+ end
33
+
34
+ def builder
35
+ checker.factory.definition_builder
36
+ end
37
+
38
+ def factory
39
+ checker.factory
40
+ end
41
+
42
+ def validate
43
+ @errors = []
44
+
45
+ validate_decl
46
+ validate_const
47
+ validate_global
48
+ end
49
+
50
+ def validate_one_decl(name, decl)
51
+ case decl
52
+ when Declarations::Class
53
+ rescue_validation_errors do
54
+ Steep.logger.info "#{Location.to_string decl.location}:\tValidating class definition `#{name}`..."
55
+ builder.build_instance(decl.name.absolute!).each_type do |type|
56
+ env.validate type, namespace: Ruby::Signature::Namespace.root
57
+ end
58
+ builder.build_singleton(decl.name.absolute!).each_type do |type|
59
+ env.validate type, namespace: Ruby::Signature::Namespace.root
60
+ end
61
+ end
62
+ when Declarations::Interface
63
+ rescue_validation_errors do
64
+ Steep.logger.info "#{Location.to_string decl.location}:\tValidating interface `#{name}`..."
65
+ builder.build_interface(decl.name.absolute!, decl).each_type do |type|
66
+ env.validate type, namespace: Ruby::Signature::Namespace.root
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ def validate_decl
73
+ env.each_decl do |name, decl|
74
+ validate_one_decl name, decl
75
+ end
76
+ end
77
+
78
+ def validate_const
79
+ env.each_constant do |name, decl|
80
+ rescue_validation_errors do
81
+ Steep.logger.info "#{Location.to_string decl.location}:\tValidating constant `#{name}`..."
82
+ env.validate(decl.type, namespace: name.namespace)
83
+ end
84
+ end
85
+ end
86
+
87
+ def validate_global
88
+ env.each_global do |name, decl|
89
+ rescue_validation_errors do
90
+ Steep.logger.info "#{Location.to_string decl.location}:\tValidating global `#{name}`..."
91
+ env.validate(decl.type, namespace: Ruby::Signature::Namespace.root)
92
+ end
93
+ end
94
+ end
95
+
96
+ def validate_alias
97
+ env.each_alias do |name, decl|
98
+ rescue_validation_errors do
99
+ Steep.logger.info "#{Location.to_string decl.location}:\tValidating alias `#{name}`..."
100
+ env.validate(decl.type, namespace: name.namespace)
101
+ end
102
+ end
103
+ end
104
+
105
+ def rescue_validation_errors
106
+ yield
107
+ rescue Ruby::Signature::InvalidTypeApplicationError => exn
108
+ @errors << Errors::InvalidTypeApplicationError.new(
109
+ name: factory.type_name(exn.type_name),
110
+ args: exn.args.map {|ty| factory.type(ty) },
111
+ params: exn.params.each.map(&:name),
112
+ location: exn.location
113
+ )
114
+ rescue Ruby::Signature::NoTypeFoundError => exn
115
+ @errors << Errors::UnknownTypeNameError.new(
116
+ name: factory.type_name(exn.type_name),
117
+ location: exn.location
118
+ )
119
+ end
120
+ end
121
+ end
122
+ end