ruby-lsp 0.23.1 → 0.23.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d4a7b6b44dae357ccbc6a9f6494bd892d890bebf1287aa6c989ef4f2aee14e82
4
- data.tar.gz: cbfc554b33a2cf45663ab394e4fb81e27eb2ec4309907943e3fe67d591222d63
3
+ metadata.gz: 95642b8034d20684e2596755f391591d6dfffc9021e23a6e2efd0b9a0e500eb0
4
+ data.tar.gz: 6db469fda24144ce71eb0c2d8434251b3bf01a800035d85bea5e8e6801cf5120
5
5
  SHA512:
6
- metadata.gz: bee0f714bd2f2865eeefa2de4eeb2f31bbf55d1fb106cb2a19af208bfc8c868815e2fcad86dcd58a119c9494c6a8254b01fcacdbeb02ce4379a8242ad94d2fcb
7
- data.tar.gz: 690d71bce5781f0de3ff170782d76e1d6ef34afd6801525c9ebbb92cfc64c2b9adc25b591710eaf4100c138706a8a358bfe6959d133a0da96e7cdd16279549c7
6
+ metadata.gz: 69365797e36c6597b43b5067da2e10b6c634cdb9121081db0e7c16c657fe12e2aa72042ba7beb07480b1cbb4a24c9a37a7a71f5a49a1be42923adb7a85a80715
7
+ data.tar.gz: 22695e4a4fd4e72738b43c32e9a693ed9895033e82240317700cde5583537b0ad6e7d8ce530a110624c57278d5a08c4eeb207ae010a4db99b3885bc241c5caa4
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.23.1
1
+ 0.23.3
@@ -45,6 +45,12 @@ rescue Errno::ECHILD
45
45
  # In theory, the child process can finish before we even get to the wait call, but that is not an error
46
46
  end
47
47
 
48
+ error_path = File.join(".ruby-lsp", "install_error")
49
+
50
+ install_error = if File.exist?(error_path)
51
+ Marshal.load(File.read(error_path))
52
+ end
53
+
48
54
  begin
49
55
  bundle_env_path = File.join(".ruby-lsp", "bundle_env")
50
56
  # We can't require `bundler/setup` because that file prematurely exits the process if setup fails. However, we can't
@@ -67,21 +73,21 @@ begin
67
73
  rescue StandardError => e
68
74
  # If installing gems failed for any reason, we don't want to exit the process prematurely. We can still provide most
69
75
  # features in a degraded mode. We simply save the error so that we can report to the user that certain gems might be
70
- # missing, but we respect the LSP life cycle
71
- setup_error = e
72
- $stderr.puts("Failed to set up composed Bundle\n#{e.full_message}")
76
+ # missing, but we respect the LSP life cycle.
77
+ #
78
+ # If an install error occurred and one of the gems is not installed, Bundler.setup is guaranteed to fail with
79
+ # `Bundler::GemNotFound`. We don't set `setup_error` here because that would essentially report the same problem twice
80
+ # to telemetry, which is not useful
81
+ unless install_error && e.is_a?(Bundler::GemNotFound)
82
+ setup_error = e
83
+ $stderr.puts("Failed to set up composed Bundle\n#{e.full_message}")
84
+ end
73
85
 
74
86
  # If Bundler.setup fails, we need to restore the original $LOAD_PATH so that we can still require the Ruby LSP server
75
87
  # in degraded mode
76
88
  $LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
77
89
  end
78
90
 
79
- error_path = File.join(".ruby-lsp", "install_error")
80
-
81
- install_error = if File.exist?(error_path)
82
- Marshal.load(File.read(error_path))
83
- end
84
-
85
91
  # Now that the bundle is set up, we can begin actually launching the server. Note that `Bundler.setup` will have already
86
92
  # configured the load path using the version of the Ruby LSP present in the composed bundle. Do not push any Ruby LSP
87
93
  # paths into the load path manually or we may end up requiring the wrong version of the gem
@@ -24,7 +24,7 @@ module RubyIndexer
24
24
  @index = index
25
25
  @uri = uri
26
26
  @enhancements = T.let(Enhancement.all(self), T::Array[Enhancement])
27
- @visibility_stack = T.let([Entry::Visibility::PUBLIC], T::Array[Entry::Visibility])
27
+ @visibility_stack = T.let([VisibilityScope.public_scope], T::Array[VisibilityScope])
28
28
  @comments_by_line = T.let(
29
29
  parse_result.comments.to_h do |c|
30
30
  [c.location.start_line, c]
@@ -64,7 +64,6 @@ module RubyIndexer
64
64
  :on_constant_path_or_write_node_enter,
65
65
  :on_constant_path_operator_write_node_enter,
66
66
  :on_constant_path_and_write_node_enter,
67
- :on_constant_or_write_node_enter,
68
67
  :on_constant_write_node_enter,
69
68
  :on_constant_or_write_node_enter,
70
69
  :on_constant_and_write_node_enter,
@@ -138,7 +137,7 @@ module RubyIndexer
138
137
 
139
138
  sig { params(node: Prism::SingletonClassNode).void }
140
139
  def on_singleton_class_node_enter(node)
141
- @visibility_stack.push(Entry::Visibility::PUBLIC)
140
+ @visibility_stack.push(VisibilityScope.public_scope)
142
141
 
143
142
  current_owner = @owner_stack.last
144
143
 
@@ -280,15 +279,14 @@ module RubyIndexer
280
279
  when :include, :prepend, :extend
281
280
  handle_module_operation(node, message)
282
281
  when :public
283
- @visibility_stack.push(Entry::Visibility::PUBLIC)
282
+ @visibility_stack.push(VisibilityScope.public_scope)
284
283
  when :protected
285
- @visibility_stack.push(Entry::Visibility::PROTECTED)
284
+ @visibility_stack.push(VisibilityScope.new(visibility: Entry::Visibility::PROTECTED))
286
285
  when :private
287
- @visibility_stack.push(Entry::Visibility::PRIVATE)
286
+ @visibility_stack.push(VisibilityScope.new(visibility: Entry::Visibility::PRIVATE))
288
287
  when :module_function
289
288
  handle_module_function(node)
290
289
  when :private_class_method
291
- @visibility_stack.push(Entry::Visibility::PRIVATE)
292
290
  handle_private_class_method(node)
293
291
  end
294
292
 
@@ -324,42 +322,61 @@ module RubyIndexer
324
322
 
325
323
  sig { params(node: Prism::DefNode).void }
326
324
  def on_def_node_enter(node)
325
+ owner = @owner_stack.last
326
+ return unless owner
327
+
327
328
  @inside_def = true
328
329
  method_name = node.name.to_s
329
330
  comments = collect_comments(node)
331
+ scope = current_visibility_scope
330
332
 
331
333
  case node.receiver
332
334
  when nil
335
+ location = Location.from_prism_location(node.location, @code_units_cache)
336
+ name_location = Location.from_prism_location(node.name_loc, @code_units_cache)
337
+ signatures = [Entry::Signature.new(list_params(node.parameters))]
338
+
333
339
  @index.add(Entry::Method.new(
334
340
  method_name,
335
341
  @uri,
336
- Location.from_prism_location(node.location, @code_units_cache),
337
- Location.from_prism_location(node.name_loc, @code_units_cache),
342
+ location,
343
+ name_location,
338
344
  comments,
339
- [Entry::Signature.new(list_params(node.parameters))],
340
- current_visibility,
341
- @owner_stack.last,
345
+ signatures,
346
+ scope.visibility,
347
+ owner,
342
348
  ))
343
- when Prism::SelfNode
344
- owner = @owner_stack.last
345
349
 
346
- if owner
350
+ if scope.module_func
347
351
  singleton = @index.existing_or_new_singleton_class(owner.name)
348
352
 
349
353
  @index.add(Entry::Method.new(
350
354
  method_name,
351
355
  @uri,
352
- Location.from_prism_location(node.location, @code_units_cache),
353
- Location.from_prism_location(node.name_loc, @code_units_cache),
356
+ location,
357
+ name_location,
354
358
  comments,
355
- [Entry::Signature.new(list_params(node.parameters))],
356
- current_visibility,
359
+ signatures,
360
+ Entry::Visibility::PUBLIC,
357
361
  singleton,
358
362
  ))
359
-
360
- @owner_stack << singleton
361
- @stack << "<Class:#{@stack.last}>"
362
363
  end
364
+ when Prism::SelfNode
365
+ singleton = @index.existing_or_new_singleton_class(owner.name)
366
+
367
+ @index.add(Entry::Method.new(
368
+ method_name,
369
+ @uri,
370
+ Location.from_prism_location(node.location, @code_units_cache),
371
+ Location.from_prism_location(node.name_loc, @code_units_cache),
372
+ comments,
373
+ [Entry::Signature.new(list_params(node.parameters))],
374
+ scope.visibility,
375
+ singleton,
376
+ ))
377
+
378
+ @owner_stack << singleton
379
+ @stack << "<Class:#{@stack.last}>"
363
380
  end
364
381
  end
365
382
 
@@ -834,6 +851,8 @@ module RubyIndexer
834
851
  return unless receiver.nil? || receiver.is_a?(Prism::SelfNode)
835
852
 
836
853
  comments = collect_comments(node)
854
+ scope = current_visibility_scope
855
+
837
856
  arguments.each do |argument|
838
857
  name, loc = case argument
839
858
  when Prism::SymbolNode
@@ -850,7 +869,7 @@ module RubyIndexer
850
869
  @uri,
851
870
  Location.from_prism_location(loc, @code_units_cache),
852
871
  comments,
853
- current_visibility,
872
+ scope.visibility,
854
873
  @owner_stack.last,
855
874
  ))
856
875
  end
@@ -862,7 +881,7 @@ module RubyIndexer
862
881
  @uri,
863
882
  Location.from_prism_location(loc, @code_units_cache),
864
883
  comments,
865
- current_visibility,
884
+ scope.visibility,
866
885
  @owner_stack.last,
867
886
  ))
868
887
  end
@@ -904,11 +923,20 @@ module RubyIndexer
904
923
 
905
924
  sig { params(node: Prism::CallNode).void }
906
925
  def handle_module_function(node)
926
+ # Invoking `module_function` in a class raises
927
+ owner = @owner_stack.last
928
+ return unless owner.is_a?(Entry::Module)
929
+
907
930
  arguments_node = node.arguments
908
- return unless arguments_node
909
931
 
910
- owner_name = @owner_stack.last&.name
911
- return unless owner_name
932
+ # If `module_function` is invoked without arguments, all methods defined after it become singleton methods and the
933
+ # visibility for instance methods changes to private
934
+ unless arguments_node
935
+ @visibility_stack.push(VisibilityScope.module_function_scope)
936
+ return
937
+ end
938
+
939
+ owner_name = owner.name
912
940
 
913
941
  arguments_node.arguments.each do |argument|
914
942
  method_name = case argument
@@ -946,45 +974,48 @@ module RubyIndexer
946
974
 
947
975
  sig { params(node: Prism::CallNode).void }
948
976
  def handle_private_class_method(node)
949
- node.arguments&.arguments&.each do |argument|
950
- string_or_symbol_nodes = case argument
951
- when Prism::StringNode, Prism::SymbolNode
952
- [argument]
953
- when Prism::ArrayNode
954
- argument.elements
955
- else
956
- []
957
- end
977
+ arguments = node.arguments&.arguments
978
+ return unless arguments
958
979
 
959
- unless string_or_symbol_nodes.empty?
960
- # pop the visibility off since there isn't a method definition following `private_class_method`
961
- @visibility_stack.pop
962
- end
980
+ # If we're passing a method definition directly to `private_class_method`, push a new private scope. That will be
981
+ # applied when the indexer finds the method definition and then popped on `call_node_leave`
982
+ if arguments.first.is_a?(Prism::DefNode)
983
+ @visibility_stack.push(VisibilityScope.new(visibility: Entry::Visibility::PRIVATE))
984
+ return
985
+ end
963
986
 
964
- string_or_symbol_nodes.each do |string_or_symbol_node|
965
- method_name = case string_or_symbol_node
966
- when Prism::StringNode
967
- string_or_symbol_node.content
968
- when Prism::SymbolNode
969
- string_or_symbol_node.value
970
- end
971
- next unless method_name
987
+ owner_name = @owner_stack.last&.name
988
+ return unless owner_name
972
989
 
973
- owner_name = @owner_stack.last&.name
974
- next unless owner_name
990
+ # private_class_method accepts strings, symbols or arrays of strings and symbols as arguments. Here we build a
991
+ # single list of all of the method names that have to be made private
992
+ arrays, others = T.cast(
993
+ arguments.partition { |argument| argument.is_a?(Prism::ArrayNode) },
994
+ [T::Array[Prism::ArrayNode], T::Array[Prism::Node]],
995
+ )
996
+ arrays.each { |array| others.concat(array.elements) }
975
997
 
976
- entries = @index.resolve_method(method_name, @index.existing_or_new_singleton_class(owner_name).name)
977
- next unless entries
998
+ names = others.filter_map do |argument|
999
+ case argument
1000
+ when Prism::StringNode
1001
+ argument.unescaped
1002
+ when Prism::SymbolNode
1003
+ argument.value
1004
+ end
1005
+ end
978
1006
 
979
- entries.each do |entry|
980
- entry.visibility = Entry::Visibility::PRIVATE
981
- end
1007
+ names.each do |name|
1008
+ entries = @index.resolve_method(name, @index.existing_or_new_singleton_class(owner_name).name)
1009
+ next unless entries
1010
+
1011
+ entries.each do |entry|
1012
+ entry.visibility = Entry::Visibility::PRIVATE
982
1013
  end
983
1014
  end
984
1015
  end
985
1016
 
986
- sig { returns(Entry::Visibility) }
987
- def current_visibility
1017
+ sig { returns(VisibilityScope) }
1018
+ def current_visibility_scope
988
1019
  T.must(@visibility_stack.last)
989
1020
  end
990
1021
 
@@ -1091,7 +1122,7 @@ module RubyIndexer
1091
1122
 
1092
1123
  sig { params(short_name: String, entry: Entry::Namespace).void }
1093
1124
  def advance_namespace_stack(short_name, entry)
1094
- @visibility_stack.push(Entry::Visibility::PUBLIC)
1125
+ @visibility_stack.push(VisibilityScope.public_scope)
1095
1126
  @owner_stack << entry
1096
1127
  @index.add(entry)
1097
1128
  @stack << short_name
@@ -48,6 +48,8 @@ module RubyIndexer
48
48
  )
49
49
 
50
50
  @configuration = T.let(RubyIndexer::Configuration.new, Configuration)
51
+
52
+ @initial_indexing_completed = T.let(false, T::Boolean)
51
53
  end
52
54
 
53
55
  # Register an included `hook` that will be executed when `module_name` is included into any namespace
@@ -56,8 +58,8 @@ module RubyIndexer
56
58
  (@included_hooks[module_name] ||= []) << hook
57
59
  end
58
60
 
59
- sig { params(uri: URI::Generic).void }
60
- def delete(uri)
61
+ sig { params(uri: URI::Generic, skip_require_paths_tree: T::Boolean).void }
62
+ def delete(uri, skip_require_paths_tree: false)
61
63
  key = uri.to_s
62
64
  # For each constant discovered in `path`, delete the associated entry from the index. If there are no entries
63
65
  # left, delete the constant from the index.
@@ -80,6 +82,7 @@ module RubyIndexer
80
82
  end
81
83
 
82
84
  @uris_to_entries.delete(key)
85
+ return if skip_require_paths_tree
83
86
 
84
87
  require_path = uri.require_path
85
88
  @require_paths_tree.delete(require_path) if require_path
@@ -357,12 +360,13 @@ module RubyIndexer
357
360
  # When troubleshooting an indexing issue, e.g. through irb, it's not obvious that `index_all` will augment the
358
361
  # existing index values, meaning it may contain 'stale' entries. This check ensures that the user is aware of this
359
362
  # behavior and can take appropriate action.
360
- # binding.break
361
- if @entries.any?
363
+ if @initial_indexing_completed
362
364
  raise IndexNotEmptyError,
363
365
  "The index is not empty. To prevent invalid entries, `index_all` can only be called once."
364
366
  end
365
367
 
368
+ @initial_indexing_completed = true
369
+
366
370
  RBSIndexer.new(self).index_ruby_core
367
371
  # Calculate how many paths are worth 1% of progress
368
372
  progress_step = (uris.length / 100.0).ceil
@@ -618,17 +622,24 @@ module RubyIndexer
618
622
  end
619
623
 
620
624
  # Synchronizes a change made to the given URI. This method will ensure that new declarations are indexed, removed
621
- # declarations removed and that the ancestor linearization cache is cleared if necessary
622
- sig { params(uri: URI::Generic, source: String).void }
623
- def handle_change(uri, source)
625
+ # declarations removed and that the ancestor linearization cache is cleared if necessary. If a block is passed, the
626
+ # consumer of this API has to handle deleting and inserting/updating entries in the index instead of passing the
627
+ # document's source (used to handle unsaved changes to files)
628
+ sig do
629
+ params(uri: URI::Generic, source: T.nilable(String), block: T.nilable(T.proc.params(index: Index).void)).void
630
+ end
631
+ def handle_change(uri, source = nil, &block)
624
632
  key = uri.to_s
625
633
  original_entries = @uris_to_entries[key]
626
634
 
627
- delete(uri)
628
- index_single(uri, source)
635
+ if block
636
+ block.call(self)
637
+ else
638
+ delete(uri)
639
+ index_single(uri, T.must(source))
640
+ end
629
641
 
630
642
  updated_entries = @uris_to_entries[key]
631
-
632
643
  return unless original_entries && updated_entries
633
644
 
634
645
  # A change in one ancestor may impact several different others, which could be including that ancestor through
@@ -0,0 +1,36 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyIndexer
5
+ # Represents the visibility scope in a Ruby namespace. This keeps track of whether methods are in a public, private or
6
+ # protected section, and whether they are module functions.
7
+ class VisibilityScope
8
+ extend T::Sig
9
+
10
+ class << self
11
+ extend T::Sig
12
+
13
+ sig { returns(T.attached_class) }
14
+ def module_function_scope
15
+ new(module_func: true, visibility: Entry::Visibility::PRIVATE)
16
+ end
17
+
18
+ sig { returns(T.attached_class) }
19
+ def public_scope
20
+ new
21
+ end
22
+ end
23
+
24
+ sig { returns(Entry::Visibility) }
25
+ attr_reader :visibility
26
+
27
+ sig { returns(T::Boolean) }
28
+ attr_reader :module_func
29
+
30
+ sig { params(visibility: Entry::Visibility, module_func: T::Boolean).void }
31
+ def initialize(visibility: Entry::Visibility::PUBLIC, module_func: false)
32
+ @visibility = visibility
33
+ @module_func = module_func
34
+ end
35
+ end
36
+ end
@@ -5,6 +5,7 @@ require "yaml"
5
5
  require "did_you_mean"
6
6
 
7
7
  require "ruby_indexer/lib/ruby_indexer/uri"
8
+ require "ruby_indexer/lib/ruby_indexer/visibility_scope"
8
9
  require "ruby_indexer/lib/ruby_indexer/declaration_listener"
9
10
  require "ruby_indexer/lib/ruby_indexer/reference_finder"
10
11
  require "ruby_indexer/lib/ruby_indexer/enhancement"
@@ -2061,7 +2061,8 @@ module RubyIndexer
2061
2061
  end
2062
2062
 
2063
2063
  def test_prevents_multiple_calls_to_index_all
2064
- # For this test class, `index_all` is already called once in `setup`.
2064
+ @index.index_all
2065
+
2065
2066
  assert_raises(Index::IndexNotEmptyError) do
2066
2067
  @index.index_all
2067
2068
  end
@@ -216,5 +216,25 @@ module RubyIndexer
216
216
  assert_instance_of(Entry::Class, owner)
217
217
  assert_equal("Foo", owner.name)
218
218
  end
219
+
220
+ def test_module_function_does_not_impact_instance_variables
221
+ # One possible way of implementing `module_function` would be to push a fake singleton class to the stack, so that
222
+ # methods are inserted into it. However, that would be incorrect because it would then bind instance variables to
223
+ # the wrong type. This test is here to prevent that from happening.
224
+ index(<<~RUBY)
225
+ module Foo
226
+ module_function
227
+
228
+ def something; end
229
+
230
+ @a = 123
231
+ end
232
+ RUBY
233
+
234
+ entry = T.must(@index["@a"]&.first)
235
+ owner = T.must(entry.owner)
236
+ assert_instance_of(Entry::SingletonClass, owner)
237
+ assert_equal("Foo::<Class:Foo>", owner.name)
238
+ end
219
239
  end
220
240
  end
@@ -88,19 +88,21 @@ module RubyIndexer
88
88
 
89
89
  def test_visibility_tracking
90
90
  index(<<~RUBY)
91
- private def foo
92
- end
91
+ class Foo
92
+ private def foo
93
+ end
93
94
 
94
- def bar; end
95
+ def bar; end
95
96
 
96
- protected
97
+ protected
97
98
 
98
- def baz; end
99
+ def baz; end
100
+ end
99
101
  RUBY
100
102
 
101
- assert_entry("foo", Entry::Method, "/fake/path/foo.rb:0-8:1-3", visibility: Entry::Visibility::PRIVATE)
102
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:3-0:3-12", visibility: Entry::Visibility::PUBLIC)
103
- assert_entry("baz", Entry::Method, "/fake/path/foo.rb:7-0:7-12", visibility: Entry::Visibility::PROTECTED)
103
+ assert_entry("foo", Entry::Method, "/fake/path/foo.rb:1-10:2-5", visibility: Entry::Visibility::PRIVATE)
104
+ assert_entry("bar", Entry::Method, "/fake/path/foo.rb:4-2:4-14", visibility: Entry::Visibility::PUBLIC)
105
+ assert_entry("baz", Entry::Method, "/fake/path/foo.rb:8-2:8-14", visibility: Entry::Visibility::PROTECTED)
104
106
  end
105
107
 
106
108
  def test_visibility_tracking_with_nested_class_or_modules
@@ -846,6 +848,82 @@ module RubyIndexer
846
848
  assert_signature_matches(entry, "baz(1)")
847
849
  end
848
850
 
851
+ def test_module_function_with_no_arguments
852
+ index(<<~RUBY)
853
+ module Foo
854
+ def bar; end
855
+
856
+ module_function
857
+
858
+ def baz; end
859
+ attr_reader :attribute
860
+
861
+ public
862
+
863
+ def qux; end
864
+ end
865
+ RUBY
866
+
867
+ entry = T.must(@index["bar"].first)
868
+ assert_predicate(entry, :public?)
869
+ assert_equal("Foo", T.must(entry.owner).name)
870
+
871
+ instance_baz, singleton_baz = T.must(@index["baz"])
872
+ assert_predicate(instance_baz, :private?)
873
+ assert_equal("Foo", T.must(instance_baz.owner).name)
874
+
875
+ assert_predicate(singleton_baz, :public?)
876
+ assert_equal("Foo::<Class:Foo>", T.must(singleton_baz.owner).name)
877
+
878
+ # After invoking `public`, the state of `module_function` is reset
879
+ instance_qux, singleton_qux = T.must(@index["qux"])
880
+ assert_nil(singleton_qux)
881
+ assert_predicate(instance_qux, :public?)
882
+ assert_equal("Foo", T.must(instance_baz.owner).name)
883
+
884
+ # Attributes are not turned into class methods, they do become private
885
+ instance_attribute, singleton_attribute = @index["attribute"]
886
+ assert_nil(singleton_attribute)
887
+ assert_equal("Foo", T.must(instance_attribute.owner).name)
888
+ assert_predicate(instance_attribute, :private?)
889
+ end
890
+
891
+ def test_module_function_does_nothing_in_classes
892
+ # Invoking `module_function` in a class raises an error. We simply ignore it
893
+ index(<<~RUBY)
894
+ class Foo
895
+ def bar; end
896
+
897
+ module_function
898
+
899
+ def baz; end
900
+ end
901
+ RUBY
902
+
903
+ entry = T.must(@index["bar"].first)
904
+ assert_predicate(entry, :public?)
905
+ assert_equal("Foo", T.must(entry.owner).name)
906
+
907
+ entry = T.must(@index["baz"].first)
908
+ assert_predicate(entry, :public?)
909
+ assert_equal("Foo", T.must(entry.owner).name)
910
+ end
911
+
912
+ def test_making_several_class_methods_private
913
+ index(<<~RUBY)
914
+ class Foo
915
+ def self.bar; end
916
+ def self.baz; end
917
+ def self.qux; end
918
+
919
+ private_class_method :bar, :baz, :qux
920
+
921
+ def initialize
922
+ end
923
+ end
924
+ RUBY
925
+ end
926
+
849
927
  private
850
928
 
851
929
  sig { params(entry: Entry::Method, call_string: String).void }
@@ -18,22 +18,21 @@ module RubyLsp
18
18
  @incoming_queue = T.let(Thread::Queue.new, Thread::Queue)
19
19
  @outgoing_queue = T.let(Thread::Queue.new, Thread::Queue)
20
20
  @cancelled_requests = T.let([], T::Array[Integer])
21
- @mutex = T.let(Mutex.new, Mutex)
22
21
  @worker = T.let(new_worker, Thread)
23
22
  @current_request_id = T.let(1, Integer)
24
- @store = T.let(Store.new, Store)
23
+ @global_state = T.let(GlobalState.new, GlobalState)
24
+ @store = T.let(Store.new(@global_state), Store)
25
25
  @outgoing_dispatcher = T.let(
26
26
  Thread.new do
27
27
  unless @test_mode
28
28
  while (message = @outgoing_queue.pop)
29
- @mutex.synchronize { @writer.write(message.to_hash) }
29
+ @global_state.synchronize { @writer.write(message.to_hash) }
30
30
  end
31
31
  end
32
32
  end,
33
33
  Thread,
34
34
  )
35
35
 
36
- @global_state = T.let(GlobalState.new, GlobalState)
37
36
  Thread.main.priority = 1
38
37
 
39
38
  # We read the initialize request in `exe/ruby-lsp` to be able to determine the workspace URI where Bundler should
@@ -51,7 +50,7 @@ module RubyLsp
51
50
  # source. Altering the source reference during parsing will put the parser in an invalid internal state, since
52
51
  # it started parsing with one source but then it changed in the middle. We don't want to do this for text
53
52
  # synchronization notifications
54
- @mutex.synchronize do
53
+ @global_state.synchronize do
55
54
  uri = message.dig(:params, :textDocument, :uri)
56
55
 
57
56
  if uri
@@ -91,18 +90,17 @@ module RubyLsp
91
90
  # The following requests need to be executed in the main thread directly to avoid concurrency issues. Everything
92
91
  # else is pushed into the incoming queue
93
92
  case method
94
- when "initialize", "initialized", "textDocument/didOpen", "textDocument/didClose", "textDocument/didChange",
95
- "$/cancelRequest"
93
+ when "initialize", "initialized", "textDocument/didOpen", "textDocument/didClose", "textDocument/didChange"
96
94
  process_message(message)
97
95
  when "shutdown"
98
- @mutex.synchronize do
96
+ @global_state.synchronize do
99
97
  send_log_message("Shutting down Ruby LSP...")
100
98
  shutdown
101
99
  run_shutdown
102
100
  @writer.write(Result.new(id: message[:id], response: nil).to_hash)
103
101
  end
104
102
  when "exit"
105
- @mutex.synchronize do
103
+ @global_state.synchronize do
106
104
  status = @incoming_queue.closed? ? 0 : 1
107
105
  send_log_message("Shutdown complete with status #{status}")
108
106
  exit(status)
@@ -157,13 +155,9 @@ module RubyLsp
157
155
  id = message[:id]
158
156
 
159
157
  # Check if the request was cancelled before trying to process it
160
- @mutex.synchronize do
158
+ @global_state.synchronize do
161
159
  if id && @cancelled_requests.include?(id)
162
- send_message(Error.new(
163
- id: id,
164
- code: Constant::ErrorCodes::REQUEST_CANCELLED,
165
- message: "Request #{id} was cancelled",
166
- ))
160
+ send_message(Result.new(id: id, response: nil))
167
161
  @cancelled_requests.delete(id)
168
162
  next
169
163
  end