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
@@ -4,22 +4,21 @@
4
4
  module RubyLsp
5
5
  module ResponseBuilders
6
6
  class SignatureHelp < ResponseBuilder
7
- extend T::Sig
8
-
9
7
  ResponseType = type_member { { fixed: T.nilable(Interface::SignatureHelp) } }
10
8
 
11
- sig { void }
9
+ #: -> void
12
10
  def initialize
13
11
  super
14
- @signature_help = T.let(nil, ResponseType)
12
+ @signature_help = nil #: ResponseType
15
13
  end
16
14
 
17
- sig { params(signature_help: ResponseType).void }
15
+ #: (ResponseType signature_help) -> void
18
16
  def replace(signature_help)
19
17
  @signature_help = signature_help
20
18
  end
21
19
 
22
- sig { override.returns(ResponseType) }
20
+ # @override
21
+ #: -> ResponseType
23
22
  def response
24
23
  @signature_help
25
24
  end
@@ -4,32 +4,28 @@
4
4
  module RubyLsp
5
5
  module ResponseBuilders
6
6
  class TestCollection < ResponseBuilder
7
- class DuplicateIdError < StandardError; end
8
-
9
- extend T::Sig
10
7
  extend T::Generic
11
8
 
12
9
  ResponseType = type_member { { fixed: Requests::Support::TestItem } }
13
10
 
14
- sig { void }
11
+ #: -> void
15
12
  def initialize
16
13
  super
17
- @items = T.let({}, T::Hash[String, ResponseType])
14
+ @items = {} #: Hash[String, ResponseType]
18
15
  end
19
16
 
20
- sig { params(item: ResponseType).void }
17
+ #: (ResponseType item) -> void
21
18
  def add(item)
22
- raise DuplicateIdError, "TestItem ID is already in use" if @items.key?(item.id)
23
-
24
19
  @items[item.id] = item
25
20
  end
26
21
 
27
- sig { params(id: String).returns(T.nilable(ResponseType)) }
22
+ #: (String id) -> ResponseType?
28
23
  def [](id)
29
24
  @items[id]
30
25
  end
31
26
 
32
- sig { override.returns(T::Array[ResponseType]) }
27
+ # @override
28
+ #: -> Array[ResponseType]
33
29
  def response
34
30
  @items.values
35
31
  end
@@ -3,7 +3,6 @@
3
3
 
4
4
  module RubyLsp
5
5
  class RubyDocument < Document
6
- extend T::Sig
7
6
  extend T::Generic
8
7
 
9
8
  ParseResultType = type_member { { fixed: Prism::ParseResult } }
@@ -35,38 +34,15 @@ module RubyLsp
35
34
  end
36
35
 
37
36
  class << self
38
- extend T::Sig
39
-
40
- sig do
41
- params(
42
- node: Prism::Node,
43
- char_position: Integer,
44
- code_units_cache: T.any(
45
- T.proc.params(arg0: Integer).returns(Integer),
46
- Prism::CodeUnitsCache,
47
- ),
48
- node_types: T::Array[T.class_of(Prism::Node)],
49
- ).returns(NodeContext)
50
- end
37
+ #: (Prism::Node node, Integer char_position, code_units_cache: (^(Integer arg0) -> Integer | Prism::CodeUnitsCache), ?node_types: Array[singleton(Prism::Node)]) -> NodeContext
51
38
  def locate(node, char_position, code_units_cache:, node_types: [])
52
- queue = T.let(node.child_nodes.compact, T::Array[T.nilable(Prism::Node)])
39
+ queue = node.child_nodes.compact #: Array[Prism::Node?]
53
40
  closest = node
54
- parent = T.let(nil, T.nilable(Prism::Node))
55
- nesting_nodes = T.let(
56
- [],
57
- T::Array[T.any(
58
- Prism::ClassNode,
59
- Prism::ModuleNode,
60
- Prism::SingletonClassNode,
61
- Prism::DefNode,
62
- Prism::BlockNode,
63
- Prism::LambdaNode,
64
- Prism::ProgramNode,
65
- )],
66
- )
41
+ parent = nil #: Prism::Node?
42
+ nesting_nodes = [] #: Array[(Prism::ClassNode | Prism::ModuleNode | Prism::SingletonClassNode | Prism::DefNode | Prism::BlockNode | Prism::LambdaNode | Prism::ProgramNode)] # rubocop:disable Layout/LineLength
67
43
 
68
44
  nesting_nodes << node if node.is_a?(Prism::ProgramNode)
69
- call_node = T.let(nil, T.nilable(Prism::CallNode))
45
+ call_node = nil #: Prism::CallNode?
70
46
 
71
47
  until queue.empty?
72
48
  candidate = queue.shift
@@ -150,24 +126,18 @@ module RubyLsp
150
126
  end
151
127
  end
152
128
 
153
- sig do
154
- returns(T.any(
155
- T.proc.params(arg0: Integer).returns(Integer),
156
- Prism::CodeUnitsCache,
157
- ))
158
- end
129
+ #: (^(Integer arg0) -> Integer | Prism::CodeUnitsCache)
159
130
  attr_reader :code_units_cache
160
131
 
161
- sig { params(source: String, version: Integer, uri: URI::Generic, global_state: GlobalState).void }
132
+ #: (source: String, version: Integer, uri: URI::Generic, global_state: GlobalState) -> void
162
133
  def initialize(source:, version:, uri:, global_state:)
163
134
  super
164
- @code_units_cache = T.let(@parse_result.code_units_cache(@encoding), T.any(
165
- T.proc.params(arg0: Integer).returns(Integer),
166
- Prism::CodeUnitsCache,
167
- ))
135
+ @code_units_cache = @parse_result
136
+ .code_units_cache(@encoding) #: (^(Integer arg0) -> Integer | Prism::CodeUnitsCache)
168
137
  end
169
138
 
170
- sig { override.returns(T::Boolean) }
139
+ # @override
140
+ #: -> bool
171
141
  def parse!
172
142
  return false unless @needs_parsing
173
143
 
@@ -177,17 +147,19 @@ module RubyLsp
177
147
  true
178
148
  end
179
149
 
180
- sig { override.returns(T::Boolean) }
150
+ # @override
151
+ #: -> bool
181
152
  def syntax_error?
182
153
  @parse_result.failure?
183
154
  end
184
155
 
185
- sig { override.returns(LanguageId) }
156
+ # @override
157
+ #: -> LanguageId
186
158
  def language_id
187
159
  LanguageId::Ruby
188
160
  end
189
161
 
190
- sig { returns(SorbetLevel) }
162
+ #: -> SorbetLevel
191
163
  def sorbet_level
192
164
  sigil = parse_result.magic_comments.find do |comment|
193
165
  comment.key == "typed"
@@ -207,17 +179,12 @@ module RubyLsp
207
179
  end
208
180
  end
209
181
 
210
- sig do
211
- params(
212
- range: T::Hash[Symbol, T.untyped],
213
- node_types: T::Array[T.class_of(Prism::Node)],
214
- ).returns(T.nilable(Prism::Node))
215
- end
182
+ #: (Hash[Symbol, untyped] range, ?node_types: Array[singleton(Prism::Node)]) -> Prism::Node?
216
183
  def locate_first_within_range(range, node_types: [])
217
184
  start_position, end_position = find_index_by_position(range[:start], range[:end])
218
185
 
219
186
  desired_range = (start_position...end_position)
220
- queue = T.let(@parse_result.value.child_nodes.compact, T::Array[T.nilable(Prism::Node)])
187
+ queue = @parse_result.value.child_nodes.compact #: Array[Prism::Node?]
221
188
 
222
189
  until queue.empty?
223
190
  candidate = queue.shift
@@ -240,12 +207,7 @@ module RubyLsp
240
207
  end
241
208
  end
242
209
 
243
- sig do
244
- params(
245
- position: T::Hash[Symbol, T.untyped],
246
- node_types: T::Array[T.class_of(Prism::Node)],
247
- ).returns(NodeContext)
248
- end
210
+ #: (Hash[Symbol, untyped] position, ?node_types: Array[singleton(Prism::Node)]) -> NodeContext
249
211
  def locate_node(position, node_types: [])
250
212
  char_position, _ = find_index_by_position(position)
251
213
 
@@ -257,7 +219,7 @@ module RubyLsp
257
219
  )
258
220
  end
259
221
 
260
- sig { returns(T::Boolean) }
222
+ #: -> bool
261
223
  def should_index?
262
224
  # This method controls when we should index documents. If there's no recent edit and the document has just been
263
225
  # opened, we need to index it
@@ -268,7 +230,7 @@ module RubyLsp
268
230
 
269
231
  private
270
232
 
271
- sig { returns(T::Boolean) }
233
+ #: -> bool
272
234
  def last_edit_may_change_declarations?
273
235
  case @last_edit
274
236
  when Delete
@@ -282,7 +244,7 @@ module RubyLsp
282
244
  end
283
245
  end
284
246
 
285
- sig { params(position: T::Hash[Symbol, Integer]).returns(T::Boolean) }
247
+ #: (Hash[Symbol, Integer] position) -> bool
286
248
  def position_may_impact_declarations?(position)
287
249
  node_context = locate_node(position)
288
250
  node_at_edit = node_context.node
@@ -0,0 +1,109 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ begin
5
+ require "minitest"
6
+ rescue LoadError
7
+ return
8
+ end
9
+
10
+ require_relative "test_reporter"
11
+ require "ruby_indexer/lib/ruby_indexer/uri"
12
+
13
+ module Minitest
14
+ module Reporters
15
+ class RubyLspReporter < ::Minitest::AbstractReporter
16
+ class << self
17
+ #: (Hash[untyped, untyped]) -> void
18
+ def minitest_plugin_init(_options)
19
+ Minitest.reporter.reporters << RubyLspReporter.new
20
+ end
21
+ end
22
+
23
+ #: (singleton(Minitest::Test) test_class, String method_name) -> void
24
+ def prerecord(test_class, method_name)
25
+ uri = uri_from_test_class(test_class, method_name)
26
+ return unless uri
27
+
28
+ RubyLsp::TestReporter.start_test(
29
+ id: "#{test_class.name}##{method_name}",
30
+ uri: uri,
31
+ )
32
+ end
33
+
34
+ #: (Minitest::Result result) -> void
35
+ def record(result)
36
+ if result.error?
37
+ record_error(result)
38
+ elsif result.passed?
39
+ record_pass(result)
40
+ elsif result.skipped?
41
+ record_skip(result)
42
+ elsif result.failure
43
+ record_fail(result)
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ #: (Minitest::Result result) -> void
50
+ def record_pass(result)
51
+ RubyLsp::TestReporter.record_pass(
52
+ id: id_from_result(result),
53
+ uri: uri_from_result(result),
54
+ )
55
+ end
56
+
57
+ #: (Minitest::Result result) -> void
58
+ def record_skip(result)
59
+ RubyLsp::TestReporter.record_skip(
60
+ id: id_from_result(result),
61
+ uri: uri_from_result(result),
62
+ )
63
+ end
64
+
65
+ #: (Minitest::Result result) -> void
66
+ def record_fail(result)
67
+ RubyLsp::TestReporter.record_fail(
68
+ id: id_from_result(result),
69
+ message: result.failure.message,
70
+ uri: uri_from_result(result),
71
+ )
72
+ end
73
+
74
+ #: (Minitest::Result result) -> void
75
+ def record_error(result)
76
+ RubyLsp::TestReporter.record_error(
77
+ id: id_from_result(result),
78
+ uri: uri_from_result(result),
79
+ message: result.failures.first.message,
80
+ )
81
+ end
82
+
83
+ #: (Minitest::Result result) -> String
84
+ def id_from_result(result)
85
+ "#{result.klass}##{result.name}"
86
+ end
87
+
88
+ #: (Minitest::Result result) -> URI::Generic
89
+ def uri_from_result(result)
90
+ file = result.source_location[0]
91
+ absolute_path = File.expand_path(file, Dir.pwd)
92
+ URI::Generic.from_path(path: absolute_path)
93
+ end
94
+
95
+ #: (singleton(Minitest::Test) test_class, String method_name) -> URI::Generic?
96
+ def uri_from_test_class(test_class, method_name)
97
+ file, _line = test_class.instance_method(method_name).source_location
98
+ return unless file
99
+
100
+ return if file.start_with?("(eval at ") # test is dynamically defined
101
+
102
+ absolute_path = File.expand_path(file, Dir.pwd)
103
+ URI::Generic.from_path(path: absolute_path)
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ Minitest.extensions << Minitest::Reporters::RubyLspReporter
@@ -3,26 +3,24 @@
3
3
 
4
4
  module RubyLsp
5
5
  class Scope
6
- extend T::Sig
7
-
8
- sig { returns(T.nilable(Scope)) }
6
+ #: Scope?
9
7
  attr_reader :parent
10
8
 
11
- sig { params(parent: T.nilable(Scope)).void }
9
+ #: (?Scope? parent) -> void
12
10
  def initialize(parent = nil)
13
11
  @parent = parent
14
12
 
15
13
  # A hash of name => type
16
- @locals = T.let({}, T::Hash[Symbol, Local])
14
+ @locals = {} #: Hash[Symbol, Local]
17
15
  end
18
16
 
19
17
  # Add a new local to this scope. The types should only be `:parameter` or `:variable`
20
- sig { params(name: T.any(String, Symbol), type: Symbol).void }
18
+ #: ((String | Symbol) name, Symbol type) -> void
21
19
  def add(name, type)
22
20
  @locals[name.to_sym] = Local.new(type)
23
21
  end
24
22
 
25
- sig { params(name: T.any(String, Symbol)).returns(T.nilable(Local)) }
23
+ #: ((String | Symbol) name) -> Local?
26
24
  def lookup(name)
27
25
  sym = name.to_sym
28
26
  entry = @locals[sym]
@@ -33,12 +31,10 @@ module RubyLsp
33
31
  end
34
32
 
35
33
  class Local
36
- extend T::Sig
37
-
38
- sig { returns(Symbol) }
34
+ #: Symbol
39
35
  attr_reader :type
40
36
 
41
- sig { params(type: Symbol).void }
37
+ #: (Symbol type) -> void
42
38
  def initialize(type)
43
39
  @type = type
44
40
  end