ruby-lsp 0.23.11 → 0.23.13

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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp-launcher +12 -11
  5. data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +1 -1
  6. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
  7. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +81 -115
  8. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +117 -166
  9. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +9 -7
  10. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +88 -200
  11. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +56 -192
  12. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
  13. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +14 -16
  14. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +22 -45
  15. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +42 -60
  16. data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +9 -16
  17. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +5 -9
  18. data/lib/ruby_indexer/test/configuration_test.rb +42 -3
  19. data/lib/ruby_indexer/test/method_test.rb +28 -2
  20. data/lib/ruby_indexer/test/rbs_indexer_test.rb +1 -1
  21. data/lib/ruby_lsp/addon.rb +44 -71
  22. data/lib/ruby_lsp/base_server.rb +29 -32
  23. data/lib/ruby_lsp/client_capabilities.rb +10 -12
  24. data/lib/ruby_lsp/document.rb +34 -45
  25. data/lib/ruby_lsp/erb_document.rb +24 -36
  26. data/lib/ruby_lsp/global_state.rb +51 -56
  27. data/lib/ruby_lsp/internal.rb +2 -0
  28. data/lib/ruby_lsp/listeners/code_lens.rb +81 -88
  29. data/lib/ruby_lsp/listeners/completion.rb +36 -55
  30. data/lib/ruby_lsp/listeners/definition.rb +37 -51
  31. data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
  32. data/lib/ruby_lsp/listeners/document_link.rb +43 -62
  33. data/lib/ruby_lsp/listeners/document_symbol.rb +35 -49
  34. data/lib/ruby_lsp/listeners/folding_ranges.rb +32 -39
  35. data/lib/ruby_lsp/listeners/hover.rb +81 -100
  36. data/lib/ruby_lsp/listeners/inlay_hints.rb +4 -11
  37. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +42 -51
  38. data/lib/ruby_lsp/listeners/signature_help.rb +6 -25
  39. data/lib/ruby_lsp/listeners/spec_style.rb +155 -0
  40. data/lib/ruby_lsp/listeners/test_discovery.rb +89 -0
  41. data/lib/ruby_lsp/listeners/test_style.rb +160 -88
  42. data/lib/ruby_lsp/node_context.rb +12 -39
  43. data/lib/ruby_lsp/rbs_document.rb +8 -6
  44. data/lib/ruby_lsp/requests/code_action_resolve.rb +10 -10
  45. data/lib/ruby_lsp/requests/code_actions.rb +14 -26
  46. data/lib/ruby_lsp/requests/code_lens.rb +6 -17
  47. data/lib/ruby_lsp/requests/completion.rb +7 -20
  48. data/lib/ruby_lsp/requests/completion_resolve.rb +5 -5
  49. data/lib/ruby_lsp/requests/definition.rb +8 -17
  50. data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
  51. data/lib/ruby_lsp/requests/discover_tests.rb +18 -5
  52. data/lib/ruby_lsp/requests/document_highlight.rb +5 -15
  53. data/lib/ruby_lsp/requests/document_link.rb +6 -17
  54. data/lib/ruby_lsp/requests/document_symbol.rb +5 -8
  55. data/lib/ruby_lsp/requests/folding_ranges.rb +7 -15
  56. data/lib/ruby_lsp/requests/formatting.rb +6 -9
  57. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +87 -0
  58. data/lib/ruby_lsp/requests/hover.rb +8 -18
  59. data/lib/ruby_lsp/requests/inlay_hints.rb +6 -17
  60. data/lib/ruby_lsp/requests/on_type_formatting.rb +28 -38
  61. data/lib/ruby_lsp/requests/prepare_rename.rb +4 -9
  62. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +4 -13
  63. data/lib/ruby_lsp/requests/range_formatting.rb +5 -6
  64. data/lib/ruby_lsp/requests/references.rb +6 -36
  65. data/lib/ruby_lsp/requests/rename.rb +11 -37
  66. data/lib/ruby_lsp/requests/request.rb +7 -19
  67. data/lib/ruby_lsp/requests/selection_ranges.rb +5 -5
  68. data/lib/ruby_lsp/requests/semantic_highlighting.rb +12 -31
  69. data/lib/ruby_lsp/requests/show_syntax_tree.rb +5 -6
  70. data/lib/ruby_lsp/requests/signature_help.rb +8 -26
  71. data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
  72. data/lib/ruby_lsp/requests/support/common.rb +13 -50
  73. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +27 -35
  74. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +9 -12
  75. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +22 -34
  76. data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
  77. data/lib/ruby_lsp/requests/support/sorbet.rb +29 -38
  78. data/lib/ruby_lsp/requests/support/source_uri.rb +16 -30
  79. data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +12 -19
  80. data/lib/ruby_lsp/requests/support/test_item.rb +10 -14
  81. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +5 -6
  82. data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
  83. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +5 -5
  84. data/lib/ruby_lsp/response_builders/document_symbol.rb +10 -16
  85. data/lib/ruby_lsp/response_builders/hover.rb +10 -13
  86. data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
  87. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +59 -87
  88. data/lib/ruby_lsp/response_builders/signature_help.rb +5 -6
  89. data/lib/ruby_lsp/response_builders/test_collection.rb +6 -10
  90. data/lib/ruby_lsp/ruby_document.rb +22 -60
  91. data/lib/ruby_lsp/ruby_lsp_reporter_plugin.rb +109 -0
  92. data/lib/ruby_lsp/scope.rb +7 -11
  93. data/lib/ruby_lsp/server.rb +133 -74
  94. data/lib/ruby_lsp/setup_bundler.rb +58 -57
  95. data/lib/ruby_lsp/static_docs.rb +4 -7
  96. data/lib/ruby_lsp/store.rb +21 -40
  97. data/lib/ruby_lsp/test_helper.rb +3 -12
  98. data/lib/ruby_lsp/test_reporter.rb +207 -0
  99. data/lib/ruby_lsp/test_unit_test_runner.rb +98 -0
  100. data/lib/ruby_lsp/type_inferrer.rb +9 -13
  101. data/lib/ruby_lsp/utils.rb +37 -81
  102. metadata +9 -3
@@ -5,29 +5,25 @@ module RubyIndexer
5
5
  # Represents the visibility scope in a Ruby namespace. This keeps track of whether methods are in a public, private or
6
6
  # protected section, and whether they are module functions.
7
7
  class VisibilityScope
8
- extend T::Sig
9
-
10
8
  class << self
11
- extend T::Sig
12
-
13
- sig { returns(T.attached_class) }
9
+ #: -> instance
14
10
  def module_function_scope
15
11
  new(module_func: true, visibility: Entry::Visibility::PRIVATE)
16
12
  end
17
13
 
18
- sig { returns(T.attached_class) }
14
+ #: -> instance
19
15
  def public_scope
20
16
  new
21
17
  end
22
18
  end
23
19
 
24
- sig { returns(Entry::Visibility) }
20
+ #: Entry::Visibility
25
21
  attr_reader :visibility
26
22
 
27
- sig { returns(T::Boolean) }
23
+ #: bool
28
24
  attr_reader :module_func
29
25
 
30
- sig { params(visibility: Entry::Visibility, module_func: T::Boolean).void }
26
+ #: (?visibility: Entry::Visibility, ?module_func: bool) -> void
31
27
  def initialize(visibility: Entry::Visibility::PUBLIC, module_func: false)
32
28
  @visibility = visibility
33
29
  @module_func = module_func
@@ -12,7 +12,7 @@ module RubyIndexer
12
12
  end
13
13
 
14
14
  def test_load_configuration_executes_configure_block
15
- @config.apply_config({ "excluded_patterns" => ["**/fixtures/**/*.rb"] })
15
+ @config.apply_config({ "excluded_patterns" => ["**/fixtures/**/*"] })
16
16
  uris = @config.indexable_uris
17
17
 
18
18
  bundle_path = Bundler.bundle_path.join("gems")
@@ -39,7 +39,11 @@ module RubyIndexer
39
39
  next if lazy_spec.name == "ruby-lsp"
40
40
 
41
41
  spec = Gem::Specification.find_by_name(lazy_spec.name)
42
- assert(uris.none? { |uri| uri.full_path.start_with?("#{spec.full_gem_path}/test/") })
42
+
43
+ test_uris = uris.select do |uri|
44
+ File.fnmatch?(File.join(spec.full_gem_path, "test/**/*"), uri.full_path, File::Constants::FNM_PATHNAME)
45
+ end
46
+ assert_empty(test_uris)
43
47
  rescue Gem::MissingSpecError
44
48
  # Transitive dependencies might be missing when running tests on Windows
45
49
  end
@@ -143,17 +147,26 @@ module RubyIndexer
143
147
  uris = @config.indexable_uris
144
148
  assert(uris.none? { |uri| uri.full_path.start_with?(File.join(dir, "ignore")) })
145
149
 
150
+ # The regular default gem path is ~/.rubies/3.4.1/lib/ruby/3.4.0
151
+ # The alternative default gem path is ~/.rubies/3.4.1/lib/ruby/gems/3.4.0
152
+ # Here part_1 contains ~/.rubies/3.4.1/lib/ruby/ and part_2 contains 3.4.0, so that we can turn it into the
153
+ # alternative path
154
+ part_1, part_2 = Pathname.new(RbConfig::CONFIG["rubylibdir"]).split
155
+ other_default_gem_dir = part_1.join("gems").join(part_2).to_s
156
+
146
157
  # After switching the workspace path, all indexable URIs will be found in one of these places:
147
158
  # - The new workspace path
148
159
  # - The Ruby LSP's own code (because Bundler is requiring the dependency from source)
149
160
  # - Bundled gems
150
161
  # - Default gems
162
+ # - Other default gem directory
151
163
  assert(
152
164
  uris.all? do |u|
153
165
  u.full_path.start_with?(dir) ||
154
166
  u.full_path.start_with?(File.join(Dir.pwd, "lib")) ||
155
167
  u.full_path.start_with?(Bundler.bundle_path.to_s) ||
156
- u.full_path.start_with?(RbConfig::CONFIG["rubylibdir"])
168
+ u.full_path.start_with?(RbConfig::CONFIG["rubylibdir"]) ||
169
+ u.full_path.start_with?(other_default_gem_dir)
157
170
  end,
158
171
  )
159
172
  end
@@ -235,5 +248,31 @@ module RubyIndexer
235
248
  end
236
249
  end
237
250
  end
251
+
252
+ def test_indexables_include_non_test_files_in_test_directories
253
+ # In order to linearize test parent classes and accurately detect the framework being used, then intermediate
254
+ # parent classes _must_ also be indexed. Otherwise, we have no way of linearizing the rest of the ancestors to
255
+ # determine what the test class ultimately inherits from.
256
+ #
257
+ # Therefore, we need to ensure that test files are excluded, but non test files inside test directories have to be
258
+ # indexed
259
+ FileUtils.touch("test/test_case.rb")
260
+
261
+ uris = @config.indexable_uris
262
+ project_paths = uris.filter_map do |uri|
263
+ path = uri.full_path
264
+ next if path.start_with?(Bundler.bundle_path.to_s) || path.start_with?(RbConfig::CONFIG["rubylibdir"])
265
+
266
+ Pathname.new(path).relative_path_from(Dir.pwd).to_s
267
+ end
268
+
269
+ begin
270
+ assert_includes(project_paths, "test/requests/support/expectations_test_runner.rb")
271
+ assert_includes(project_paths, "test/test_helper.rb")
272
+ assert_includes(project_paths, "test/test_case.rb")
273
+ ensure
274
+ FileUtils.rm("test/test_case.rb")
275
+ end
276
+ end
238
277
  end
239
278
  end
@@ -924,16 +924,42 @@ module RubyIndexer
924
924
  RUBY
925
925
  end
926
926
 
927
+ def test_changing_visibility_post_definition
928
+ index(<<~RUBY)
929
+ class Foo
930
+ def bar; end
931
+ private :bar
932
+
933
+ def baz; end
934
+ protected :baz
935
+
936
+ private
937
+ def qux; end
938
+
939
+ public :qux
940
+ end
941
+ RUBY
942
+
943
+ entry = T.must(@index["bar"].first)
944
+ assert_predicate(entry, :private?)
945
+
946
+ entry = T.must(@index["baz"].first)
947
+ assert_predicate(entry, :protected?)
948
+
949
+ entry = T.must(@index["qux"].first)
950
+ assert_predicate(entry, :public?)
951
+ end
952
+
927
953
  private
928
954
 
929
- sig { params(entry: Entry::Method, call_string: String).void }
955
+ #: (Entry::Method entry, String call_string) -> void
930
956
  def assert_signature_matches(entry, call_string)
931
957
  sig = T.must(entry.signatures.first)
932
958
  arguments = parse_prism_args(call_string)
933
959
  assert(sig.matches?(arguments), "Expected #{call_string} to match #{entry.name}#{entry.decorated_parameters}")
934
960
  end
935
961
 
936
- sig { params(entry: Entry::Method, call_string: String).void }
962
+ #: (Entry::Method entry, String call_string) -> void
937
963
  def refute_signature_matches(entry, call_string)
938
964
  sig = T.must(entry.signatures.first)
939
965
  arguments = parse_prism_args(call_string)
@@ -359,7 +359,7 @@ module RubyIndexer
359
359
  assert_equal("all?", entry.old_name)
360
360
  assert_equal("Array", entry.owner.name)
361
361
  assert(entry.file_path.end_with?("core/array.rbs"))
362
- assert_includes(entry.comments, "Returns `true` if any element of `self` meets a given criterion.")
362
+ refute_empty(entry.comments)
363
363
  end
364
364
 
365
365
  def test_indexing_untyped_functions
@@ -25,42 +25,34 @@ module RubyLsp
25
25
 
26
26
  abstract!
27
27
 
28
- @addons = T.let([], T::Array[Addon])
29
- @addon_classes = T.let([], T::Array[T.class_of(Addon)])
28
+ @addons = [] #: Array[Addon]
29
+ @addon_classes = [] #: Array[singleton(Addon)]
30
30
  # Add-on instances that have declared a handler to accept file watcher events
31
- @file_watcher_addons = T.let([], T::Array[Addon])
31
+ @file_watcher_addons = [] #: Array[Addon]
32
32
 
33
33
  AddonNotFoundError = Class.new(StandardError)
34
34
 
35
35
  class IncompatibleApiError < StandardError; end
36
36
 
37
37
  class << self
38
- extend T::Sig
39
-
40
- sig { returns(T::Array[Addon]) }
38
+ #: Array[Addon]
41
39
  attr_accessor :addons
42
40
 
43
- sig { returns(T::Array[Addon]) }
41
+ #: Array[Addon]
44
42
  attr_accessor :file_watcher_addons
45
43
 
46
- sig { returns(T::Array[T.class_of(Addon)]) }
44
+ #: Array[singleton(Addon)]
47
45
  attr_reader :addon_classes
48
46
 
49
47
  # Automatically track and instantiate add-on classes
50
- sig { params(child_class: T.class_of(Addon)).void }
48
+ #: (singleton(Addon) child_class) -> void
51
49
  def inherited(child_class)
52
50
  addon_classes << child_class
53
51
  super
54
52
  end
55
53
 
56
54
  # Discovers and loads all add-ons. Returns a list of errors when trying to require add-ons
57
- sig do
58
- params(
59
- global_state: GlobalState,
60
- outgoing_queue: Thread::Queue,
61
- include_project_addons: T::Boolean,
62
- ).returns(T::Array[StandardError])
63
- end
55
+ #: (GlobalState global_state, Thread::Queue outgoing_queue, ?include_project_addons: bool) -> Array[StandardError]
64
56
  def load_addons(global_state, outgoing_queue, include_project_addons: true)
65
57
  # Require all add-ons entry points, which should be placed under
66
58
  # `some_gem/lib/ruby_lsp/your_gem_name/addon.rb` or in the workspace under
@@ -98,7 +90,7 @@ module RubyLsp
98
90
  end
99
91
 
100
92
  # Unloads all add-ons. Only intended to be invoked once when shutting down the Ruby LSP server
101
- sig { void }
93
+ #: -> void
102
94
  def unload_addons
103
95
  @addons.each(&:deactivate)
104
96
  @addons.clear
@@ -112,7 +104,7 @@ module RubyLsp
112
104
  # Important: if the add-on is not found, AddonNotFoundError will be raised. If the add-on is found, but its
113
105
  # current version does not satisfy the given version constraint, then IncompatibleApiError will be raised. It is
114
106
  # the responsibility of the add-ons using this API to handle these errors appropriately.
115
- sig { params(addon_name: String, version_constraints: String).returns(Addon) }
107
+ #: (String addon_name, *String version_constraints) -> Addon
116
108
  def get(addon_name, *version_constraints)
117
109
  if version_constraints.empty?
118
110
  raise IncompatibleApiError, "Must specify version constraints when accessing other add-ons"
@@ -144,7 +136,7 @@ module RubyLsp
144
136
  # end
145
137
  # end
146
138
  # ```
147
- sig { params(version_constraints: String).void }
139
+ #: (*String version_constraints) -> void
148
140
  def depend_on_ruby_lsp!(*version_constraints)
149
141
  version_object = Gem::Version.new(RubyLsp::VERSION)
150
142
 
@@ -155,23 +147,23 @@ module RubyLsp
155
147
  end
156
148
  end
157
149
 
158
- sig { void }
150
+ #: -> void
159
151
  def initialize
160
- @errors = T.let([], T::Array[StandardError])
152
+ @errors = [] #: Array[StandardError]
161
153
  end
162
154
 
163
- sig { params(error: StandardError).returns(T.self_type) }
155
+ #: (StandardError error) -> self
164
156
  def add_error(error)
165
157
  @errors << error
166
158
  self
167
159
  end
168
160
 
169
- sig { returns(T::Boolean) }
161
+ #: -> bool
170
162
  def error?
171
163
  @errors.any?
172
164
  end
173
165
 
174
- sig { returns(String) }
166
+ #: -> String
175
167
  def formatted_errors
176
168
  <<~ERRORS
177
169
  #{name}:
@@ -179,7 +171,7 @@ module RubyLsp
179
171
  ERRORS
180
172
  end
181
173
 
182
- sig { returns(String) }
174
+ #: -> String
183
175
  def errors_details
184
176
  @errors.map(&:full_message).join("\n\n")
185
177
  end
@@ -207,69 +199,50 @@ module RubyLsp
207
199
  # original request so that the response is delegated to the correct add-on and must override this method to handle
208
200
  # the response
209
201
  # https://microsoft.github.io/language-server-protocol/specification#window_showMessageRequest
210
- sig { overridable.params(title: String).void }
202
+ # @overridable
203
+ #: (String title) -> void
211
204
  def handle_window_show_message_response(title); end
212
205
 
213
206
  # Creates a new CodeLens listener. This method is invoked on every CodeLens request
214
- sig do
215
- overridable.params(
216
- response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens],
217
- uri: URI::Generic,
218
- dispatcher: Prism::Dispatcher,
219
- ).void
220
- end
207
+ # @overridable
208
+ #: (ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens] response_builder, URI::Generic uri, Prism::Dispatcher dispatcher) -> void
221
209
  def create_code_lens_listener(response_builder, uri, dispatcher); end
222
210
 
223
211
  # Creates a new Hover listener. This method is invoked on every Hover request
224
- sig do
225
- overridable.params(
226
- response_builder: ResponseBuilders::Hover,
227
- node_context: NodeContext,
228
- dispatcher: Prism::Dispatcher,
229
- ).void
230
- end
212
+ # @overridable
213
+ #: (ResponseBuilders::Hover response_builder, NodeContext node_context, Prism::Dispatcher dispatcher) -> void
231
214
  def create_hover_listener(response_builder, node_context, dispatcher); end
232
215
 
233
216
  # Creates a new DocumentSymbol listener. This method is invoked on every DocumentSymbol request
234
- sig do
235
- overridable.params(
236
- response_builder: ResponseBuilders::DocumentSymbol,
237
- dispatcher: Prism::Dispatcher,
238
- ).void
239
- end
217
+ # @overridable
218
+ #: (ResponseBuilders::DocumentSymbol response_builder, Prism::Dispatcher dispatcher) -> void
240
219
  def create_document_symbol_listener(response_builder, dispatcher); end
241
220
 
242
- sig do
243
- overridable.params(
244
- response_builder: ResponseBuilders::SemanticHighlighting,
245
- dispatcher: Prism::Dispatcher,
246
- ).void
247
- end
221
+ # @overridable
222
+ #: (ResponseBuilders::SemanticHighlighting response_builder, Prism::Dispatcher dispatcher) -> void
248
223
  def create_semantic_highlighting_listener(response_builder, dispatcher); end
249
224
 
250
225
  # Creates a new Definition listener. This method is invoked on every Definition request
251
- sig do
252
- overridable.params(
253
- response_builder: ResponseBuilders::CollectionResponseBuilder[T.any(
254
- Interface::Location,
255
- Interface::LocationLink,
256
- )],
257
- uri: URI::Generic,
258
- node_context: NodeContext,
259
- dispatcher: Prism::Dispatcher,
260
- ).void
261
- end
226
+ # @overridable
227
+ #: (ResponseBuilders::CollectionResponseBuilder[(Interface::Location | Interface::LocationLink)] response_builder, URI::Generic uri, NodeContext node_context, Prism::Dispatcher dispatcher) -> void
262
228
  def create_definition_listener(response_builder, uri, node_context, dispatcher); end
263
229
 
264
230
  # Creates a new Completion listener. This method is invoked on every Completion request
265
- sig do
266
- overridable.params(
267
- response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem],
268
- node_context: NodeContext,
269
- dispatcher: Prism::Dispatcher,
270
- uri: URI::Generic,
271
- ).void
272
- end
231
+ # @overridable
232
+ #: (ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem] response_builder, NodeContext node_context, Prism::Dispatcher dispatcher, URI::Generic uri) -> void
273
233
  def create_completion_listener(response_builder, node_context, dispatcher, uri); end
234
+
235
+ # Creates a new Discover Tests listener. This method is invoked on every DiscoverTests request
236
+ # @overridable
237
+ #: (ResponseBuilders::TestCollection response_builder, Prism::Dispatcher dispatcher, URI::Generic uri) -> void
238
+ def create_discover_tests_listener(response_builder, dispatcher, uri); end
239
+
240
+ # Resolves the minimal set of commands required to execute the requested tests. Add-ons are responsible for only
241
+ # handling items related to the framework they add support for and have discovered themselves
242
+ # @overridable
243
+ #: (Array[Hash[Symbol, untyped]]) -> Array[String]
244
+ def resolve_test_commands(items)
245
+ []
246
+ end
274
247
  end
275
248
  end
@@ -8,30 +8,27 @@ module RubyLsp
8
8
 
9
9
  abstract!
10
10
 
11
- sig { params(options: T.untyped).void }
11
+ #: (**untyped options) -> void
12
12
  def initialize(**options)
13
- @test_mode = T.let(options[:test_mode], T.nilable(T::Boolean))
14
- @setup_error = T.let(options[:setup_error], T.nilable(StandardError))
15
- @install_error = T.let(options[:install_error], T.nilable(StandardError))
16
- @writer = T.let(Transport::Stdio::Writer.new, Transport::Stdio::Writer)
17
- @reader = T.let(Transport::Stdio::Reader.new, Transport::Stdio::Reader)
18
- @incoming_queue = T.let(Thread::Queue.new, Thread::Queue)
19
- @outgoing_queue = T.let(Thread::Queue.new, Thread::Queue)
20
- @cancelled_requests = T.let([], T::Array[Integer])
21
- @worker = T.let(new_worker, Thread)
22
- @current_request_id = T.let(1, Integer)
23
- @global_state = T.let(GlobalState.new, GlobalState)
24
- @store = T.let(Store.new(@global_state), Store)
25
- @outgoing_dispatcher = T.let(
26
- Thread.new do
27
- unless @test_mode
28
- while (message = @outgoing_queue.pop)
29
- @global_state.synchronize { @writer.write(message.to_hash) }
30
- end
13
+ @test_mode = options[:test_mode] #: bool?
14
+ @setup_error = options[:setup_error] #: StandardError?
15
+ @install_error = options[:install_error] #: StandardError?
16
+ @writer = Transport::Stdio::Writer.new #: Transport::Stdio::Writer
17
+ @reader = Transport::Stdio::Reader.new #: Transport::Stdio::Reader
18
+ @incoming_queue = Thread::Queue.new #: Thread::Queue
19
+ @outgoing_queue = Thread::Queue.new #: Thread::Queue
20
+ @cancelled_requests = [] #: Array[Integer]
21
+ @worker = new_worker #: Thread
22
+ @current_request_id = 1 #: Integer
23
+ @global_state = GlobalState.new #: GlobalState
24
+ @store = Store.new(@global_state) #: Store
25
+ @outgoing_dispatcher = Thread.new do
26
+ unless @test_mode
27
+ while (message = @outgoing_queue.pop)
28
+ @global_state.synchronize { @writer.write(message.to_hash) }
31
29
  end
32
- end,
33
- Thread,
34
- )
30
+ end
31
+ end #: Thread
35
32
 
36
33
  Thread.main.priority = 1
37
34
 
@@ -41,7 +38,7 @@ module RubyLsp
41
38
  process_message(initialize_request) if initialize_request
42
39
  end
43
40
 
44
- sig { void }
41
+ #: -> void
45
42
  def start
46
43
  @reader.read do |message|
47
44
  method = message[:method]
@@ -108,7 +105,7 @@ module RubyLsp
108
105
  end
109
106
  end
110
107
 
111
- sig { void }
108
+ #: -> void
112
109
  def run_shutdown
113
110
  @incoming_queue.clear
114
111
  @outgoing_queue.clear
@@ -122,13 +119,13 @@ module RubyLsp
122
119
  end
123
120
 
124
121
  # This method is only intended to be used in tests! Pops the latest response that would be sent to the client
125
- sig { returns(T.untyped) }
122
+ #: -> untyped
126
123
  def pop_response
127
124
  @outgoing_queue.pop
128
125
  end
129
126
 
130
127
  # This method is only intended to be used in tests! Pushes a message to the incoming queue directly
131
- sig { params(message: T::Hash[Symbol, T.untyped]).void }
128
+ #: (Hash[Symbol, untyped] message) -> void
132
129
  def push_message(message)
133
130
  @incoming_queue << message
134
131
  end
@@ -139,16 +136,16 @@ module RubyLsp
139
136
  sig { abstract.void }
140
137
  def shutdown; end
141
138
 
142
- sig { params(id: Integer, message: String, type: Integer).void }
139
+ #: (Integer id, String message, ?type: Integer) -> void
143
140
  def fail_request_and_notify(id, message, type: Constant::MessageType::INFO)
144
141
  send_message(Error.new(id: id, code: Constant::ErrorCodes::REQUEST_FAILED, message: message))
145
142
  send_message(Notification.window_show_message(message, type: type))
146
143
  end
147
144
 
148
- sig { returns(Thread) }
145
+ #: -> Thread
149
146
  def new_worker
150
147
  Thread.new do
151
- while (message = T.let(@incoming_queue.pop, T.nilable(T::Hash[Symbol, T.untyped])))
148
+ while (message = @incoming_queue.pop)
152
149
  id = message[:id]
153
150
 
154
151
  # Check if the request was cancelled before trying to process it
@@ -165,7 +162,7 @@ module RubyLsp
165
162
  end
166
163
  end
167
164
 
168
- sig { params(message: T.any(Result, Error, Notification, Request)).void }
165
+ #: ((Result | Error | Notification | Request) message) -> void
169
166
  def send_message(message)
170
167
  # When we're shutting down the server, there's a small race condition between closing the thread queues and
171
168
  # finishing remaining requests. We may close the queue in the middle of processing a request, which will then fail
@@ -176,12 +173,12 @@ module RubyLsp
176
173
  @current_request_id += 1 if message.is_a?(Request)
177
174
  end
178
175
 
179
- sig { params(id: Integer).void }
176
+ #: (Integer id) -> void
180
177
  def send_empty_response(id)
181
178
  send_message(Result.new(id: id, response: nil))
182
179
  end
183
180
 
184
- sig { params(message: String, type: Integer).void }
181
+ #: (String message, ?type: Integer) -> void
185
182
  def send_log_message(message, type: Constant::MessageType::LOG)
186
183
  send_message(Notification.window_log_message(message, type: Constant::MessageType::LOG))
187
184
  end
@@ -5,40 +5,38 @@ module RubyLsp
5
5
  # This class stores all client capabilities that the Ruby LSP and its add-ons depend on to ensure that we're
6
6
  # not enabling functionality unsupported by the editor connecting to the server
7
7
  class ClientCapabilities
8
- extend T::Sig
9
-
10
- sig { returns(T::Boolean) }
8
+ #: bool
11
9
  attr_reader :supports_watching_files,
12
10
  :supports_request_delegation,
13
11
  :window_show_message_supports_extra_properties,
14
12
  :supports_progress,
15
13
  :supports_diagnostic_refresh
16
14
 
17
- sig { void }
15
+ #: -> void
18
16
  def initialize
19
17
  # The editor supports watching files. This requires two capabilities: dynamic registration and relative pattern
20
18
  # support
21
- @supports_watching_files = T.let(false, T::Boolean)
19
+ @supports_watching_files = false #: bool
22
20
 
23
21
  # The editor supports request delegation. This is an experimental capability since request delegation has not been
24
22
  # standardized into the LSP spec yet
25
- @supports_request_delegation = T.let(false, T::Boolean)
23
+ @supports_request_delegation = false #: bool
26
24
 
27
25
  # The editor supports extra arbitrary properties for `window/showMessageRequest`. Necessary for add-ons to show
28
26
  # dialogs with user interactions
29
- @window_show_message_supports_extra_properties = T.let(false, T::Boolean)
27
+ @window_show_message_supports_extra_properties = false #: bool
30
28
 
31
29
  # Which resource operations the editor supports, like renaming files
32
- @supported_resource_operations = T.let([], T::Array[String])
30
+ @supported_resource_operations = [] #: Array[String]
33
31
 
34
32
  # The editor supports displaying progress requests
35
- @supports_progress = T.let(false, T::Boolean)
33
+ @supports_progress = false #: bool
36
34
 
37
35
  # The editor supports server initiated refresh for diagnostics
38
- @supports_diagnostic_refresh = T.let(false, T::Boolean)
36
+ @supports_diagnostic_refresh = false #: bool
39
37
  end
40
38
 
41
- sig { params(capabilities: T::Hash[Symbol, T.untyped]).void }
39
+ #: (Hash[Symbol, untyped] capabilities) -> void
42
40
  def apply_client_capabilities(capabilities)
43
41
  workspace_capabilities = capabilities[:workspace] || {}
44
42
 
@@ -65,7 +63,7 @@ module RubyLsp
65
63
  @supports_diagnostic_refresh = workspace_capabilities.dig(:diagnostics, :refreshSupport) || false
66
64
  end
67
65
 
68
- sig { returns(T::Boolean) }
66
+ #: -> bool
69
67
  def supports_rename?
70
68
  @supported_resource_operations.include?("rename")
71
69
  end