steep 0.14.0 → 0.16.3

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 (211) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +0 -3
  3. data/CHANGELOG.md +25 -0
  4. data/Rakefile +0 -13
  5. data/bin/setup +0 -2
  6. data/bin/smoke_runner.rb +0 -1
  7. data/exe/steep +0 -1
  8. data/lib/steep.rb +18 -2
  9. data/lib/steep/annotation_parser.rb +4 -4
  10. data/lib/steep/ast/buffer.rb +11 -7
  11. data/lib/steep/ast/builtin.rb +8 -0
  12. data/lib/steep/ast/types/factory.rb +55 -55
  13. data/lib/steep/cli.rb +16 -1
  14. data/lib/steep/drivers/annotations.rb +1 -1
  15. data/lib/steep/drivers/check.rb +20 -4
  16. data/lib/steep/drivers/langserver.rb +13 -457
  17. data/lib/steep/drivers/utils/driver_helper.rb +1 -1
  18. data/lib/steep/drivers/vendor.rb +2 -2
  19. data/lib/steep/drivers/watch.rb +97 -85
  20. data/lib/steep/drivers/worker.rb +51 -0
  21. data/lib/steep/project.rb +9 -5
  22. data/lib/steep/project/completion_provider.rb +9 -13
  23. data/lib/steep/project/dsl.rb +14 -0
  24. data/lib/steep/project/file.rb +43 -46
  25. data/lib/steep/project/hover_content.rb +17 -8
  26. data/lib/steep/project/options.rb +25 -3
  27. data/lib/steep/project/target.rb +40 -24
  28. data/lib/steep/server/base_worker.rb +56 -0
  29. data/lib/steep/server/code_worker.rb +151 -0
  30. data/lib/steep/server/interaction_worker.rb +281 -0
  31. data/lib/steep/server/master.rb +196 -0
  32. data/lib/steep/server/signature_worker.rb +148 -0
  33. data/lib/steep/server/utils.rb +36 -0
  34. data/lib/steep/server/worker_process.rb +62 -0
  35. data/lib/steep/signature/errors.rb +1 -1
  36. data/lib/steep/signature/validator.rb +13 -13
  37. data/lib/steep/source.rb +1 -1
  38. data/lib/steep/type_construction.rb +996 -726
  39. data/lib/steep/type_inference/constant_env.rb +3 -11
  40. data/lib/steep/type_inference/context.rb +8 -3
  41. data/lib/steep/type_inference/context_array.rb +111 -0
  42. data/lib/steep/type_inference/local_variable_type_env.rb +226 -0
  43. data/lib/steep/type_inference/logic.rb +130 -0
  44. data/lib/steep/type_inference/type_env.rb +5 -69
  45. data/lib/steep/typing.rb +79 -22
  46. data/lib/steep/version.rb +1 -1
  47. data/smoke/alias/Steepfile +1 -0
  48. data/smoke/and/Steepfile +1 -0
  49. data/smoke/array/Steepfile +1 -0
  50. data/smoke/array/b.rb +0 -2
  51. data/smoke/block/Steepfile +1 -0
  52. data/smoke/case/Steepfile +1 -0
  53. data/smoke/class/Steepfile +1 -0
  54. data/smoke/const/Steepfile +1 -0
  55. data/smoke/dstr/Steepfile +1 -0
  56. data/smoke/ensure/Steepfile +1 -0
  57. data/smoke/enumerator/Steepfile +1 -0
  58. data/smoke/extension/Steepfile +1 -0
  59. data/smoke/extension/c.rb +1 -0
  60. data/smoke/hash/Steepfile +1 -0
  61. data/smoke/hello/Steepfile +1 -0
  62. data/smoke/if/Steepfile +1 -0
  63. data/smoke/if/a.rb +1 -1
  64. data/smoke/implements/Steepfile +1 -0
  65. data/smoke/initialize/Steepfile +1 -0
  66. data/smoke/integer/Steepfile +1 -0
  67. data/smoke/interface/Steepfile +1 -0
  68. data/smoke/kwbegin/Steepfile +1 -0
  69. data/smoke/lambda/Steepfile +1 -0
  70. data/smoke/literal/Steepfile +1 -0
  71. data/smoke/map/Steepfile +1 -0
  72. data/smoke/method/Steepfile +1 -0
  73. data/smoke/module/Steepfile +1 -0
  74. data/smoke/regexp/Steepfile +1 -0
  75. data/smoke/regression/Steepfile +1 -0
  76. data/smoke/rescue/Steepfile +1 -0
  77. data/smoke/rescue/a.rb +1 -1
  78. data/smoke/self/Steepfile +1 -0
  79. data/smoke/skip/Steepfile +1 -0
  80. data/smoke/stdout/Steepfile +1 -0
  81. data/smoke/super/Steepfile +1 -0
  82. data/smoke/type_case/Steepfile +1 -0
  83. data/smoke/yield/Steepfile +1 -0
  84. data/steep.gemspec +7 -8
  85. metadata +26 -141
  86. data/exe/rbs +0 -3
  87. data/exe/ruby-signature +0 -3
  88. data/vendor/ruby-signature/.github/workflows/ruby.yml +0 -27
  89. data/vendor/ruby-signature/.gitignore +0 -12
  90. data/vendor/ruby-signature/.rubocop.yml +0 -15
  91. data/vendor/ruby-signature/BSDL +0 -22
  92. data/vendor/ruby-signature/COPYING +0 -56
  93. data/vendor/ruby-signature/Gemfile +0 -6
  94. data/vendor/ruby-signature/README.md +0 -93
  95. data/vendor/ruby-signature/Rakefile +0 -67
  96. data/vendor/ruby-signature/bin/annotate-with-rdoc +0 -156
  97. data/vendor/ruby-signature/bin/console +0 -14
  98. data/vendor/ruby-signature/bin/query-rdoc +0 -103
  99. data/vendor/ruby-signature/bin/setup +0 -10
  100. data/vendor/ruby-signature/bin/sort +0 -88
  101. data/vendor/ruby-signature/bin/test_runner.rb +0 -17
  102. data/vendor/ruby-signature/docs/CONTRIBUTING.md +0 -97
  103. data/vendor/ruby-signature/docs/sigs.md +0 -148
  104. data/vendor/ruby-signature/docs/stdlib.md +0 -152
  105. data/vendor/ruby-signature/docs/syntax.md +0 -528
  106. data/vendor/ruby-signature/exe/rbs +0 -3
  107. data/vendor/ruby-signature/exe/ruby-signature +0 -7
  108. data/vendor/ruby-signature/lib/ruby/signature.rb +0 -64
  109. data/vendor/ruby-signature/lib/ruby/signature/ast/annotation.rb +0 -29
  110. data/vendor/ruby-signature/lib/ruby/signature/ast/comment.rb +0 -29
  111. data/vendor/ruby-signature/lib/ruby/signature/ast/declarations.rb +0 -391
  112. data/vendor/ruby-signature/lib/ruby/signature/ast/members.rb +0 -364
  113. data/vendor/ruby-signature/lib/ruby/signature/buffer.rb +0 -52
  114. data/vendor/ruby-signature/lib/ruby/signature/builtin_names.rb +0 -54
  115. data/vendor/ruby-signature/lib/ruby/signature/cli.rb +0 -555
  116. data/vendor/ruby-signature/lib/ruby/signature/constant.rb +0 -28
  117. data/vendor/ruby-signature/lib/ruby/signature/constant_table.rb +0 -152
  118. data/vendor/ruby-signature/lib/ruby/signature/definition.rb +0 -172
  119. data/vendor/ruby-signature/lib/ruby/signature/definition_builder.rb +0 -921
  120. data/vendor/ruby-signature/lib/ruby/signature/environment.rb +0 -283
  121. data/vendor/ruby-signature/lib/ruby/signature/environment_loader.rb +0 -138
  122. data/vendor/ruby-signature/lib/ruby/signature/environment_walker.rb +0 -126
  123. data/vendor/ruby-signature/lib/ruby/signature/errors.rb +0 -189
  124. data/vendor/ruby-signature/lib/ruby/signature/location.rb +0 -104
  125. data/vendor/ruby-signature/lib/ruby/signature/method_type.rb +0 -125
  126. data/vendor/ruby-signature/lib/ruby/signature/namespace.rb +0 -93
  127. data/vendor/ruby-signature/lib/ruby/signature/parser.y +0 -1344
  128. data/vendor/ruby-signature/lib/ruby/signature/prototype/rb.rb +0 -444
  129. data/vendor/ruby-signature/lib/ruby/signature/prototype/rbi.rb +0 -579
  130. data/vendor/ruby-signature/lib/ruby/signature/prototype/runtime.rb +0 -383
  131. data/vendor/ruby-signature/lib/ruby/signature/substitution.rb +0 -48
  132. data/vendor/ruby-signature/lib/ruby/signature/test.rb +0 -28
  133. data/vendor/ruby-signature/lib/ruby/signature/test/errors.rb +0 -63
  134. data/vendor/ruby-signature/lib/ruby/signature/test/hook.rb +0 -290
  135. data/vendor/ruby-signature/lib/ruby/signature/test/setup.rb +0 -58
  136. data/vendor/ruby-signature/lib/ruby/signature/test/spy.rb +0 -327
  137. data/vendor/ruby-signature/lib/ruby/signature/test/test_helper.rb +0 -185
  138. data/vendor/ruby-signature/lib/ruby/signature/test/type_check.rb +0 -256
  139. data/vendor/ruby-signature/lib/ruby/signature/type_name.rb +0 -72
  140. data/vendor/ruby-signature/lib/ruby/signature/types.rb +0 -932
  141. data/vendor/ruby-signature/lib/ruby/signature/variance_calculator.rb +0 -140
  142. data/vendor/ruby-signature/lib/ruby/signature/vendorer.rb +0 -49
  143. data/vendor/ruby-signature/lib/ruby/signature/version.rb +0 -5
  144. data/vendor/ruby-signature/lib/ruby/signature/writer.rb +0 -271
  145. data/vendor/ruby-signature/ruby-signature.gemspec +0 -45
  146. data/vendor/ruby-signature/stdlib/abbrev/abbrev.rbs +0 -3
  147. data/vendor/ruby-signature/stdlib/base64/base64.rbs +0 -15
  148. data/vendor/ruby-signature/stdlib/builtin/array.rbs +0 -1997
  149. data/vendor/ruby-signature/stdlib/builtin/basic_object.rbs +0 -280
  150. data/vendor/ruby-signature/stdlib/builtin/binding.rbs +0 -177
  151. data/vendor/ruby-signature/stdlib/builtin/builtin.rbs +0 -35
  152. data/vendor/ruby-signature/stdlib/builtin/class.rbs +0 -145
  153. data/vendor/ruby-signature/stdlib/builtin/comparable.rbs +0 -116
  154. data/vendor/ruby-signature/stdlib/builtin/complex.rbs +0 -400
  155. data/vendor/ruby-signature/stdlib/builtin/constants.rbs +0 -37
  156. data/vendor/ruby-signature/stdlib/builtin/data.rbs +0 -5
  157. data/vendor/ruby-signature/stdlib/builtin/deprecated.rbs +0 -2
  158. data/vendor/ruby-signature/stdlib/builtin/dir.rbs +0 -419
  159. data/vendor/ruby-signature/stdlib/builtin/encoding.rbs +0 -606
  160. data/vendor/ruby-signature/stdlib/builtin/enumerable.rbs +0 -404
  161. data/vendor/ruby-signature/stdlib/builtin/enumerator.rbs +0 -260
  162. data/vendor/ruby-signature/stdlib/builtin/errno.rbs +0 -781
  163. data/vendor/ruby-signature/stdlib/builtin/errors.rbs +0 -582
  164. data/vendor/ruby-signature/stdlib/builtin/exception.rbs +0 -193
  165. data/vendor/ruby-signature/stdlib/builtin/false_class.rbs +0 -40
  166. data/vendor/ruby-signature/stdlib/builtin/fiber.rbs +0 -68
  167. data/vendor/ruby-signature/stdlib/builtin/fiber_error.rbs +0 -12
  168. data/vendor/ruby-signature/stdlib/builtin/file.rbs +0 -476
  169. data/vendor/ruby-signature/stdlib/builtin/file_test.rbs +0 -59
  170. data/vendor/ruby-signature/stdlib/builtin/float.rbs +0 -696
  171. data/vendor/ruby-signature/stdlib/builtin/gc.rbs +0 -121
  172. data/vendor/ruby-signature/stdlib/builtin/hash.rbs +0 -1029
  173. data/vendor/ruby-signature/stdlib/builtin/integer.rbs +0 -710
  174. data/vendor/ruby-signature/stdlib/builtin/io.rbs +0 -683
  175. data/vendor/ruby-signature/stdlib/builtin/kernel.rbs +0 -574
  176. data/vendor/ruby-signature/stdlib/builtin/marshal.rbs +0 -135
  177. data/vendor/ruby-signature/stdlib/builtin/match_data.rbs +0 -271
  178. data/vendor/ruby-signature/stdlib/builtin/math.rbs +0 -66
  179. data/vendor/ruby-signature/stdlib/builtin/method.rbs +0 -182
  180. data/vendor/ruby-signature/stdlib/builtin/module.rbs +0 -248
  181. data/vendor/ruby-signature/stdlib/builtin/nil_class.rbs +0 -82
  182. data/vendor/ruby-signature/stdlib/builtin/numeric.rbs +0 -409
  183. data/vendor/ruby-signature/stdlib/builtin/object.rbs +0 -824
  184. data/vendor/ruby-signature/stdlib/builtin/proc.rbs +0 -426
  185. data/vendor/ruby-signature/stdlib/builtin/process.rbs +0 -354
  186. data/vendor/ruby-signature/stdlib/builtin/random.rbs +0 -93
  187. data/vendor/ruby-signature/stdlib/builtin/range.rbs +0 -226
  188. data/vendor/ruby-signature/stdlib/builtin/rational.rbs +0 -424
  189. data/vendor/ruby-signature/stdlib/builtin/rb_config.rbs +0 -10
  190. data/vendor/ruby-signature/stdlib/builtin/regexp.rbs +0 -1083
  191. data/vendor/ruby-signature/stdlib/builtin/ruby_vm.rbs +0 -14
  192. data/vendor/ruby-signature/stdlib/builtin/signal.rbs +0 -55
  193. data/vendor/ruby-signature/stdlib/builtin/string.rbs +0 -1894
  194. data/vendor/ruby-signature/stdlib/builtin/string_io.rbs +0 -13
  195. data/vendor/ruby-signature/stdlib/builtin/struct.rbs +0 -40
  196. data/vendor/ruby-signature/stdlib/builtin/symbol.rbs +0 -230
  197. data/vendor/ruby-signature/stdlib/builtin/thread.rbs +0 -1112
  198. data/vendor/ruby-signature/stdlib/builtin/thread_group.rbs +0 -23
  199. data/vendor/ruby-signature/stdlib/builtin/time.rbs +0 -739
  200. data/vendor/ruby-signature/stdlib/builtin/trace_point.rbs +0 -91
  201. data/vendor/ruby-signature/stdlib/builtin/true_class.rbs +0 -46
  202. data/vendor/ruby-signature/stdlib/builtin/unbound_method.rbs +0 -159
  203. data/vendor/ruby-signature/stdlib/builtin/warning.rbs +0 -17
  204. data/vendor/ruby-signature/stdlib/erb/erb.rbs +0 -18
  205. data/vendor/ruby-signature/stdlib/find/find.rbs +0 -44
  206. data/vendor/ruby-signature/stdlib/pathname/pathname.rbs +0 -21
  207. data/vendor/ruby-signature/stdlib/prime/integer-extension.rbs +0 -23
  208. data/vendor/ruby-signature/stdlib/prime/prime.rbs +0 -188
  209. data/vendor/ruby-signature/stdlib/securerandom/securerandom.rbs +0 -9
  210. data/vendor/ruby-signature/stdlib/set/set.rbs +0 -77
  211. data/vendor/ruby-signature/stdlib/tmpdir/tmpdir.rbs +0 -53
@@ -8,7 +8,7 @@ module Steep
8
8
  raise "Cannot find a configuration at #{path}: `steep init` to scaffold" unless path.file?
9
9
 
10
10
  steep_file_path = path.absolute? ? path : Pathname.pwd + path
11
- Project.new(base_dir: steep_file_path.parent).tap do |project|
11
+ Project.new(steepfile_path: steep_file_path).tap do |project|
12
12
  Project::DSL.parse(project, path.read, filename: path.to_s)
13
13
  end
14
14
  end
@@ -20,7 +20,7 @@ module Steep
20
20
  def run
21
21
  stdout.puts "Vendoring into #{vendor_dir}..."
22
22
 
23
- vendorer = Ruby::Signature::Vendorer.new(vendor_dir: vendor_dir)
23
+ vendorer = RBS::Vendorer.new(vendor_dir: vendor_dir)
24
24
 
25
25
  if clean_before
26
26
  stdout.puts " Cleaning directory..."
@@ -32,7 +32,7 @@ module Steep
32
32
 
33
33
  if defined?(Bundler)
34
34
  Bundler.locked_gems.specs.each do |spec|
35
- if Ruby::Signature::EnvironmentLoader.gem_sig_path(spec.name, spec.version.to_s).directory?
35
+ if RBS::EnvironmentLoader.gem_sig_path(spec.name, spec.version.to_s).directory?
36
36
  stdout.puts " Vendoring rubygem: #{spec.full_name}..."
37
37
  vendorer.gem! spec.name, spec.version.to_s
38
38
  end
@@ -15,110 +15,122 @@ module Steep
15
15
  @queue = Thread::Queue.new
16
16
  end
17
17
 
18
- def listener
19
- @listener ||= begin
20
- Steep.logger.info "Watching #{dirs.join(", ")}..."
21
- Listen.to(*dirs.map(&:to_s)) do |modified, added, removed|
22
- Steep.logger.tagged "watch" do
23
- Steep.logger.info "Received file system updates: modified=[#{modified.join(",")}], added=[#{added.join(",")}], removed=[#{removed.join(",")}]"
24
- end
25
- queue << [modified, added, removed]
26
- end
18
+ def run()
19
+ if dirs.empty?
20
+ stdout.puts "Specify directories to watch"
21
+ return 1
27
22
  end
28
- end
29
23
 
30
- def type_check_loop(project)
31
- until queue.closed?
32
- stdout.puts "🚥 Waiting for updates..."
24
+ project = load_config()
33
25
 
34
- events = []
35
- events << queue.deq
36
- until queue.empty?
37
- events << queue.deq(nonblock: true)
38
- end
26
+ loader = Project::FileLoader.new(project: project)
27
+ loader.load_sources(dirs)
28
+ loader.load_signatures()
39
29
 
40
- events.compact.each do |modified, added, removed|
41
- modified.each do |name|
42
- path = Pathname(name).relative_path_from(Pathname.pwd)
30
+ client_read, server_write = IO.pipe
31
+ server_read, client_write = IO.pipe
43
32
 
44
- project.targets.each do |target|
45
- target.update_source path, path.read if target.source_file?(path)
46
- target.update_signature path, path.read if target.signature_file?(path)
47
- end
48
- end
33
+ client_reader = LanguageServer::Protocol::Transport::Io::Reader.new(client_read)
34
+ client_writer = LanguageServer::Protocol::Transport::Io::Writer.new(client_write)
49
35
 
50
- added.each do |name|
51
- path = Pathname(name).relative_path_from(Pathname.pwd)
36
+ server_reader = LanguageServer::Protocol::Transport::Io::Reader.new(server_read)
37
+ server_writer = LanguageServer::Protocol::Transport::Io::Writer.new(server_write)
52
38
 
53
- project.targets.each do |target|
54
- target.add_source path, path.read if target.possible_source_file?(path)
55
- target.add_signature path, path.read if target.possible_signature_file?(path)
56
- end
57
- end
39
+ interaction_worker = Server::WorkerProcess.spawn_worker(:interaction, name: "interaction", steepfile: project.steepfile_path)
40
+ signature_worker = Server::WorkerProcess.spawn_worker(:signature, name: "signature", steepfile: project.steepfile_path)
41
+ code_workers = Server::WorkerProcess.spawn_code_workers(steepfile: project.steepfile_path)
58
42
 
59
- removed.each do |name|
60
- path = Pathname(name).relative_path_from(Pathname.pwd)
43
+ master = Server::Master.new(
44
+ project: project,
45
+ reader: server_reader,
46
+ writer: server_writer,
47
+ interaction_worker: interaction_worker,
48
+ signature_worker: signature_worker,
49
+ code_workers: code_workers
50
+ )
61
51
 
62
- project.targets.each do |target|
63
- target.remove_source path if target.source_file?(path)
64
- target.remove_signature path if target.signature_file?(path)
65
- end
52
+ main_thread = Thread.start do
53
+ master.start()
54
+ end
55
+ main_thread.abort_on_exception = true
56
+
57
+ client_writer.write(method: "initialize", id: 0)
58
+
59
+ Steep.logger.info "Watching #{dirs.join(", ")}..."
60
+ listener = Listen.to(*dirs.map(&:to_s)) do |modified, added, removed|
61
+ stdout.puts "🔬 Type checking updated files..."
62
+
63
+ version = Time.now.to_i
64
+ Steep.logger.tagged "watch" do
65
+ Steep.logger.info "Received file system updates: modified=[#{modified.join(",")}], added=[#{added.join(",")}], removed=[#{removed.join(",")}]"
66
+
67
+ (modified + added).each do |path|
68
+ client_writer.write(
69
+ method: "textDocument/didChange",
70
+ params: {
71
+ textDocument: {
72
+ uri: "file://#{path}",
73
+ version: version
74
+ },
75
+ contentChanges: [
76
+ {
77
+ text: Pathname(path).read
78
+ }
79
+ ]
80
+ }
81
+ )
66
82
  end
67
- end
68
83
 
69
- stdout.puts "🔬 Type checking..."
70
- type_check project
71
- print_project_result project
72
- end
73
- rescue ClosedQueueError
74
- # nop
75
- end
84
+ removed.each do |path|
85
+ client_writer.write(
86
+ method: "textDocument/didChange",
87
+ params: {
88
+ textDocument: {
89
+ uri: "file://#{path}",
90
+ version: version
91
+ },
92
+ contentChanges: [
93
+ {
94
+ text: ""
95
+ }
96
+ ]
97
+ }
98
+ )
99
+ end
100
+ end
101
+ end.tap(&:start)
76
102
 
77
- def print_project_result(project)
78
- project.targets.each do |target|
79
- Steep.logger.tagged "target=#{target.name}" do
80
- case (status = target.status)
81
- when Project::Target::SignatureSyntaxErrorStatus
82
- printer = SignatureErrorPrinter.new(stdout: stdout, stderr: stderr)
83
- printer.print_syntax_errors(status.errors)
84
- when Project::Target::SignatureValidationErrorStatus
85
- printer = SignatureErrorPrinter.new(stdout: stdout, stderr: stderr)
86
- printer.print_semantic_errors(status.errors)
87
- when Project::Target::TypeCheckStatus
88
- status.type_check_sources.each do |source_file|
89
- source_file.errors.each do |error|
90
- error.print_to stdout
103
+ begin
104
+ stdout.puts "👀 Watching directories, Ctrl-C to stop."
105
+ client_reader.read do |response|
106
+ case response[:method]
107
+ when "textDocument/publishDiagnostics"
108
+ uri = URI.parse(response[:params][:uri])
109
+ path = project.relative_path(Pathname(uri.path))
110
+
111
+ diagnostics = response[:params][:diagnostics]
112
+
113
+ unless diagnostics.empty?
114
+ diagnostics.each do |diagnostic|
115
+ start = diagnostic[:range][:start]
116
+ loc = "#{start[:line]+1}:#{start[:character]}"
117
+ message = diagnostic[:message].chomp.lines.join(" ")
118
+
119
+ stdout.puts "#{path}:#{loc}: #{message}"
91
120
  end
92
121
  end
93
122
  end
94
123
  end
95
- end
96
- end
97
-
98
- def run()
99
- if dirs.empty?
100
- stdout.puts "Specify directories to watch"
101
- return 1
102
- end
103
-
104
- project = load_config()
105
-
106
- loader = Project::FileLoader.new(project: project)
107
- loader.load_sources([])
108
- loader.load_signatures()
109
-
110
- type_check project
111
- print_project_result project
112
-
113
- listener.start
114
-
115
- stdout.puts "👀 Watching directories, Ctrl-C to stop."
116
- begin
117
- type_check_loop project
118
124
  rescue Interrupt
119
- # bye
125
+ stdout.puts "Shutting down workers..."
126
+ client_writer.write({ method: :shutdown, id: 10000 })
127
+ client_writer.write({ method: :exit })
128
+ client_writer.io.close()
120
129
  end
121
130
 
131
+ listener.stop
132
+ main_thread.join
133
+
122
134
  0
123
135
  end
124
136
  end
@@ -0,0 +1,51 @@
1
+ module Steep
2
+ module Drivers
3
+ class Worker
4
+ attr_reader :stdout, :stderr, :stdin
5
+
6
+ attr_accessor :steepfile_path
7
+ attr_accessor :worker_type
8
+ attr_accessor :worker_name
9
+
10
+ include Utils::DriverHelper
11
+
12
+ def initialize(stdout:, stderr:, stdin:)
13
+ @stdout = stdout
14
+ @stderr = stderr
15
+ @stdin = stdin
16
+ end
17
+
18
+ def run()
19
+ Steep.logger.tagged("#{worker_type}:#{worker_name}") do
20
+ project = load_config()
21
+
22
+ loader = Project::FileLoader.new(project: project)
23
+ loader.load_sources([])
24
+ loader.load_signatures()
25
+
26
+ reader = LanguageServer::Protocol::Transport::Io::Reader.new(stdin)
27
+ writer = LanguageServer::Protocol::Transport::Io::Writer.new(stdout)
28
+
29
+ worker = case worker_type
30
+ when :code
31
+ Server::CodeWorker.new(project: project, reader: reader, writer: writer)
32
+ when :signature
33
+ Server::SignatureWorker.new(project: project, reader: reader, writer: writer)
34
+ when :interaction
35
+ Server::InteractionWorker.new(project: project, reader: reader, writer: writer)
36
+ else
37
+ raise "Unknown worker type: #{worker_type}"
38
+ end
39
+
40
+ Steep.logger.info "Starting #{worker_type} worker..."
41
+
42
+ worker.run()
43
+ rescue Interrupt
44
+ Steep.logger.info "Shutting down by interrupt..."
45
+ end
46
+
47
+ 0
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,17 +1,21 @@
1
1
  module Steep
2
2
  class Project
3
3
  attr_reader :targets
4
- attr_reader :base_dir
4
+ attr_reader :steepfile_path
5
5
 
6
- def initialize(base_dir:)
6
+ def initialize(steepfile_path:)
7
7
  @targets = []
8
- @base_dir = base_dir
8
+ @steepfile_path = steepfile_path
9
9
 
10
- unless base_dir.absolute?
11
- raise "Project#initialize(base_dir:): base_dir should be absolute path"
10
+ unless steepfile_path.absolute?
11
+ raise "Project#initialize(steepfile_path:): steepfile_path should be absolute path"
12
12
  end
13
13
  end
14
14
 
15
+ def base_dir
16
+ steepfile_path.parent
17
+ end
18
+
15
19
  def relative_path(path)
16
20
  path.relative_path_from(base_dir)
17
21
  end
@@ -47,8 +47,10 @@ module Steep
47
47
  position = Position.new(line: line, column: column)
48
48
 
49
49
  begin
50
- Steep.measure "type_check!" do
51
- type_check!(source_text)
50
+ Steep.logger.tagged "completion_provider#run(line: #{line}, column: #{column})" do
51
+ Steep.measure "type_check!" do
52
+ type_check!(source_text)
53
+ end
52
54
  end
53
55
 
54
56
  Steep.measure "completion item collection" do
@@ -99,10 +101,11 @@ module Steep
99
101
 
100
102
  items = []
101
103
 
104
+ context = typing.context_at(line: position.line, column: position.column)
105
+
102
106
  case
103
107
  when node.type == :send && node.children[0] == nil && at_end?(position, of: node.loc.selector)
104
108
  # foo ←
105
- context = typing.context_of(node: node)
106
109
  prefix = node.children[1].to_s
107
110
 
108
111
  method_items_for_receiver_type(context.self_type,
@@ -114,12 +117,10 @@ module Steep
114
117
 
115
118
  when node.type == :lvar && at_end?(position, of: node.loc)
116
119
  # foo ← (lvar)
117
- context = typing.context_of(node: node)
118
120
  local_variable_items_for_context(context, position: position, prefix: node.children[0].name.to_s, items: items)
119
121
 
120
122
  when node.type == :send && node.children[0] && at_end?(position, of: node.loc.selector)
121
123
  # foo.ba ←
122
- context = typing.context_of(node: node)
123
124
  receiver_type = case (type = typing.type_of(node: node.children[0]))
124
125
  when AST::Types::Self
125
126
  context.self_type
@@ -136,7 +137,6 @@ module Steep
136
137
 
137
138
  when node.type == :const && node.children[0] == nil && at_end?(position, of: node.loc)
138
139
  # Foo ← (const)
139
- context = typing.context_of(node: node)
140
140
  prefix = node.children[1].to_s
141
141
 
142
142
  method_items_for_receiver_type(context.self_type,
@@ -147,7 +147,6 @@ module Steep
147
147
 
148
148
  when node.type == :send && at_end?(position, of: node.loc.dot)
149
149
  # foo.← ba
150
- context = typing.context_of(node: node)
151
150
  receiver_type = case (type = typing.type_of(node: node.children[0]))
152
151
  when AST::Types::Self
153
152
  context.self_type
@@ -163,12 +162,9 @@ module Steep
163
162
 
164
163
  when node.type == :ivar && at_end?(position, of: node.loc)
165
164
  # @fo ←
166
- context = typing.context_of(node: node)
167
165
  instance_variable_items_for_context(context, position: position, prefix: node.children[0].to_s, items: items)
168
166
 
169
167
  else
170
- context = typing.context_of(node: node)
171
-
172
168
  method_items_for_receiver_type(context.self_type,
173
169
  include_private: true,
174
170
  prefix: "",
@@ -190,7 +186,7 @@ module Steep
190
186
  return [] unless node
191
187
 
192
188
  if at_end?(shift_pos, of: node.loc)
193
- context = typing.context_of(node: node)
189
+ context = typing.context_at(line: position.line, column: position.column)
194
190
  receiver_type = case (type = typing.type_of(node: node))
195
191
  when AST::Types::Self
196
192
  context.self_type
@@ -218,7 +214,7 @@ module Steep
218
214
 
219
215
  return [] unless node
220
216
 
221
- context = typing.context_of(node: node)
217
+ context = typing.context_at(line: position.line, column: position.column)
222
218
  items = []
223
219
  instance_variable_items_for_context(context, prefix: "", position: position, items: items)
224
220
  items
@@ -263,7 +259,7 @@ module Steep
263
259
 
264
260
  def local_variable_items_for_context(context, position:, prefix:, items:)
265
261
  range = range_for(position, prefix: prefix)
266
- context.type_env.lvar_types.each do |name, type|
262
+ context.lvar_env.each do |name, type|
267
263
  if name.to_s.start_with?(prefix)
268
264
  items << LocalVariableItem.new(identifier: name,
269
265
  range: range,
@@ -9,6 +9,7 @@ module Steep
9
9
  attr_reader :ignored_sources
10
10
  attr_reader :no_builtin
11
11
  attr_reader :vendor_dir
12
+ attr_reader :strictness_level
12
13
 
13
14
  def initialize(name, sources: [], libraries: [], signatures: [], ignored_sources: [])
14
15
  @name = name
@@ -17,6 +18,7 @@ module Steep
17
18
  @signatures = signatures
18
19
  @ignored_sources = ignored_sources
19
20
  @vendor_dir = nil
21
+ @strictness_level = :default
20
22
  end
21
23
 
22
24
  def initialize_copy(other)
@@ -26,6 +28,7 @@ module Steep
26
28
  @signatures = other.signatures.dup
27
29
  @ignored_sources = other.ignored_sources.dup
28
30
  @vendor_dir = other.vendor_dir
31
+ @strictness_level = other.strictness_level
29
32
  end
30
33
 
31
34
  def check(*args)
@@ -40,6 +43,10 @@ module Steep
40
43
  libraries.push(*args)
41
44
  end
42
45
 
46
+ def typing_options(level)
47
+ @strictness_level = level
48
+ end
49
+
43
50
  def signature(*args)
44
51
  signatures.push(*args)
45
52
  end
@@ -114,6 +121,13 @@ module Steep
114
121
  options: Options.new.tap do |options|
115
122
  options.libraries.push(*target.libraries)
116
123
 
124
+ case target.strictness_level
125
+ when :strict
126
+ options.apply_strict_typing_options!
127
+ when :lenient
128
+ options.apply_lenient_typing_options!
129
+ end
130
+
117
131
  case target.vendor_dir
118
132
  when Array
119
133
  options.vendored_stdlib_path = target.vendor_dir[0]