ruby-lsp 0.23.11 → 0.23.17

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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp-launcher +20 -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 +82 -116
  8. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +134 -183
  9. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +9 -10
  10. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +97 -217
  11. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +139 -281
  12. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
  13. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +18 -19
  14. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +23 -55
  15. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +47 -61
  16. data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +17 -19
  17. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +7 -11
  18. data/lib/ruby_indexer/test/class_variables_test.rb +14 -14
  19. data/lib/ruby_indexer/test/classes_and_modules_test.rb +65 -40
  20. data/lib/ruby_indexer/test/configuration_test.rb +48 -7
  21. data/lib/ruby_indexer/test/constant_test.rb +34 -34
  22. data/lib/ruby_indexer/test/enhancements_test.rb +1 -1
  23. data/lib/ruby_indexer/test/index_test.rb +146 -135
  24. data/lib/ruby_indexer/test/instance_variables_test.rb +37 -37
  25. data/lib/ruby_indexer/test/method_test.rb +149 -123
  26. data/lib/ruby_indexer/test/prefix_tree_test.rb +13 -13
  27. data/lib/ruby_indexer/test/rbs_indexer_test.rb +68 -73
  28. data/lib/ruby_indexer/test/test_case.rb +9 -3
  29. data/lib/ruby_indexer/test/uri_test.rb +15 -2
  30. data/lib/ruby_lsp/addon.rb +44 -71
  31. data/lib/ruby_lsp/base_server.rb +29 -32
  32. data/lib/ruby_lsp/client_capabilities.rb +10 -12
  33. data/lib/ruby_lsp/document.rb +40 -54
  34. data/lib/ruby_lsp/erb_document.rb +37 -41
  35. data/lib/ruby_lsp/global_state.rb +52 -57
  36. data/lib/ruby_lsp/internal.rb +2 -0
  37. data/lib/ruby_lsp/listeners/code_lens.rb +82 -89
  38. data/lib/ruby_lsp/listeners/completion.rb +67 -73
  39. data/lib/ruby_lsp/listeners/definition.rb +44 -58
  40. data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
  41. data/lib/ruby_lsp/listeners/document_link.rb +50 -70
  42. data/lib/ruby_lsp/listeners/document_symbol.rb +38 -52
  43. data/lib/ruby_lsp/listeners/folding_ranges.rb +40 -43
  44. data/lib/ruby_lsp/listeners/hover.rb +92 -110
  45. data/lib/ruby_lsp/listeners/inlay_hints.rb +4 -11
  46. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -56
  47. data/lib/ruby_lsp/listeners/signature_help.rb +12 -27
  48. data/lib/ruby_lsp/listeners/spec_style.rb +155 -0
  49. data/lib/ruby_lsp/listeners/test_discovery.rb +89 -0
  50. data/lib/ruby_lsp/listeners/test_style.rb +167 -90
  51. data/lib/ruby_lsp/node_context.rb +12 -39
  52. data/lib/ruby_lsp/rbs_document.rb +9 -7
  53. data/lib/ruby_lsp/requests/code_action_resolve.rb +63 -59
  54. data/lib/ruby_lsp/requests/code_actions.rb +14 -26
  55. data/lib/ruby_lsp/requests/code_lens.rb +20 -19
  56. data/lib/ruby_lsp/requests/completion.rb +7 -20
  57. data/lib/ruby_lsp/requests/completion_resolve.rb +6 -6
  58. data/lib/ruby_lsp/requests/definition.rb +7 -17
  59. data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
  60. data/lib/ruby_lsp/requests/discover_tests.rb +18 -5
  61. data/lib/ruby_lsp/requests/document_highlight.rb +5 -15
  62. data/lib/ruby_lsp/requests/document_link.rb +6 -17
  63. data/lib/ruby_lsp/requests/document_symbol.rb +5 -8
  64. data/lib/ruby_lsp/requests/folding_ranges.rb +7 -15
  65. data/lib/ruby_lsp/requests/formatting.rb +6 -9
  66. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +85 -0
  67. data/lib/ruby_lsp/requests/hover.rb +10 -20
  68. data/lib/ruby_lsp/requests/inlay_hints.rb +6 -17
  69. data/lib/ruby_lsp/requests/on_type_formatting.rb +32 -40
  70. data/lib/ruby_lsp/requests/prepare_rename.rb +4 -9
  71. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +5 -15
  72. data/lib/ruby_lsp/requests/range_formatting.rb +5 -6
  73. data/lib/ruby_lsp/requests/references.rb +9 -53
  74. data/lib/ruby_lsp/requests/rename.rb +20 -46
  75. data/lib/ruby_lsp/requests/request.rb +8 -19
  76. data/lib/ruby_lsp/requests/selection_ranges.rb +6 -6
  77. data/lib/ruby_lsp/requests/semantic_highlighting.rb +16 -35
  78. data/lib/ruby_lsp/requests/show_syntax_tree.rb +7 -8
  79. data/lib/ruby_lsp/requests/signature_help.rb +8 -26
  80. data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
  81. data/lib/ruby_lsp/requests/support/common.rb +15 -55
  82. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +27 -35
  83. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +11 -14
  84. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +22 -34
  85. data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
  86. data/lib/ruby_lsp/requests/support/sorbet.rb +29 -38
  87. data/lib/ruby_lsp/requests/support/source_uri.rb +20 -32
  88. data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +12 -19
  89. data/lib/ruby_lsp/requests/support/test_item.rb +16 -14
  90. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +5 -6
  91. data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
  92. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +5 -5
  93. data/lib/ruby_lsp/response_builders/document_symbol.rb +14 -19
  94. data/lib/ruby_lsp/response_builders/hover.rb +11 -14
  95. data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
  96. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +60 -88
  97. data/lib/ruby_lsp/response_builders/signature_help.rb +5 -6
  98. data/lib/ruby_lsp/response_builders/test_collection.rb +43 -10
  99. data/lib/ruby_lsp/ruby_document.rb +24 -92
  100. data/lib/ruby_lsp/scope.rb +7 -11
  101. data/lib/ruby_lsp/scripts/compose_bundle.rb +6 -4
  102. data/lib/ruby_lsp/server.rb +182 -99
  103. data/lib/ruby_lsp/setup_bundler.rb +65 -60
  104. data/lib/ruby_lsp/static_docs.rb +11 -7
  105. data/lib/ruby_lsp/store.rb +29 -47
  106. data/lib/ruby_lsp/test_helper.rb +2 -12
  107. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +191 -0
  108. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +105 -0
  109. data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +94 -0
  110. data/lib/ruby_lsp/type_inferrer.rb +13 -14
  111. data/lib/ruby_lsp/utils.rb +92 -83
  112. metadata +9 -3
@@ -4,32 +4,65 @@
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
+ #: Array[Interface::CodeLens]
12
+ attr_reader :code_lens
13
+
14
+ #: -> void
15
15
  def initialize
16
16
  super
17
- @items = T.let({}, T::Hash[String, ResponseType])
17
+ @items = {} #: Hash[String, ResponseType]
18
+ @code_lens = [] #: Array[Interface::CodeLens]
18
19
  end
19
20
 
20
- sig { params(item: ResponseType).void }
21
+ #: (ResponseType item) -> void
21
22
  def add(item)
22
- raise DuplicateIdError, "TestItem ID is already in use" if @items.key?(item.id)
23
-
24
23
  @items[item.id] = item
25
24
  end
26
25
 
27
- sig { params(id: String).returns(T.nilable(ResponseType)) }
26
+ #: (ResponseType item) -> void
27
+ def add_code_lens(item)
28
+ range = item.range
29
+ arguments = [item.uri.to_standardized_path, item.id]
30
+
31
+ @code_lens << Interface::CodeLens.new(
32
+ range: range,
33
+ command: Interface::Command.new(
34
+ title: "▶ Run",
35
+ command: "rubyLsp.runTest",
36
+ arguments: arguments,
37
+ ),
38
+ )
39
+
40
+ @code_lens << Interface::CodeLens.new(
41
+ range: range,
42
+ command: Interface::Command.new(
43
+ title: "▶ Run In Terminal",
44
+ command: "rubyLsp.runTestInTerminal",
45
+ arguments: arguments,
46
+ ),
47
+ )
48
+
49
+ @code_lens << Interface::CodeLens.new(
50
+ range: range,
51
+ command: Interface::Command.new(
52
+ title: "⚙ Debug",
53
+ command: "rubyLsp.debugTest",
54
+ arguments: arguments,
55
+ ),
56
+ )
57
+ end
58
+
59
+ #: (String id) -> ResponseType?
28
60
  def [](id)
29
61
  @items[id]
30
62
  end
31
63
 
32
- sig { override.returns(T::Array[ResponseType]) }
64
+ # @override
65
+ #: -> Array[ResponseType]
33
66
  def response
34
67
  @items.values
35
68
  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 } }
@@ -24,49 +23,16 @@ module RubyLsp
24
23
  :private_class_method,
25
24
  ].freeze
26
25
 
27
- class SorbetLevel < T::Enum
28
- enums do
29
- None = new("none")
30
- Ignore = new("ignore")
31
- False = new("false")
32
- True = new("true")
33
- Strict = new("strict")
34
- end
35
- end
36
-
37
26
  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
27
+ #: (Prism::Node node, Integer char_position, code_units_cache: (^(Integer arg0) -> Integer | Prism::CodeUnitsCache), ?node_types: Array[singleton(Prism::Node)]) -> NodeContext
51
28
  def locate(node, char_position, code_units_cache:, node_types: [])
52
- queue = T.let(node.child_nodes.compact, T::Array[T.nilable(Prism::Node)])
29
+ queue = node.child_nodes.compact #: Array[Prism::Node?]
53
30
  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
- )
31
+ parent = nil #: Prism::Node?
32
+ nesting_nodes = [] #: Array[(Prism::ClassNode | Prism::ModuleNode | Prism::SingletonClassNode | Prism::DefNode | Prism::BlockNode | Prism::LambdaNode | Prism::ProgramNode)] # rubocop:disable Layout/LineLength
67
33
 
68
34
  nesting_nodes << node if node.is_a?(Prism::ProgramNode)
69
- call_node = T.let(nil, T.nilable(Prism::CallNode))
35
+ call_node = nil #: Prism::CallNode?
70
36
 
71
37
  until queue.empty?
72
38
  candidate = queue.shift
@@ -77,7 +43,7 @@ module RubyLsp
77
43
  # Add the next child_nodes to the queue to be processed. The order here is important! We want to move in the
78
44
  # same order as the visiting mechanism, which means searching the child nodes before moving on to the next
79
45
  # sibling
80
- T.unsafe(queue).unshift(*candidate.child_nodes)
46
+ queue.unshift(*candidate.child_nodes)
81
47
 
82
48
  # Skip if the current node doesn't cover the desired position
83
49
  loc = candidate.location
@@ -150,24 +116,18 @@ module RubyLsp
150
116
  end
151
117
  end
152
118
 
153
- sig do
154
- returns(T.any(
155
- T.proc.params(arg0: Integer).returns(Integer),
156
- Prism::CodeUnitsCache,
157
- ))
158
- end
119
+ #: (^(Integer arg0) -> Integer | Prism::CodeUnitsCache)
159
120
  attr_reader :code_units_cache
160
121
 
161
- sig { params(source: String, version: Integer, uri: URI::Generic, global_state: GlobalState).void }
122
+ #: (source: String, version: Integer, uri: URI::Generic, global_state: GlobalState) -> void
162
123
  def initialize(source:, version:, uri:, global_state:)
163
124
  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
- ))
125
+ @code_units_cache = @parse_result
126
+ .code_units_cache(@encoding) #: (^(Integer arg0) -> Integer | Prism::CodeUnitsCache)
168
127
  end
169
128
 
170
- sig { override.returns(T::Boolean) }
129
+ # @override
130
+ #: -> bool
171
131
  def parse!
172
132
  return false unless @needs_parsing
173
133
 
@@ -177,47 +137,24 @@ module RubyLsp
177
137
  true
178
138
  end
179
139
 
180
- sig { override.returns(T::Boolean) }
140
+ # @override
141
+ #: -> bool
181
142
  def syntax_error?
182
143
  @parse_result.failure?
183
144
  end
184
145
 
185
- sig { override.returns(LanguageId) }
146
+ # @override
147
+ #: -> Symbol
186
148
  def language_id
187
- LanguageId::Ruby
149
+ :ruby
188
150
  end
189
151
 
190
- sig { returns(SorbetLevel) }
191
- def sorbet_level
192
- sigil = parse_result.magic_comments.find do |comment|
193
- comment.key == "typed"
194
- end&.value
195
-
196
- case sigil
197
- when "ignore"
198
- SorbetLevel::Ignore
199
- when "false"
200
- SorbetLevel::False
201
- when "true"
202
- SorbetLevel::True
203
- when "strict", "strong"
204
- SorbetLevel::Strict
205
- else
206
- SorbetLevel::None
207
- end
208
- end
209
-
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
152
+ #: (Hash[Symbol, untyped] range, ?node_types: Array[singleton(Prism::Node)]) -> Prism::Node?
216
153
  def locate_first_within_range(range, node_types: [])
217
154
  start_position, end_position = find_index_by_position(range[:start], range[:end])
218
155
 
219
156
  desired_range = (start_position...end_position)
220
- queue = T.let(@parse_result.value.child_nodes.compact, T::Array[T.nilable(Prism::Node)])
157
+ queue = @parse_result.value.child_nodes.compact #: Array[Prism::Node?]
221
158
 
222
159
  until queue.empty?
223
160
  candidate = queue.shift
@@ -228,7 +165,7 @@ module RubyLsp
228
165
  # Add the next child_nodes to the queue to be processed. The order here is important! We want to move in the
229
166
  # same order as the visiting mechanism, which means searching the child nodes before moving on to the next
230
167
  # sibling
231
- T.unsafe(queue).unshift(*candidate.child_nodes)
168
+ queue.unshift(*candidate.child_nodes)
232
169
 
233
170
  # Skip if the current node doesn't cover the desired position
234
171
  loc = candidate.location
@@ -240,12 +177,7 @@ module RubyLsp
240
177
  end
241
178
  end
242
179
 
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
180
+ #: (Hash[Symbol, untyped] position, ?node_types: Array[singleton(Prism::Node)]) -> NodeContext
249
181
  def locate_node(position, node_types: [])
250
182
  char_position, _ = find_index_by_position(position)
251
183
 
@@ -257,7 +189,7 @@ module RubyLsp
257
189
  )
258
190
  end
259
191
 
260
- sig { returns(T::Boolean) }
192
+ #: -> bool
261
193
  def should_index?
262
194
  # This method controls when we should index documents. If there's no recent edit and the document has just been
263
195
  # opened, we need to index it
@@ -268,7 +200,7 @@ module RubyLsp
268
200
 
269
201
  private
270
202
 
271
- sig { returns(T::Boolean) }
203
+ #: -> bool
272
204
  def last_edit_may_change_declarations?
273
205
  case @last_edit
274
206
  when Delete
@@ -282,7 +214,7 @@ module RubyLsp
282
214
  end
283
215
  end
284
216
 
285
- sig { params(position: T::Hash[Symbol, Integer]).returns(T::Boolean) }
217
+ #: (Hash[Symbol, Integer] position) -> bool
286
218
  def position_may_impact_declarations?(position)
287
219
  node_context = locate_node(position)
288
220
  node_at_edit = node_context.node
@@ -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
@@ -13,8 +13,10 @@ def compose(raw_initialize)
13
13
  workspace_path ||= Dir.pwd
14
14
 
15
15
  env = RubyLsp::SetupBundler.new(workspace_path, launcher: true).setup!
16
- File.write(
17
- File.join(".ruby-lsp", "bundle_env"),
18
- env.map { |k, v| "#{k}=#{v}" }.join("\n"),
19
- )
16
+
17
+ File.open(File.join(".ruby-lsp", "bundle_env"), "w") do |f|
18
+ f.flock(File::LOCK_EX)
19
+ f.write(env.map { |k, v| "#{k}=#{v}" }.join("\n"))
20
+ f.flush
21
+ end
20
22
  end