steep 1.8.0.dev.1 → 1.8.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/README.md +3 -2
  4. data/bin/mem_graph.rb +67 -0
  5. data/bin/mem_prof.rb +102 -0
  6. data/bin/stackprof_test.rb +19 -0
  7. data/bin/steep-check.rb +251 -0
  8. data/guides/src/gem-rbs-collection/gem-rbs-collection.md +1 -1
  9. data/lib/steep/annotation_parser.rb +1 -1
  10. data/lib/steep/ast/builtin.rb +5 -5
  11. data/lib/steep/ast/node/type_application.rb +7 -6
  12. data/lib/steep/ast/types/any.rb +1 -9
  13. data/lib/steep/ast/types/boolean.rb +8 -16
  14. data/lib/steep/ast/types/bot.rb +2 -10
  15. data/lib/steep/ast/types/class.rb +1 -13
  16. data/lib/steep/ast/types/factory.rb +101 -85
  17. data/lib/steep/ast/types/instance.rb +1 -13
  18. data/lib/steep/ast/types/intersection.rb +8 -15
  19. data/lib/steep/ast/types/literal.rb +2 -8
  20. data/lib/steep/ast/types/logic.rb +3 -24
  21. data/lib/steep/ast/types/name.rb +5 -16
  22. data/lib/steep/ast/types/nil.rb +3 -12
  23. data/lib/steep/ast/types/proc.rb +4 -13
  24. data/lib/steep/ast/types/record.rb +21 -12
  25. data/lib/steep/ast/types/self.rb +1 -13
  26. data/lib/steep/ast/types/shared_instance.rb +11 -0
  27. data/lib/steep/ast/types/top.rb +1 -9
  28. data/lib/steep/ast/types/tuple.rb +4 -10
  29. data/lib/steep/ast/types/union.rb +10 -15
  30. data/lib/steep/ast/types/var.rb +4 -13
  31. data/lib/steep/ast/types/void.rb +2 -10
  32. data/lib/steep/diagnostic/ruby.rb +10 -10
  33. data/lib/steep/drivers/check.rb +11 -14
  34. data/lib/steep/drivers/checkfile.rb +8 -10
  35. data/lib/steep/drivers/stats.rb +17 -13
  36. data/lib/steep/drivers/utils/driver_helper.rb +24 -3
  37. data/lib/steep/drivers/watch.rb +3 -3
  38. data/lib/steep/interface/builder.rb +162 -138
  39. data/lib/steep/interface/method_type.rb +12 -20
  40. data/lib/steep/interface/shape.rb +66 -10
  41. data/lib/steep/interface/substitution.rb +2 -0
  42. data/lib/steep/interface/type_param.rb +20 -7
  43. data/lib/steep/located_value.rb +20 -0
  44. data/lib/steep/server/change_buffer.rb +5 -7
  45. data/lib/steep/server/custom_methods.rb +61 -0
  46. data/lib/steep/server/delay_queue.rb +8 -1
  47. data/lib/steep/server/interaction_worker.rb +13 -6
  48. data/lib/steep/server/lsp_formatter.rb +8 -6
  49. data/lib/steep/server/master.rb +195 -142
  50. data/lib/steep/server/type_check_worker.rb +25 -22
  51. data/lib/steep/server/work_done_progress.rb +64 -0
  52. data/lib/steep/server/worker_process.rb +1 -1
  53. data/lib/steep/services/completion_provider.rb +32 -24
  54. data/lib/steep/services/goto_service.rb +3 -2
  55. data/lib/steep/services/hover_provider/ruby.rb +30 -17
  56. data/lib/steep/services/signature_help_provider.rb +9 -7
  57. data/lib/steep/services/signature_service.rb +1 -1
  58. data/lib/steep/services/type_check_service.rb +19 -9
  59. data/lib/steep/signature/validator.rb +17 -20
  60. data/lib/steep/source.rb +47 -1
  61. data/lib/steep/subtyping/check.rb +105 -55
  62. data/lib/steep/subtyping/constraints.rb +13 -17
  63. data/lib/steep/type_construction.rb +106 -100
  64. data/lib/steep/type_inference/block_params.rb +8 -5
  65. data/lib/steep/type_inference/logic_type_interpreter.rb +11 -7
  66. data/lib/steep/type_inference/method_call.rb +3 -3
  67. data/lib/steep/type_inference/method_params.rb +1 -1
  68. data/lib/steep/type_inference/send_args.rb +1 -1
  69. data/lib/steep/typing.rb +164 -106
  70. data/lib/steep/version.rb +1 -1
  71. data/lib/steep.rb +29 -4
  72. data/steep.gemspec +2 -2
  73. metadata +16 -9
  74. data/lib/steep/type_inference/context_array.rb +0 -112
@@ -2,16 +2,14 @@ module Steep
2
2
  module AST
3
3
  module Types
4
4
  class Proc
5
- attr_reader :location
6
5
  attr_reader :type
7
6
  attr_reader :self_type
8
7
  attr_reader :block
9
8
 
10
- def initialize(type:, block:, self_type:, location: type.location)
9
+ def initialize(type:, block:, self_type:)
11
10
  @type = type
12
11
  @block = block
13
12
  @self_type = self_type
14
- @location = location
15
13
  end
16
14
 
17
15
  def ==(other)
@@ -28,8 +26,7 @@ module Steep
28
26
  self.class.new(
29
27
  type: type.subst(s),
30
28
  block: block&.subst(s),
31
- self_type: self_type&.subst(s),
32
- location: location
29
+ self_type: self_type&.subst(s)
33
30
  )
34
31
  end
35
32
 
@@ -70,16 +67,11 @@ module Steep
70
67
  [0] + level_of_children(children)
71
68
  end
72
69
 
73
- def with_location(new_location)
74
- self.class.new(location: new_location, block: block, type: type, self_type: self_type)
75
- end
76
-
77
70
  def map_type(&block)
78
71
  self.class.new(
79
72
  type: type.map_type(&block),
80
73
  block: self.block&.map_type(&block),
81
- self_type: self_type ? yield(self_type) : nil,
82
- location: location
74
+ self_type: self_type ? yield(self_type) : nil
83
75
  )
84
76
  end
85
77
 
@@ -99,8 +91,7 @@ module Steep
99
91
 
100
92
  def back_type
101
93
  Name::Instance.new(name: Builtin::Proc.module_name,
102
- args: [],
103
- location: location)
94
+ args: [])
104
95
  end
105
96
 
106
97
  def block_required?
@@ -2,32 +2,37 @@ module Steep
2
2
  module AST
3
3
  module Types
4
4
  class Record
5
- attr_reader :location
6
- attr_reader :elements
5
+ attr_reader :elements, :required_keys
7
6
 
8
- def initialize(elements:, location: nil)
7
+ def initialize(elements:, required_keys:)
9
8
  @elements = elements
10
- @location = location
9
+ @required_keys = required_keys
11
10
  end
12
11
 
13
12
  def ==(other)
14
- other.is_a?(Record) && other.elements == elements
13
+ other.is_a?(Record) && other.elements == elements && other.required_keys == required_keys
15
14
  end
16
15
 
17
16
  def hash
18
- self.class.hash ^ elements.hash
17
+ self.class.hash ^ elements.hash ^ required_keys.hash
19
18
  end
20
19
 
21
20
  alias eql? ==
22
21
 
23
22
  def subst(s)
24
- self.class.new(location: location,
25
- elements: elements.transform_values {|type| type.subst(s) })
23
+ self.class.new(
24
+ elements: elements.transform_values {|type| type.subst(s) },
25
+ required_keys: required_keys
26
+ )
26
27
  end
27
28
 
28
29
  def to_s
29
30
  strings = elements.keys.sort.map do |key|
30
- "#{key.inspect} => #{elements[key]}"
31
+ if optional?(key)
32
+ "?#{key.inspect} => #{elements[key]}"
33
+ else
34
+ "#{key.inspect} => #{elements[key]}"
35
+ end
31
36
  end
32
37
  "{ #{strings.join(", ")} }"
33
38
  end
@@ -53,7 +58,7 @@ module Steep
53
58
  def map_type(&block)
54
59
  self.class.new(
55
60
  elements: elements.transform_values(&block),
56
- location: location
61
+ required_keys: required_keys
57
62
  )
58
63
  end
59
64
 
@@ -61,8 +66,12 @@ module Steep
61
66
  [0] + level_of_children(elements.values)
62
67
  end
63
68
 
64
- def with_location(new_location)
65
- self.class.new(elements: elements, location: new_location)
69
+ def required?(key)
70
+ required_keys.include?(key)
71
+ end
72
+
73
+ def optional?(key)
74
+ !required_keys.include?(key)
66
75
  end
67
76
  end
68
77
  end
@@ -2,15 +2,7 @@ module Steep
2
2
  module AST
3
3
  module Types
4
4
  class Self
5
- attr_reader :location
6
-
7
- def initialize(location: nil)
8
- @location = location
9
- end
10
-
11
- def self.instance
12
- @instance ||= new()
13
- end
5
+ extend SharedInstance
14
6
 
15
7
  def ==(other)
16
8
  other.is_a?(Self)
@@ -45,10 +37,6 @@ module Steep
45
37
  def level
46
38
  [0]
47
39
  end
48
-
49
- def with_location(new_location)
50
- self.class.new(location: new_location)
51
- end
52
40
  end
53
41
  end
54
42
  end
@@ -0,0 +1,11 @@
1
+ module Steep
2
+ module AST
3
+ module Types
4
+ module SharedInstance
5
+ def instance
6
+ @instance ||= new
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -2,11 +2,7 @@ module Steep
2
2
  module AST
3
3
  module Types
4
4
  class Top
5
- attr_reader :location
6
-
7
- def initialize(location: nil)
8
- @location = location
9
- end
5
+ extend SharedInstance
10
6
 
11
7
  def ==(other)
12
8
  other.is_a?(Top)
@@ -33,10 +29,6 @@ module Steep
33
29
  def level
34
30
  [2]
35
31
  end
36
-
37
- def with_location(new_location)
38
- self.class.new(location: new_location)
39
- end
40
32
  end
41
33
  end
42
34
  end
@@ -3,11 +3,9 @@ module Steep
3
3
  module Types
4
4
  class Tuple
5
5
  attr_reader :types
6
- attr_reader :location
7
6
 
8
- def initialize(types:, location: nil)
7
+ def initialize(types:)
9
8
  @types = types
10
- @location = location
11
9
  end
12
10
 
13
11
  def ==(other)
@@ -22,8 +20,7 @@ module Steep
22
20
  alias eql? ==
23
21
 
24
22
  def subst(s)
25
- self.class.new(location: location,
26
- types: types.map {|ty| ty.subst(s) })
23
+ self.class.new(types: types.map {|ty| ty.subst(s) })
27
24
  end
28
25
 
29
26
  def to_s
@@ -47,10 +44,7 @@ module Steep
47
44
  end
48
45
 
49
46
  def map_type(&block)
50
- Tuple.new(
51
- types: types.map(&block),
52
- location: location
53
- )
47
+ Tuple.new(types: types.map(&block))
54
48
  end
55
49
 
56
50
  def level
@@ -58,7 +52,7 @@ module Steep
58
52
  end
59
53
 
60
54
  def with_location(new_location)
61
- self.class.new(types: types, location: new_location)
55
+ self.class.new(types: types)
62
56
  end
63
57
  end
64
58
  end
@@ -3,15 +3,13 @@ module Steep
3
3
  module Types
4
4
  class Union
5
5
  attr_reader :types
6
- attr_reader :location
7
6
 
8
- def initialize(types:, location: nil)
7
+ def initialize(types:)
9
8
  @types = types
10
- @location = location
11
9
  end
12
10
 
13
- def self.build(types:, location: nil)
14
- return AST::Types::Bot.new if types.empty?
11
+ def self.build(types:)
12
+ return AST::Types::Bot.instance if types.empty?
15
13
  if types.size == 1
16
14
  return types.first || raise
17
15
  end
@@ -25,9 +23,9 @@ module Steep
25
23
  end.map do |type|
26
24
  case type
27
25
  when AST::Types::Any
28
- return AST::Types::Any.new(location: location)
26
+ return AST::Types::Any.instance()
29
27
  when AST::Types::Top
30
- return AST::Types::Top.new(location: location)
28
+ return AST::Types::Top.instance
31
29
  when AST::Types::Bot
32
30
  nil
33
31
  else
@@ -36,11 +34,11 @@ module Steep
36
34
  end.compact.uniq.yield_self do |tys|
37
35
  case tys.size
38
36
  when 0
39
- AST::Types::Bot.new
37
+ AST::Types::Bot.instance
40
38
  when 1
41
39
  tys.first || raise
42
40
  else
43
- new(types: tys, location: location)
41
+ new(types: tys)
44
42
  end
45
43
  end
46
44
  end
@@ -57,7 +55,7 @@ module Steep
57
55
  alias eql? ==
58
56
 
59
57
  def subst(s)
60
- self.class.build(location: location, types: types.map {|ty| ty.subst(s) })
58
+ self.class.build(types: types.map {|ty| ty.subst(s) })
61
59
  end
62
60
 
63
61
  def to_s
@@ -81,10 +79,7 @@ module Steep
81
79
  end
82
80
 
83
81
  def map_type(&block)
84
- Union.build(
85
- types: types.map(&block),
86
- location: location
87
- )
82
+ Union.build(types: types.map(&block))
88
83
  end
89
84
 
90
85
  include Helper::ChildrenLevel
@@ -94,7 +89,7 @@ module Steep
94
89
  end
95
90
 
96
91
  def with_location(new_location)
97
- self.class.new(types: types, location: new_location)
92
+ self.class.new(types: types)
98
93
  end
99
94
  end
100
95
  end
@@ -3,11 +3,9 @@ module Steep
3
3
  module Types
4
4
  class Var
5
5
  attr_reader :name
6
- attr_reader :location
7
6
 
8
- def initialize(name:, location: nil)
7
+ def initialize(name:)
9
8
  @name = name
10
- @location = location
11
9
  end
12
10
 
13
11
  def ==(other)
@@ -33,7 +31,7 @@ module Steep
33
31
  end
34
32
 
35
33
  def self.fresh(name, location: nil)
36
- new(name: fresh_name(name), location: location)
34
+ new(name: fresh_name(name))
37
35
  end
38
36
 
39
37
  def to_s
@@ -58,15 +56,8 @@ module Steep
58
56
  [0]
59
57
  end
60
58
 
61
- def update(name: self.name, location: self.location)
62
- self.class.new(
63
- name: name,
64
- location: location
65
- )
66
- end
67
-
68
- def with_location(new_location)
69
- update(location: new_location)
59
+ def update(name: self.name)
60
+ self.class.new(name: name)
70
61
  end
71
62
  end
72
63
  end
@@ -2,12 +2,8 @@ module Steep
2
2
  module AST
3
3
  module Types
4
4
  class Void
5
- attr_reader :location
6
-
7
- def initialize(location: nil)
8
- @location = location
9
- end
10
-
5
+ extend SharedInstance
6
+
11
7
  def ==(other)
12
8
  other.is_a?(Void)
13
9
  end
@@ -33,10 +29,6 @@ module Steep
33
29
  def level
34
30
  [0]
35
31
  end
36
-
37
- def with_location(new_location)
38
- self.class.new(location: new_location)
39
- end
40
32
  end
41
33
  end
42
34
  end
@@ -162,7 +162,7 @@ module Steep
162
162
  end
163
163
 
164
164
  loc = if send
165
- send.loc.selector.with(end_pos: send.loc.expression.end_pos)
165
+ send.loc.selector.with(end_pos: send.loc.expression.end_pos) # steep:ignore NoMethod
166
166
  else
167
167
  node.loc.expression
168
168
  end
@@ -213,7 +213,7 @@ module Steep
213
213
  end
214
214
 
215
215
  loc = if send
216
- send.loc.selector.with(end_pos: send.loc.expression.end_pos)
216
+ send.loc.selector.with(end_pos: send.loc.expression.end_pos) # steep:ignore NoMethod
217
217
  else
218
218
  node.loc.expression
219
219
  end
@@ -287,8 +287,8 @@ module Steep
287
287
  loc = case node.type
288
288
  when :send
289
289
  loc = _ = nil
290
- loc ||= node.loc.operator if node.loc.respond_to?(:operator)
291
- loc ||= node.loc.selector if node.loc.respond_to?(:selector)
290
+ loc ||= node.loc.operator if node.loc.respond_to?(:operator) # steep:ignore NoMethod
291
+ loc ||= node.loc.selector if node.loc.respond_to?(:selector) # steep:ignore NoMethod
292
292
  loc
293
293
  when :block
294
294
  node.children[0].loc.selector
@@ -463,7 +463,7 @@ module Steep
463
463
  node.children[1]
464
464
  when :defs
465
465
  node.children[2]
466
- end
466
+ end #: Parser::AST::Node?
467
467
  super(node: node, location: args&.loc&.expression || node.loc.name)
468
468
  @method_type = method_type
469
469
  end
@@ -668,7 +668,7 @@ module Steep
668
668
  attr_reader :name
669
669
 
670
670
  def initialize(node:, name:)
671
- super(node: node, location: node.loc.name)
671
+ super(node: node, location: node.loc.name) # steep:ignore NoMethod
672
672
  @name = name
673
673
  end
674
674
 
@@ -904,8 +904,8 @@ module Steep
904
904
  class UnexpectedTypeArgument < Base
905
905
  attr_reader :type_arg, :method_type
906
906
 
907
- def initialize(type_arg:, method_type:)
908
- super(node: nil, location: type_arg.location)
907
+ def initialize(type_arg:, method_type:, location:)
908
+ super(node: nil, location: location)
909
909
  @type_arg = type_arg
910
910
  @method_type = method_type
911
911
  end
@@ -932,8 +932,8 @@ module Steep
932
932
  class TypeArgumentMismatchError < Base
933
933
  attr_reader :type_argument, :type_parameter, :result
934
934
 
935
- def initialize(type_arg:, type_param:, result:)
936
- super(node: nil, location: type_arg.location)
935
+ def initialize(type_arg:, type_param:, result:, location:)
936
+ super(node: nil, location: location)
937
937
  @type_argument = type_arg
938
938
  @type_parameter = type_param
939
939
  @result = result
@@ -61,42 +61,39 @@ module Steep
61
61
 
62
62
  Steep.logger.info { "Initializing server" }
63
63
  initialize_id = request_id()
64
- client_writer.write({ method: :initialize, id: initialize_id, params: {} })
64
+ client_writer.write({ method: :initialize, id: initialize_id, params: DEFAULT_CLI_LSP_INITIALIZE_PARAMS })
65
65
  wait_for_response_id(reader: client_reader, id: initialize_id)
66
66
 
67
67
  request_guid = SecureRandom.uuid
68
68
  Steep.logger.info { "Starting type checking: #{request_guid}" }
69
- client_writer.write({ method: "$/typecheck", params: { guid: request_guid } })
69
+ client_writer.write(Server::CustomMethods::TypeCheck.request(request_guid, { guid: request_guid}))
70
70
 
71
71
  diagnostic_notifications = [] #: Array[LanguageServer::Protocol::Interface::PublishDiagnosticsParams]
72
72
  error_messages = [] #: Array[String]
73
- client_reader.read do |response|
73
+
74
+ response = wait_for_response_id(reader: client_reader, id: request_guid) do |message|
74
75
  case
75
- when response[:method] == "textDocument/publishDiagnostics"
76
- ds = response[:params][:diagnostics]
76
+ when message[:method] == "textDocument/publishDiagnostics"
77
+ ds = message[:params][:diagnostics]
77
78
  ds.select! {|d| keep_diagnostic?(d, severity_level: severity_level) }
78
79
  if ds.empty?
79
80
  stdout.print "."
80
81
  else
81
82
  stdout.print "F"
82
83
  end
83
- diagnostic_notifications << response[:params]
84
+ diagnostic_notifications << message[:params]
84
85
  stdout.flush
85
- when response[:method] == "window/showMessage"
86
+ when message[:method] == "window/showMessage"
86
87
  # Assuming ERROR message means unrecoverable error.
87
- message = response[:params]
88
+ message = message[:params]
88
89
  if message[:type] == LSP::Constant::MessageType::ERROR
89
90
  error_messages << message[:message]
90
91
  end
91
- when response[:method] == "$/progress"
92
- if response[:params][:token] == request_guid
93
- if response[:params][:value][:kind] == "end"
94
- break
95
- end
96
- end
97
92
  end
98
93
  end
99
94
 
95
+ Steep.logger.info { "Finished type checking: #{response.inspect}" }
96
+
100
97
  Steep.logger.info { "Shutting down..." }
101
98
 
102
99
  shutdown_exit(reader: client_reader, writer: client_writer)
@@ -125,7 +125,7 @@ module Steep
125
125
 
126
126
  Steep.logger.info { "Initializing server" }
127
127
  initialize_id = request_id()
128
- client_writer.write({ method: :initialize, id: initialize_id, params: {} })
128
+ client_writer.write({ method: :initialize, id: initialize_id, params: DEFAULT_CLI_LSP_INITIALIZE_PARAMS })
129
129
  wait_for_response_id(reader: client_reader, id: initialize_id)
130
130
 
131
131
  stdin_input.each do |path, content|
@@ -151,11 +151,12 @@ module Steep
151
151
  end
152
152
 
153
153
  ping_guid = master.fresh_request_id()
154
- client_writer.write({ method: "$/ping", id: ping_guid, params: {} })
154
+ client_writer.write({ method: "$/ping", id: ping_guid, params: {}})
155
155
  wait_for_response_id(reader: client_reader, id: ping_guid)
156
156
 
157
157
  request_guid = master.fresh_request_id()
158
- request = Server::Master::TypeCheckRequest.new(guid: request_guid)
158
+ progress = master.work_done_progress(request_guid)
159
+ request = Server::Master::TypeCheckRequest.new(guid: request_guid, progress: progress)
159
160
 
160
161
  target_paths.each do |path|
161
162
  request.code_paths << project.absolute_path(path)
@@ -164,12 +165,13 @@ module Steep
164
165
  request.signature_paths << project.absolute_path(path)
165
166
  end
166
167
 
167
- master.start_type_check(request, last_request: nil, start_progress: true)
168
+ master.start_type_check(request: request, last_request: nil, report_progress_threshold: 0)
168
169
 
169
170
  Steep.logger.info { "Starting type checking: #{request_guid}" }
170
171
 
171
172
  error_messages = [] #: Array[String]
172
173
  client_reader.read do |response|
174
+ Steep.logger.info { response.inspect }
173
175
  case
174
176
  when response[:method] == "textDocument/publishDiagnostics"
175
177
  params = response[:params]
@@ -188,12 +190,8 @@ module Steep
188
190
  if message[:type] == LSP::Constant::MessageType::ERROR
189
191
  error_messages << message[:message]
190
192
  end
191
- when response[:method] == "$/progress"
192
- if response[:params][:token] == request_guid
193
- if response[:params][:value][:kind] == "end"
194
- break
195
- end
196
- end
193
+ when response[:id] == request_guid
194
+ break
197
195
  end
198
196
  end
199
197
 
@@ -16,6 +16,7 @@ module Steep
16
16
  csv << ["Target", "File", "Status", "Typed calls", "Untyped calls", "All calls", "Typed %"]
17
17
  stats_result.each do |row|
18
18
  if row[:type] == "success"
19
+ # @type var row: Steep::Services::StatsCalculator::SuccessStats::json
19
20
  csv << [
20
21
  row[:target],
21
22
  row[:path],
@@ -30,6 +31,7 @@ module Steep
30
31
  end
31
32
  ]
32
33
  else
34
+ # @type var row: Steep::Services::StatsCalculator::ErrorStats::json
33
35
  csv << [
34
36
  row[:target],
35
37
  row[:path],
@@ -57,7 +59,8 @@ module Steep
57
59
  rows = [] #: Array[Array[untyped]]
58
60
  stats_result.sort_by {|row| row[:path] }.each do |row|
59
61
  if row[:type] == "success"
60
- rows << [
62
+ # @type var row: Steep::Services::StatsCalculator::SuccessStats::json
63
+ rows << [
61
64
  row[:target],
62
65
  row[:path] + " ",
63
66
  row[:type],
@@ -71,6 +74,7 @@ module Steep
71
74
  end
72
75
  ]
73
76
  else
77
+ # @type var row: Steep::Services::StatsCalculator::ErrorStats::json
74
78
  rows << [
75
79
  row[:target],
76
80
  row[:path],
@@ -150,27 +154,27 @@ module Steep
150
154
  end
151
155
 
152
156
  initialize_id = request_id()
153
- client_writer.write({ method: :initialize, id: initialize_id })
157
+ client_writer.write({ method: :initialize, id: initialize_id, params: DEFAULT_CLI_LSP_INITIALIZE_PARAMS })
154
158
  wait_for_response_id(reader: client_reader, id: initialize_id)
155
159
 
156
160
  typecheck_guid = SecureRandom.uuid
157
- client_writer.write({ method: "$/typecheck", params: { guid: typecheck_guid }})
161
+
162
+ master.job_queue << -> do
163
+ Steep.logger.info { "Type checking for stats..." }
164
+ progress = master.work_done_progress(typecheck_guid)
165
+ master.start_type_check(last_request: nil, progress: progress, include_unchanged: true, report_progress_threshold: 0)
166
+ end
158
167
  wait_for_message(reader: client_reader) do |message|
159
- message[:method] == "$/progress" &&
160
- message[:params][:token] == typecheck_guid &&
161
- message[:params][:value][:kind] == "end"
168
+ message[:id] == typecheck_guid
162
169
  end
163
170
 
171
+ Steep.logger.info { "Finished type checking for stats" }
172
+
164
173
  stats_id = request_id()
165
- client_writer.write(
166
- {
167
- id: stats_id,
168
- method: "workspace/executeCommand",
169
- params: { command: "steep/stats", arguments: _ = [] }
170
- })
174
+ client_writer.write(Server::CustomMethods::Stats.request(stats_id))
171
175
 
172
176
  stats_response = wait_for_response_id(reader: client_reader, id: stats_id)
173
- stats_result = stats_response[:result]
177
+ stats_result = stats_response[:result] #: Server::CustomMethods::Stats::result
174
178
 
175
179
  shutdown_exit(reader: client_reader, writer: client_writer)
176
180
  main_thread.join()
@@ -38,9 +38,28 @@ module Steep
38
38
  SecureRandom.alphanumeric(10)
39
39
  end
40
40
 
41
- def wait_for_response_id(reader:, id:, unknown_responses: :ignore)
42
- wait_for_message(reader: reader, unknown_messages: unknown_responses) do |response|
43
- response[:id] == id
41
+ def wait_for_response_id(reader:, id:, unknown_responses: nil, &block)
42
+ reader.read do |message|
43
+ Steep.logger.debug { "Received message waiting for #{id}: #{message.inspect}" }
44
+
45
+ response_id = message[:id]
46
+
47
+ if response_id == id
48
+ return message
49
+ end
50
+
51
+ if block
52
+ yield message
53
+ else
54
+ case unknown_responses
55
+ when :ignore, nil
56
+ # nop
57
+ when :log
58
+ Steep.logger.error { "Unexpected message: #{message.inspect}" }
59
+ when :raise
60
+ raise "Unexpected message: #{message.inspect}"
61
+ end
62
+ end
44
63
  end
45
64
  end
46
65
 
@@ -83,6 +102,8 @@ module Steep
83
102
  severity <= LanguageServer::Protocol::Constant::DiagnosticSeverity::INFORMATION
84
103
  end
85
104
  end
105
+
106
+ (DEFAULT_CLI_LSP_INITIALIZE_PARAMS = {}).freeze
86
107
  end
87
108
  end
88
109
  end