steep 1.1.1 → 1.2.0.pre.1

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 (140) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -0
  3. data/Gemfile +0 -1
  4. data/Gemfile.lock +12 -11
  5. data/Gemfile.steep +1 -1
  6. data/Gemfile.steep.lock +9 -9
  7. data/README.md +3 -3
  8. data/Steepfile +23 -0
  9. data/bin/steep-prof +2 -1
  10. data/lib/steep/annotation_parser.rb +1 -1
  11. data/lib/steep/ast/types/class.rb +4 -0
  12. data/lib/steep/ast/types/factory.rb +86 -602
  13. data/lib/steep/ast/types/instance.rb +4 -0
  14. data/lib/steep/ast/types/literal.rb +1 -1
  15. data/lib/steep/ast/types/proc.rb +22 -8
  16. data/lib/steep/ast/types/self.rb +4 -0
  17. data/lib/steep/ast/types/union.rb +1 -1
  18. data/lib/steep/cli.rb +24 -1
  19. data/lib/steep/diagnostic/ruby.rb +17 -22
  20. data/lib/steep/drivers/checkfile.rb +205 -0
  21. data/lib/steep/drivers/validate.rb +3 -1
  22. data/lib/steep/equatable.rb +2 -0
  23. data/lib/steep/interface/block.rb +21 -11
  24. data/lib/steep/interface/builder.rb +756 -0
  25. data/lib/steep/interface/function.rb +32 -24
  26. data/lib/steep/interface/method_type.rb +191 -78
  27. data/lib/steep/interface/shape.rb +132 -0
  28. data/lib/steep/interface/substitution.rb +23 -12
  29. data/lib/steep/interface/type_param.rb +1 -2
  30. data/lib/steep/path_helper.rb +1 -1
  31. data/lib/steep/project.rb +5 -7
  32. data/lib/steep/server/base_worker.rb +2 -2
  33. data/lib/steep/server/change_buffer.rb +4 -3
  34. data/lib/steep/server/interaction_worker.rb +1 -1
  35. data/lib/steep/server/master.rb +69 -9
  36. data/lib/steep/server/type_check_worker.rb +13 -11
  37. data/lib/steep/server/worker_process.rb +9 -7
  38. data/lib/steep/services/completion_provider.rb +15 -3
  39. data/lib/steep/services/hover_provider/singleton_methods.rb +5 -6
  40. data/lib/steep/services/signature_service.rb +13 -8
  41. data/lib/steep/services/type_check_service.rb +2 -0
  42. data/lib/steep/signature/validator.rb +1 -1
  43. data/lib/steep/subtyping/check.rb +154 -103
  44. data/lib/steep/subtyping/relation.rb +3 -3
  45. data/lib/steep/subtyping/result.rb +20 -2
  46. data/lib/steep/subtyping/variable_variance.rb +9 -0
  47. data/lib/steep/type_construction.rb +558 -299
  48. data/lib/steep/type_inference/block_params.rb +169 -86
  49. data/lib/steep/type_inference/logic_type_interpreter.rb +9 -14
  50. data/lib/steep/type_inference/method_params.rb +12 -7
  51. data/lib/steep/type_inference/send_args.rb +41 -35
  52. data/lib/steep/type_inference/type_env_builder.rb +1 -1
  53. data/lib/steep/version.rb +1 -1
  54. data/lib/steep.rb +71 -2
  55. data/rbs_collection.steep.lock.yaml +18 -30
  56. data/rbs_collection.steep.yaml +1 -0
  57. data/sig/shims/language-server_protocol.rbs +20 -0
  58. data/sig/shims/tagged_logging.rbs +6 -0
  59. data/sig/steep/ast/annotation/collection.rbs +6 -6
  60. data/sig/steep/ast/types/class.rbs +3 -0
  61. data/sig/steep/ast/types/factory.rbs +38 -32
  62. data/sig/steep/ast/types/instance.rbs +3 -0
  63. data/sig/steep/ast/types/intersection.rbs +1 -1
  64. data/sig/steep/ast/types/literal.rbs +7 -7
  65. data/sig/steep/ast/types/name.rbs +14 -13
  66. data/sig/steep/ast/types/proc.rbs +3 -1
  67. data/sig/steep/ast/types/self.rbs +3 -0
  68. data/sig/steep/ast/types/var.rbs +1 -1
  69. data/sig/steep/diagnostic/ruby.rbs +30 -34
  70. data/sig/steep/drivers/annotations.rbs +17 -0
  71. data/sig/steep/drivers/check.rbs +33 -0
  72. data/sig/steep/drivers/checkfile.rbs +26 -0
  73. data/sig/steep/drivers/diagnostic_printer.rbs +25 -0
  74. data/sig/steep/drivers/init.rbs +19 -0
  75. data/sig/steep/drivers/langserver.rbs +35 -0
  76. data/sig/steep/drivers/print_project.rbs +15 -0
  77. data/sig/steep/drivers/stats.rbs +37 -0
  78. data/sig/steep/drivers/utils/driver_helper.rbs +23 -0
  79. data/sig/steep/drivers/utils/jobs_count.rbs +11 -0
  80. data/sig/steep/drivers/validate.rbs +15 -0
  81. data/sig/steep/drivers/vendor.rbs +19 -0
  82. data/sig/steep/drivers/watch.rbs +27 -0
  83. data/sig/steep/drivers/worker.rbs +31 -0
  84. data/sig/steep/equatable.rbs +11 -0
  85. data/sig/steep/index/rbs_index.rbs +91 -0
  86. data/sig/steep/index/signature_symbol_provider.rbs +29 -0
  87. data/sig/steep/index/source_index.rbs +63 -0
  88. data/sig/steep/interface/block.rbs +3 -1
  89. data/sig/steep/interface/builder.rbs +152 -0
  90. data/sig/steep/interface/function.rbs +67 -55
  91. data/sig/steep/interface/method_type.rbs +60 -12
  92. data/sig/steep/interface/shape.rbs +61 -0
  93. data/sig/steep/interface/substitution.rbs +18 -22
  94. data/sig/steep/interface/type_param.rbs +9 -1
  95. data/sig/steep/path_helper.rbs +7 -0
  96. data/sig/steep/project/pattern.rbs +10 -10
  97. data/sig/steep/project/target.rbs +2 -2
  98. data/sig/steep/project.rbs +15 -8
  99. data/sig/steep/server/base_worker.rbs +49 -0
  100. data/sig/steep/server/change_buffer.rbs +32 -0
  101. data/sig/steep/server/interaction_worker.rbs +41 -0
  102. data/sig/steep/server/lsp_formatter.rbs +29 -0
  103. data/sig/steep/server/master.rbs +260 -0
  104. data/sig/steep/server/type_check_worker.rbs +135 -0
  105. data/sig/steep/server/worker_process.rbs +29 -0
  106. data/sig/steep/services/completion_provider.rbs +5 -5
  107. data/sig/steep/services/content_change.rbs +14 -12
  108. data/sig/steep/services/file_loader.rbs +12 -4
  109. data/sig/steep/services/hover_provider/singleton_methods.rbs +1 -1
  110. data/sig/steep/services/path_assignment.rbs +7 -7
  111. data/sig/steep/services/signature_service.rbs +67 -40
  112. data/sig/steep/services/type_check_service.rbs +53 -39
  113. data/sig/steep/subtyping/check.rbs +80 -44
  114. data/sig/steep/subtyping/relation.rbs +24 -22
  115. data/sig/steep/subtyping/result.rbs +48 -30
  116. data/sig/steep/subtyping/variable_variance.rbs +2 -0
  117. data/sig/steep/type_construction.rbs +132 -23
  118. data/sig/steep/type_inference/block_params.rbs +120 -18
  119. data/sig/steep/type_inference/context.rbs +45 -20
  120. data/sig/steep/type_inference/context_array.rbs +37 -0
  121. data/sig/steep/type_inference/logic_type_interpreter.rbs +3 -1
  122. data/sig/steep/type_inference/method_params.rbs +13 -9
  123. data/sig/steep/type_inference/send_args.rbs +229 -0
  124. data/sig/steep/type_inference/type_env_builder.rbs +1 -1
  125. data/sig/steep/typing.rbs +4 -4
  126. data/sig/steep.rbs +4 -2
  127. data/smoke/block/e.rb +12 -0
  128. data/smoke/block/e.rbs +4 -0
  129. data/smoke/block/test_expectations.yml +12 -0
  130. data/smoke/regression/block_param_split.rb +7 -0
  131. data/smoke/regression/block_param_split.rbs +3 -0
  132. data/smoke/regression/empty_yield.rb +5 -0
  133. data/smoke/regression/empty_yield.rbs +3 -0
  134. data/smoke/regression/test_expectations.yml +12 -0
  135. data/smoke/yield/test_expectations.yml +4 -4
  136. data/steep.gemspec +2 -1
  137. metadata +61 -9
  138. data/lib/steep/interface/interface.rb +0 -34
  139. data/sig/steep/interface/interface.rbs +0 -23
  140. data/sig/version.rbs +0 -3
@@ -8,6 +8,10 @@ module Steep
8
8
  @location = location
9
9
  end
10
10
 
11
+ def self.instance
12
+ @instance ||= new()
13
+ end
14
+
11
15
  def ==(other)
12
16
  other.is_a?(Instance)
13
17
  end
@@ -38,7 +38,7 @@ module Steep
38
38
  end
39
39
 
40
40
  def with_location(new_location)
41
- self.class.new(location: new_location)
41
+ _ = self.class.new(value: value, location: new_location)
42
42
  end
43
43
 
44
44
  def back_type
@@ -4,20 +4,22 @@ module Steep
4
4
  class Proc
5
5
  attr_reader :location
6
6
  attr_reader :type
7
+ attr_reader :self_type
7
8
  attr_reader :block
8
9
 
9
- def initialize(type:, block:, location: type.location)
10
+ def initialize(type:, block:, self_type:, location: type.location)
10
11
  @type = type
11
12
  @block = block
13
+ @self_type = self_type
12
14
  @location = location
13
15
  end
14
16
 
15
17
  def ==(other)
16
- other.is_a?(self.class) && other.type == type && other.block == block
18
+ other.is_a?(self.class) && other.type == type && other.block == block && other.self_type == self_type
17
19
  end
18
20
 
19
21
  def hash
20
- self.class.hash ^ type.hash ^ block.hash
22
+ self.class.hash ^ type.hash ^ block.hash ^ self_type.hash
21
23
  end
22
24
 
23
25
  alias eql? ==
@@ -26,15 +28,21 @@ module Steep
26
28
  self.class.new(
27
29
  type: type.subst(s),
28
30
  block: block&.subst(s),
31
+ self_type: self_type&.subst(s),
29
32
  location: location
30
33
  )
31
34
  end
32
35
 
33
36
  def to_s
37
+ s =
38
+ if self_type
39
+ "[self: #{self_type}] "
40
+ end
41
+
34
42
  if block
35
- "^#{type.params} #{block} -> #{type.return_type}"
43
+ "^#{type.params} #{s}#{block} -> #{type.return_type}"
36
44
  else
37
- "^#{type.params} -> #{type.return_type}"
45
+ "^#{type.params} #{s}-> #{type.return_type}"
38
46
  end
39
47
  end
40
48
 
@@ -42,6 +50,7 @@ module Steep
42
50
  @fvs ||= Set[].tap do |fvs|
43
51
  fvs.merge(type.free_variables)
44
52
  fvs.merge(block.free_variables) if block
53
+ fvs.merge(self_type.free_variables) if self_type
45
54
  end
46
55
  end
47
56
 
@@ -53,21 +62,25 @@ module Steep
53
62
  children.push(*block.type.params.each_type.to_a)
54
63
  children.push(block.type.return_type)
55
64
  end
65
+ if self_type
66
+ children.push(self_type)
67
+ end
56
68
  [0] + level_of_children(children)
57
69
  end
58
70
 
59
71
  def closed?
60
- type.closed? && (block.nil? || block.closed?)
72
+ type.closed? && (block.nil? || block.closed?) && (self_type ? self_type.closed? : false)
61
73
  end
62
74
 
63
75
  def with_location(new_location)
64
- self.class.new(location: new_location, block: block, type: type)
76
+ self.class.new(location: new_location, block: block, type: type, self_type: self_type)
65
77
  end
66
78
 
67
79
  def map_type(&block)
68
80
  self.class.new(
69
81
  type: type.map_type(&block),
70
82
  block: self.block&.map_type(&block),
83
+ self_type: self_type ? yield(self_type) : nil,
71
84
  location: location
72
85
  )
73
86
  end
@@ -94,9 +107,10 @@ module Steep
94
107
  end
95
108
 
96
109
  def each_child(&block)
97
- if block_given?
110
+ if block
98
111
  type.each_child(&block)
99
112
  self.block&.type&.each_child(&block)
113
+ self_type.each_child(&block) if self_type
100
114
  else
101
115
  enum_for :each_child
102
116
  end
@@ -8,6 +8,10 @@ module Steep
8
8
  @location = location
9
9
  end
10
10
 
11
+ def self.instance
12
+ @instance ||= new()
13
+ end
14
+
11
15
  def ==(other)
12
16
  other.is_a?(Self)
13
17
  end
@@ -49,7 +49,7 @@ module Steep
49
49
  end
50
50
 
51
51
  def hash
52
- @hash ||= self.class.hash ^ types.sort_by(&:to_s).hash
52
+ @hash ||= types.inject(self.class.hash) {|c, type| type.hash ^ c }
53
53
  end
54
54
 
55
55
  alias eql? ==
data/lib/steep/cli.rb CHANGED
@@ -18,7 +18,7 @@ module Steep
18
18
  end
19
19
 
20
20
  def self.available_commands
21
- [:init, :check, :validate, :annotations, :version, :project, :watch, :langserver, :stats, :binstub]
21
+ [:init, :check, :validate, :annotations, :version, :project, :watch, :langserver, :stats, :binstub, :checkfile]
22
22
  end
23
23
 
24
24
  def process_global_options
@@ -123,6 +123,29 @@ module Steep
123
123
  end.run
124
124
  end
125
125
 
126
+ def process_checkfile
127
+ Drivers::Checkfile.new(stdout: stdout, stderr: stderr).tap do |check|
128
+ OptionParser.new do |opts|
129
+ opts.banner = "Usage: steep checkfile [options] [files]"
130
+
131
+ opts.on("--steepfile=PATH") {|path| check.steepfile = Pathname(path) }
132
+ opts.on("--all-rbs", "Type check all RBS files") { check.all_rbs = true }
133
+ opts.on("--all-ruby", "Type check all Ruby files") { check.all_ruby = true }
134
+ opts.on("--stdin", "Read files to type check from stdin") do
135
+ while line = stdin.gets()
136
+ object = JSON.parse(line, symbolize_names: true)
137
+ Steep.logger.info { "Loading content of `#{object[:path]}` from stdin: #{object[:content].lines[0].chomp}" }
138
+ check.stdin_input[Pathname(object[:path])] = object[:content]
139
+ end
140
+ end
141
+ handle_jobs_option check, opts
142
+ handle_logging_options opts
143
+ end.parse!(argv)
144
+
145
+ check.command_line_args.push *argv
146
+ end.run
147
+ end
148
+
126
149
  def process_stats
127
150
  Drivers::Stats.new(stdout: stdout, stderr: stderr).tap do |check|
128
151
  OptionParser.new do |opts|
@@ -87,13 +87,11 @@ module Steep
87
87
 
88
88
  class UnexpectedPositionalArgument < Base
89
89
  attr_reader :node
90
- attr_reader :method_type
91
- attr_reader :method_name
90
+ attr_reader :params
92
91
 
93
- def initialize(node:, method_name:, method_type:)
92
+ def initialize(node:, params:)
94
93
  super(node: node)
95
- @method_name = method_name
96
- @method_type = method_type
94
+ @params = params
97
95
  end
98
96
 
99
97
  def header_line
@@ -103,10 +101,9 @@ module Steep
103
101
 
104
102
  class InsufficientPositionalArguments < Base
105
103
  attr_reader :node
106
- attr_reader :method_name
107
- attr_reader :method_type
104
+ attr_reader :params
108
105
 
109
- def initialize(node:, method_name:, method_type:)
106
+ def initialize(node:, params:)
110
107
  send = case node.type
111
108
  when :send, :csend
112
109
  node
@@ -121,8 +118,7 @@ module Steep
121
118
  end
122
119
 
123
120
  super(node: node, location: loc)
124
- @method_name = method_name
125
- @method_type = method_type
121
+ @params = params
126
122
  end
127
123
 
128
124
  def header_line
@@ -132,10 +128,9 @@ module Steep
132
128
 
133
129
  class UnexpectedKeywordArgument < Base
134
130
  attr_reader :node
135
- attr_reader :method_name
136
- attr_reader :method_type
131
+ attr_reader :params
137
132
 
138
- def initialize(node:, method_name:, method_type:)
133
+ def initialize(node:, params:)
139
134
  loc = case node.type
140
135
  when :pair
141
136
  node.children[0].location.expression
@@ -145,8 +140,7 @@ module Steep
145
140
  raise
146
141
  end
147
142
  super(node: node, location: loc)
148
- @method_name = method_name
149
- @method_type = method_type
143
+ @params = params
150
144
  end
151
145
 
152
146
  def header_line
@@ -160,7 +154,7 @@ module Steep
160
154
  attr_reader :method_type
161
155
  attr_reader :missing_keywords
162
156
 
163
- def initialize(node:, method_name:, method_type:, missing_keywords:)
157
+ def initialize(node:, params:, missing_keywords:)
164
158
  send = case node.type
165
159
  when :send, :csend
166
160
  node
@@ -176,8 +170,7 @@ module Steep
176
170
 
177
171
  super(node: node, location: loc)
178
172
 
179
- @method_name = method_name
180
- @method_type = method_type
173
+ @params = params
181
174
  @missing_keywords = missing_keywords
182
175
  end
183
176
 
@@ -220,14 +213,12 @@ module Steep
220
213
  attr_reader :node
221
214
  attr_reader :expected
222
215
  attr_reader :actual
223
- attr_reader :receiver_type
224
216
  attr_reader :result
225
217
 
226
218
  include ResultPrinter
227
219
 
228
- def initialize(node:, receiver_type:, expected:, actual:, result:)
220
+ def initialize(node:, expected:, actual:, result:)
229
221
  super(node: node)
230
- @receiver_type = receiver_type
231
222
  @expected = expected
232
223
  @actual = actual
233
224
  @result = result
@@ -512,7 +503,11 @@ module Steep
512
503
  end
513
504
 
514
505
  def header_line
515
- "No superclass method `#{method}` defined"
506
+ if method
507
+ "No superclass method `#{method}` defined"
508
+ else
509
+ "`super` is not allowed from outside of method"
510
+ end
516
511
  end
517
512
  end
518
513
 
@@ -0,0 +1,205 @@
1
+ module Steep
2
+ module Drivers
3
+ class Checkfile
4
+ LSP = LanguageServer::Protocol
5
+
6
+ attr_reader :stdout
7
+ attr_reader :stderr
8
+ attr_reader :command_line_args
9
+ attr_accessor :all_ruby, :all_rbs
10
+ attr_reader :stdin_input
11
+
12
+ include Utils::DriverHelper
13
+ include Utils::JobsCount
14
+
15
+ def initialize(stdout:, stderr:)
16
+ @stdout = stdout
17
+ @stderr = stderr
18
+ @command_line_args = []
19
+
20
+ @all_rbs = false
21
+ @all_ruby = false
22
+ @stdin_input = {}
23
+ end
24
+
25
+ def run
26
+ return 0 if command_line_args.empty? && !all_rbs && !all_ruby && stdin_input.empty?
27
+
28
+ project = load_config()
29
+
30
+ client_read, server_write = IO.pipe
31
+ server_read, client_write = IO.pipe
32
+
33
+ client_reader = LanguageServer::Protocol::Transport::Io::Reader.new(client_read)
34
+ client_writer = LanguageServer::Protocol::Transport::Io::Writer.new(client_write)
35
+
36
+ server_reader = LanguageServer::Protocol::Transport::Io::Reader.new(server_read)
37
+ server_writer = LanguageServer::Protocol::Transport::Io::Writer.new(server_write)
38
+
39
+ # @type var target_paths: Set[Pathname]
40
+ target_paths = Set[]
41
+ # @type var signature_paths: Set[Pathname]
42
+ signature_paths = Set[]
43
+
44
+ loader = Services::FileLoader.new(base_dir: project.base_dir)
45
+ project.targets.each do |target|
46
+ ruby_patterns =
47
+ case
48
+ when all_ruby
49
+ []
50
+ when command_line_args.empty?
51
+ nil
52
+ else
53
+ command_line_args
54
+ end
55
+
56
+ if ruby_patterns
57
+ loader.each_path_in_patterns(target.source_pattern, ruby_patterns) do |path|
58
+ target_paths << path
59
+ end
60
+ end
61
+
62
+ rbs_patterns =
63
+ case
64
+ when all_rbs
65
+ []
66
+ when command_line_args.empty?
67
+ nil
68
+ else
69
+ command_line_args
70
+ end
71
+
72
+ if rbs_patterns
73
+ loader.each_path_in_patterns(target.signature_pattern, rbs_patterns) do |path|
74
+ signature_paths << path
75
+ end
76
+ end
77
+ end
78
+
79
+ stdin_input.each_key do |path|
80
+ case ts = project.targets_for_path(path)
81
+ when Array
82
+ signature_paths << path
83
+ when Project::Target
84
+ target_paths << path
85
+ end
86
+ end
87
+
88
+ files = target_paths + signature_paths
89
+
90
+ count =
91
+ if files.size >= jobs_count
92
+ jobs_count
93
+ else
94
+ files.size + 2
95
+ end
96
+
97
+ Steep.logger.info { "Starting #{count} workers for #{files.size} files..." }
98
+
99
+ typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(
100
+ steepfile: project.steepfile_path,
101
+ args: [],
102
+ delay_shutdown: true,
103
+ steep_command: steep_command,
104
+ count: count
105
+ )
106
+
107
+ master = Server::Master.new(
108
+ project: project,
109
+ reader: server_reader,
110
+ writer: server_writer,
111
+ interaction_worker: nil,
112
+ typecheck_workers: typecheck_workers
113
+ )
114
+ master.typecheck_automatically = false
115
+
116
+ main_thread = Thread.start do
117
+ master.start()
118
+ end
119
+ main_thread.abort_on_exception = true
120
+
121
+ Steep.logger.info { "Initializing server" }
122
+ initialize_id = request_id()
123
+ client_writer.write({ method: :initialize, id: initialize_id, params: {} })
124
+ wait_for_response_id(reader: client_reader, id: initialize_id)
125
+
126
+ stdin_input.each do |path, content|
127
+ uri = PathHelper.to_uri(project.absolute_path(path))
128
+
129
+ master.broadcast_notification(
130
+ {
131
+ method: "textDocument/didChange",
132
+ params: {
133
+ textDocument: { uri: uri, version: 0 },
134
+ contentChanges: [{ text: content }]
135
+ }
136
+ }
137
+ )
138
+ master.broadcast_notification(
139
+ {
140
+ method: "textDocument/didSave",
141
+ params: {
142
+ textDocument: { uri: uri }
143
+ }
144
+ }
145
+ )
146
+ end
147
+
148
+ ping_guid = master.fresh_request_id()
149
+ client_writer.write({ method: "$/ping", id: ping_guid, params: {} })
150
+ wait_for_response_id(reader: client_reader, id: ping_guid)
151
+
152
+ request_guid = master.fresh_request_id()
153
+ request = Server::Master::TypeCheckRequest.new(guid: request_guid)
154
+
155
+ target_paths.each do |path|
156
+ request.code_paths << project.absolute_path(path)
157
+ end
158
+ signature_paths.each do |path|
159
+ request.signature_paths << project.absolute_path(path)
160
+ end
161
+
162
+ master.start_type_check(request, last_request: nil, start_progress: true)
163
+
164
+ Steep.logger.info { "Starting type checking: #{request_guid}" }
165
+
166
+ diagnostic_notifications = []
167
+ error_messages = []
168
+ client_reader.read do |response|
169
+ case
170
+ when response[:method] == "textDocument/publishDiagnostics"
171
+ params = response[:params]
172
+
173
+ if path = PathHelper.to_pathname(params[:uri])
174
+ stdout.puts(
175
+ {
176
+ path: project.relative_path(path).to_s,
177
+ diagnostics: params[:diagnostics]
178
+ }.to_json
179
+ )
180
+ end
181
+ when response[:method] == "window/showMessage"
182
+ # Assuming ERROR message means unrecoverable error.
183
+ message = response[:params]
184
+ if message[:type] == LSP::Constant::MessageType::ERROR
185
+ error_messages << message[:message]
186
+ end
187
+ when response[:method] == "$/progress"
188
+ if response[:params][:token] == request_guid
189
+ if response[:params][:value][:kind] == "end"
190
+ break
191
+ end
192
+ end
193
+ end
194
+ end
195
+
196
+ Steep.logger.info { "Shutting down..." }
197
+
198
+ shutdown_exit(reader: client_reader, writer: client_writer)
199
+ main_thread.join()
200
+
201
+ 0
202
+ end
203
+ end
204
+ end
205
+ end
@@ -29,7 +29,9 @@ module Steep
29
29
  when Services::SignatureService::SyntaxErrorStatus, Services::SignatureService::AncestorErrorStatus
30
30
  controller.status.diagnostics
31
31
  when Services::SignatureService::LoadedStatus
32
- check = Subtyping::Check.new(factory: AST::Types::Factory.new(builder: controller.latest_builder))
32
+ factory = AST::Types::Factory.new(builder: controller.latest_builder)
33
+ builder = Interface::Builder.new(factory)
34
+ check = Subtyping::Check.new(builder: builder)
33
35
  Signature::Validator.new(checker: check).tap {|v| v.validate() }.each_error.to_a
34
36
  end
35
37
  end
@@ -5,6 +5,8 @@ module Steep
5
5
  instance_variables.all? do |name|
6
6
  other.instance_variable_get(name) == instance_variable_get(name)
7
7
  end
8
+ else
9
+ false
8
10
  end
9
11
  end
10
12
 
@@ -3,10 +3,12 @@ module Steep
3
3
  class Block
4
4
  attr_reader :type
5
5
  attr_reader :optional
6
+ attr_reader :self_type
6
7
 
7
- def initialize(type:, optional:)
8
+ def initialize(type:, optional:, self_type:)
8
9
  @type = type
9
10
  @optional = optional
11
+ @self_type = self_type
10
12
  end
11
13
 
12
14
  def optional?
@@ -20,18 +22,19 @@ module Steep
20
22
  def to_optional
21
23
  self.class.new(
22
24
  type: type,
25
+ self_type: self_type,
23
26
  optional: true
24
27
  )
25
28
  end
26
29
 
27
30
  def ==(other)
28
- other.is_a?(self.class) && other.type == type && other.optional == optional
31
+ other.is_a?(self.class) && other.type == type && other.optional == optional && other.self_type == self_type
29
32
  end
30
33
 
31
34
  alias eql? ==
32
35
 
33
36
  def hash
34
- type.hash ^ optional.hash
37
+ type.hash ^ optional.hash ^ self_type.hash
35
38
  end
36
39
 
37
40
  def closed?
@@ -40,27 +43,28 @@ module Steep
40
43
 
41
44
  def subst(s)
42
45
  ty = type.subst(s)
43
- if ty == type
46
+ st = self_type.subst(s) if self_type
47
+
48
+ if ty == type && st == self_type
44
49
  self
45
50
  else
46
- self.class.new(
47
- type: ty,
48
- optional: optional
49
- )
51
+ self.class.new(type: ty, self_type: st, optional: optional)
50
52
  end
51
53
  end
52
54
 
53
55
  def free_variables()
54
- @fvs ||= type.free_variables
56
+ @fvs ||= type.free_variables + (self_type&.free_variables || Set[])
55
57
  end
56
58
 
57
59
  def to_s
58
- "#{optional? ? "?" : ""}{ #{type.params} -> #{type.return_type} }"
60
+ self_binding = self_type ? "[self: #{self_type}] " : ""
61
+ "#{optional? ? "?" : ""}{ #{type.params} #{self_binding}-> #{type.return_type} }"
59
62
  end
60
63
 
61
64
  def map_type(&block)
62
65
  self.class.new(
63
66
  type: type.map_type(&block),
67
+ self_type: self_type&.map_type(&block),
64
68
  optional: optional
65
69
  )
66
70
  end
@@ -73,9 +77,15 @@ module Steep
73
77
  location: nil
74
78
  )
75
79
 
80
+ self_types = [self.self_type, other.self_type].compact
81
+
76
82
  self.class.new(
77
83
  type: type,
78
- optional: optional
84
+ optional: optional,
85
+ self_type:
86
+ unless self_types.empty?
87
+ AST::Types::Union.build(types: self_types)
88
+ end
79
89
  )
80
90
  end
81
91
  end