ruby-lsp 0.23.22 → 0.23.24

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48c7e1cdc0e7f0a31cbc69002bf6a6c3dea0779272757ee40ae90e4199199446
4
- data.tar.gz: 1cd0d4a426ed4b1c44540e9e3344f73623f0ea0193374cab8faa727528474bf2
3
+ metadata.gz: f36abe0931e1e5dede4e640d28315481026b16a5087021dcf8567dc97a1b7e2f
4
+ data.tar.gz: 5f7f3213e48ce66c7af5e67444ac6031d68269fe938c540c5b86b9c193a3c8c3
5
5
  SHA512:
6
- metadata.gz: ac87c3a6dcc52b2696076d9793b42f03f56a4e0fbe258cc20f09502bbb289f91acccb3593ebfd36d61b5eeb0ec0bc3ab697acc332b61889fd256db2600029eca
7
- data.tar.gz: be146b667f656ddb1103756a4cf79bd294981fa5f3d0cebc38e44498168799b14941c1768e9f030e80d4f4f7e8c4e4b0107e9cbaf694184ddc037824a05a2f1f
6
+ metadata.gz: 5242bc7d2fa9a17e49b0196161af27aaf99f57f45d1c5c07017c07e6ea5b0b572982fb1880020d727aa3db3c634a0336c811dcc874ff7cd507004fdb64ce560b
7
+ data.tar.gz: 13c106377644314b1854aa8cb0a3a6401c071ebc089a7aaa045b02503bc73569d3cda3e99b0897ebf6726606d66832dd652fb9aff171d68d95cf7374482912b9
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.23.22
1
+ 0.23.24
@@ -83,8 +83,13 @@ begin
83
83
  # This Marshal load can only happen after requiring Bundler because it will load a custom error class from Bundler
84
84
  # itself. If we try to load before requiring, the class will not be defined and loading will fail
85
85
  error_path = File.join(".ruby-lsp", "install_error")
86
- install_error = if File.exist?(error_path)
87
- Marshal.load(File.read(error_path))
86
+ install_error = begin
87
+ Marshal.load(File.read(error_path)) if File.exist?(error_path)
88
+ rescue ArgumentError
89
+ # The class we tried to load is not defined. This might happen when the user upgrades Bundler and new error
90
+ # classes are introduced or removed
91
+ File.delete(error_path)
92
+ nil
88
93
  end
89
94
 
90
95
  Bundler.setup
@@ -254,7 +254,7 @@ module RubyIndexer
254
254
  case message
255
255
  when :private_constant
256
256
  handle_private_constant(node)
257
- when :attr_reader
257
+ when :attr_reader, :attr
258
258
  handle_attribute(node, reader: true, writer: false)
259
259
  when :attr_writer
260
260
  handle_attribute(node, reader: false, writer: true)
@@ -2,11 +2,8 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module RubyIndexer
5
+ # @abstract
5
6
  class Enhancement
6
- extend T::Helpers
7
-
8
- abstract!
9
-
10
7
  @enhancements = [] #: Array[Class[Enhancement]]
11
8
 
12
9
  class << self
@@ -98,11 +98,8 @@ module RubyIndexer
98
98
  end
99
99
  end
100
100
 
101
+ # @abstract
101
102
  class ModuleOperation
102
- extend T::Helpers
103
-
104
- abstract!
105
-
106
103
  #: String
107
104
  attr_reader :module_name
108
105
 
@@ -115,11 +112,8 @@ module RubyIndexer
115
112
  class Include < ModuleOperation; end
116
113
  class Prepend < ModuleOperation; end
117
114
 
115
+ # @abstract
118
116
  class Namespace < Entry
119
- extend T::Helpers
120
-
121
- abstract!
122
-
123
117
  #: Array[String]
124
118
  attr_reader :nesting
125
119
 
@@ -191,11 +185,8 @@ module RubyIndexer
191
185
  class Constant < Entry
192
186
  end
193
187
 
188
+ # @abstract
194
189
  class Parameter
195
- extend T::Helpers
196
-
197
- abstract!
198
-
199
190
  # Name includes just the name of the parameter, excluding symbols like splats
200
191
  #: Symbol
201
192
  attr_reader :name
@@ -289,12 +280,8 @@ module RubyIndexer
289
280
  end
290
281
  end
291
282
 
283
+ # @abstract
292
284
  class Member < Entry
293
- extend T::Sig
294
- extend T::Helpers
295
-
296
- abstract!
297
-
298
285
  #: Entry::Namespace?
299
286
  attr_reader :owner
300
287
 
@@ -305,7 +292,8 @@ module RubyIndexer
305
292
  @owner = owner
306
293
  end
307
294
 
308
- sig { abstract.returns(T::Array[Entry::Signature]) }
295
+ # @abstract
296
+ #: -> Array[Signature]
309
297
  def signatures; end
310
298
 
311
299
  #: -> String
@@ -818,11 +818,22 @@ module RubyIndexer
818
818
  )
819
819
  # Find the first class entry that has a parent class. Notice that if the developer makes a mistake and inherits
820
820
  # from two different classes in different files, we simply ignore it
821
- superclass = if singleton_levels > 0
822
- self[attached_class_name]&.find { |n| n.is_a?(Entry::Class) && n.parent_class }
823
- else
824
- namespace_entries.find { |n| n.is_a?(Entry::Class) && n.parent_class }
825
- end #: as Entry::Class?
821
+ possible_parents = singleton_levels > 0 ? self[attached_class_name] : namespace_entries
822
+ superclass = nil #: Entry::Class?
823
+
824
+ possible_parents&.each do |n|
825
+ # Ignore non class entries
826
+ next unless n.is_a?(Entry::Class)
827
+
828
+ parent_class = n.parent_class
829
+ next unless parent_class
830
+
831
+ # Always set the superclass, but break early if we found one that isn't `::Object` (meaning we found an explicit
832
+ # parent class and not the implicit default). Note that when setting different parents to the same class, which
833
+ # is invalid, we pick whatever is the first one we find
834
+ superclass = n
835
+ break if parent_class != "::Object"
836
+ end
826
837
 
827
838
  if superclass
828
839
  # If the user makes a mistake and creates a class that inherits from itself, this method would throw a stack
@@ -3,11 +3,8 @@
3
3
 
4
4
  module RubyIndexer
5
5
  class ReferenceFinder
6
- class Target
7
- extend T::Helpers
8
-
9
- abstract!
10
- end
6
+ # @abstract
7
+ class Target; end
11
8
 
12
9
  class ConstTarget < Target
13
10
  #: String
@@ -35,10 +32,14 @@ module RubyIndexer
35
32
  #: String
36
33
  attr_reader :name
37
34
 
38
- #: (String name) -> void
39
- def initialize(name)
35
+ #: Array[String]
36
+ attr_reader :owner_ancestors
37
+
38
+ #: (String name, Array[String] owner_ancestors) -> void
39
+ def initialize(name, owner_ancestors)
40
40
  super()
41
41
  @name = name
42
+ @owner_ancestors = owner_ancestors
42
43
  end
43
44
  end
44
45
 
@@ -325,7 +326,10 @@ module RubyIndexer
325
326
  def collect_instance_variable_references(name, location, declaration)
326
327
  return unless @target.is_a?(InstanceVariableTarget) && name == @target.name
327
328
 
328
- @references << Reference.new(name, location, declaration: declaration)
329
+ receiver_type = Index.actual_nesting(@stack, nil).join("::")
330
+ if @target.owner_ancestors.include?(receiver_type)
331
+ @references << Reference.new(name, location, declaration: declaration)
332
+ end
329
333
  end
330
334
  end
331
335
  end
@@ -728,6 +728,30 @@ module RubyIndexer
728
728
  assert_equal(["A", "ALIAS"], @index.linearized_ancestors_of("A"))
729
729
  end
730
730
 
731
+ def test_linearizing_ancestors_for_classes_with_overridden_parents
732
+ index(<<~RUBY)
733
+ # Find the re-open of a class first, without specifying a parent
734
+ class Child
735
+ end
736
+
737
+ # Now, find the actual definition of the class, which includes a parent
738
+ class Parent; end
739
+ class Child < Parent
740
+ end
741
+ RUBY
742
+
743
+ assert_equal(
744
+ [
745
+ "Child",
746
+ "Parent",
747
+ "Object",
748
+ "Kernel",
749
+ "BasicObject",
750
+ ],
751
+ @index.linearized_ancestors_of("Child"),
752
+ )
753
+ end
754
+
731
755
  def test_resolving_an_inherited_method
732
756
  index(<<~RUBY)
733
757
  module Foo
@@ -950,6 +950,16 @@ module RubyIndexer
950
950
  assert_predicate(entry, :public?)
951
951
  end
952
952
 
953
+ def test_handling_attr
954
+ index(<<~RUBY)
955
+ class Foo
956
+ attr :bar
957
+ end
958
+ RUBY
959
+
960
+ assert_entry("bar", Entry::Accessor, "/fake/path/foo.rb:1-8:1-11")
961
+ end
962
+
953
963
  private
954
964
 
955
965
  #: (Entry::Method entry, String call_string) -> void
@@ -216,22 +216,43 @@ module RubyIndexer
216
216
  assert_equal(11, refs[2].location.start_line)
217
217
  end
218
218
 
219
- def test_finds_instance_variable_read_references
220
- refs = find_instance_variable_references("@foo", <<~RUBY)
219
+ def test_finds_instance_variable_references
220
+ refs = find_instance_variable_references("@name", ["Foo"], <<~RUBY)
221
221
  class Foo
222
- def foo
223
- @foo
222
+ def initialize
223
+ @name = "foo"
224
+ end
225
+ def name
226
+ @name
227
+ end
228
+ def name_capital
229
+ @name[0]
230
+ end
231
+ end
232
+
233
+ class Bar
234
+ def initialize
235
+ @name = "foo"
236
+ end
237
+ def name
238
+ @name
224
239
  end
225
240
  end
226
241
  RUBY
227
- assert_equal(1, refs.size)
242
+ assert_equal(3, refs.size)
228
243
 
229
- assert_equal("@foo", refs[0].name)
244
+ assert_equal("@name", refs[0].name)
230
245
  assert_equal(3, refs[0].location.start_line)
246
+
247
+ assert_equal("@name", refs[1].name)
248
+ assert_equal(6, refs[1].location.start_line)
249
+
250
+ assert_equal("@name", refs[2].name)
251
+ assert_equal(9, refs[2].location.start_line)
231
252
  end
232
253
 
233
254
  def test_finds_instance_variable_write_references
234
- refs = find_instance_variable_references("@foo", <<~RUBY)
255
+ refs = find_instance_variable_references("@foo", ["Foo"], <<~RUBY)
235
256
  class Foo
236
257
  def write
237
258
  @foo = 1
@@ -252,26 +273,70 @@ module RubyIndexer
252
273
  assert_equal(7, refs[4].location.start_line)
253
274
  end
254
275
 
255
- def test_finds_instance_variable_references_ignore_context
256
- refs = find_instance_variable_references("@name", <<~RUBY)
257
- class Foo
276
+ def test_finds_instance_variable_references_in_owner_ancestors
277
+ refs = find_instance_variable_references("@name", ["Foo", "Base", "Top", "Parent"], <<~RUBY)
278
+ module Base
279
+ def change_name(name)
280
+ @name = name
281
+ end
258
282
  def name
283
+ @name
284
+ end
285
+
286
+ module ::Top
287
+ def name
288
+ @name
289
+ end
290
+ end
291
+ end
292
+
293
+ class Parent
294
+ def initialize
295
+ @name = "parent"
296
+ end
297
+ def name_capital
298
+ @name[0]
299
+ end
300
+ end
301
+
302
+ class Foo < Parent
303
+ include Base
304
+ def initialize
259
305
  @name = "foo"
260
306
  end
307
+ def name
308
+ @name
309
+ end
261
310
  end
311
+
262
312
  class Bar
263
313
  def name
264
314
  @name = "bar"
265
315
  end
266
316
  end
267
317
  RUBY
268
- assert_equal(2, refs.size)
318
+ assert_equal(7, refs.size)
269
319
 
270
320
  assert_equal("@name", refs[0].name)
271
321
  assert_equal(3, refs[0].location.start_line)
272
322
 
273
323
  assert_equal("@name", refs[1].name)
274
- assert_equal(8, refs[1].location.start_line)
324
+ assert_equal(6, refs[1].location.start_line)
325
+
326
+ assert_equal("@name", refs[2].name)
327
+ assert_equal(11, refs[2].location.start_line)
328
+
329
+ assert_equal("@name", refs[3].name)
330
+ assert_equal(18, refs[3].location.start_line)
331
+
332
+ assert_equal("@name", refs[4].name)
333
+ assert_equal(21, refs[4].location.start_line)
334
+
335
+ assert_equal("@name", refs[5].name)
336
+ assert_equal(28, refs[5].location.start_line)
337
+
338
+ assert_equal("@name", refs[6].name)
339
+ assert_equal(31, refs[6].location.start_line)
275
340
  end
276
341
 
277
342
  def test_accounts_for_reopened_classes
@@ -310,8 +375,8 @@ module RubyIndexer
310
375
  find_references(target, source)
311
376
  end
312
377
 
313
- def find_instance_variable_references(instance_variable_name, source)
314
- target = ReferenceFinder::InstanceVariableTarget.new(instance_variable_name)
378
+ def find_instance_variable_references(instance_variable_name, owner_ancestors, source)
379
+ target = ReferenceFinder::InstanceVariableTarget.new(instance_variable_name, owner_ancestors)
315
380
  find_references(target, source)
316
381
  end
317
382
 
@@ -19,12 +19,8 @@ module RubyLsp
19
19
  # end
20
20
  # end
21
21
  # ```
22
+ # @abstract
22
23
  class Addon
23
- extend T::Sig
24
- extend T::Helpers
25
-
26
- abstract!
27
-
28
24
  @addons = [] #: Array[Addon]
29
25
  @addon_classes = [] #: Array[singleton(Addon)]
30
26
  # Add-on instances that have declared a handler to accept file watcher events
@@ -178,21 +174,25 @@ module RubyLsp
178
174
 
179
175
  # Each add-on should implement `MyAddon#activate` and use to perform any sort of initialization, such as
180
176
  # reading information into memory or even spawning a separate process
181
- sig { abstract.params(global_state: GlobalState, outgoing_queue: Thread::Queue).void }
177
+ # @abstract
178
+ #: (GlobalState, Thread::Queue) -> void
182
179
  def activate(global_state, outgoing_queue); end
183
180
 
184
181
  # Each add-on should implement `MyAddon#deactivate` and use to perform any clean up, like shutting down a
185
182
  # child process
186
- sig { abstract.void }
183
+ # @abstract
184
+ #: -> void
187
185
  def deactivate; end
188
186
 
189
187
  # Add-ons should override the `name` method to return the add-on name
190
- sig { abstract.returns(String) }
188
+ # @abstract
189
+ #: -> String
191
190
  def name; end
192
191
 
193
192
  # Add-ons should override the `version` method to return a semantic version string representing the add-on's
194
193
  # version. This is used for compatibility checks
195
- sig { abstract.returns(String) }
194
+ # @abstract
195
+ #: -> String
196
196
  def version; end
197
197
 
198
198
  # Handle a response from a window/showMessageRequest request. Add-ons must include the addon_name as part of the
@@ -2,12 +2,8 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module RubyLsp
5
+ # @abstract
5
6
  class BaseServer
6
- extend T::Sig
7
- extend T::Helpers
8
-
9
- abstract!
10
-
11
7
  #: (**untyped options) -> void
12
8
  def initialize(**options)
13
9
  @test_mode = options[:test_mode] #: bool?
@@ -130,10 +126,12 @@ module RubyLsp
130
126
  @incoming_queue << message
131
127
  end
132
128
 
133
- sig { abstract.params(message: T::Hash[Symbol, T.untyped]).void }
129
+ # @abstract
130
+ #: (Hash[Symbol, untyped] message) -> void
134
131
  def process_message(message); end
135
132
 
136
- sig { abstract.void }
133
+ # @abstract
134
+ #: -> void
137
135
  def shutdown; end
138
136
 
139
137
  #: (Integer id, String message, ?type: Integer) -> void
@@ -2,10 +2,9 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module RubyLsp
5
+ # @abstract
5
6
  #: [ParseResultType]
6
7
  class Document
7
- extend T::Sig
8
- extend T::Helpers
9
8
  extend T::Generic
10
9
 
11
10
  class LocationNotFoundError < StandardError; end
@@ -15,8 +14,6 @@ module RubyLsp
15
14
  MAXIMUM_CHARACTERS_FOR_EXPENSIVE_FEATURES = 100_000
16
15
  EMPTY_CACHE = Object.new.freeze #: Object
17
16
 
18
- abstract!
19
-
20
17
  #: ParseResultType
21
18
  attr_reader :parse_result
22
19
 
@@ -63,7 +60,8 @@ module RubyLsp
63
60
  self.class == other.class && uri == other.uri && @source == other.source
64
61
  end
65
62
 
66
- sig { abstract.returns(Symbol) }
63
+ # @abstract
64
+ #: -> Symbol
67
65
  def language_id; end
68
66
 
69
67
  #: [T] (String request_name) { (Document[ParseResultType] document) -> T } -> T
@@ -122,10 +120,12 @@ module RubyLsp
122
120
  end
123
121
 
124
122
  # Returns `true` if the document was parsed and `false` if nothing needed parsing
125
- sig { abstract.returns(T::Boolean) }
123
+ # @abstract
124
+ #: -> bool
126
125
  def parse!; end
127
126
 
128
- sig { abstract.returns(T::Boolean) }
127
+ # @abstract
128
+ #: -> bool
129
129
  def syntax_error?; end
130
130
 
131
131
  #: -> bool
@@ -150,12 +150,8 @@ module RubyLsp
150
150
  Scanner.new(@source, @encoding)
151
151
  end
152
152
 
153
+ # @abstract
153
154
  class Edit
154
- extend T::Sig
155
- extend T::Helpers
156
-
157
- abstract!
158
-
159
155
  #: Hash[Symbol, untyped]
160
156
  attr_reader :range
161
157
 
@@ -516,6 +516,14 @@ module RubyLsp
516
516
 
517
517
  entry_name = entry.name
518
518
  owner_name = entry.owner&.name
519
+ new_text = entry_name
520
+
521
+ if entry_name.end_with?("=")
522
+ method_name = entry_name.delete_suffix("=")
523
+
524
+ # For writer methods, format as assignment and prefix "self." when no receiver is specified
525
+ new_text = node.receiver.nil? ? "self.#{method_name} = " : "#{method_name} = "
526
+ end
519
527
 
520
528
  label_details = Interface::CompletionItemLabelDetails.new(
521
529
  description: entry.file_name,
@@ -525,7 +533,7 @@ module RubyLsp
525
533
  label: entry_name,
526
534
  filter_text: entry_name,
527
535
  label_details: label_details,
528
- text_edit: Interface::TextEdit.new(range: range, new_text: entry_name),
536
+ text_edit: Interface::TextEdit.new(range: range, new_text: new_text),
529
537
  kind: Constant::CompletionItemKind::METHOD,
530
538
  data: {
531
539
  owner_name: owner_name,
@@ -41,8 +41,20 @@ module RubyLsp
41
41
 
42
42
  #: (Prism::ClassNode) -> void
43
43
  def on_class_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
44
+ @spec_group_id_stack.pop
44
45
  super
46
+ end
47
+
48
+ #: (Prism::ModuleNode) -> void
49
+ def on_module_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
50
+ @spec_group_id_stack << nil
51
+ super
52
+ end
53
+
54
+ #: (Prism::ModuleNode) -> void
55
+ def on_module_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
45
56
  @spec_group_id_stack.pop
57
+ super
46
58
  end
47
59
 
48
60
  #: (Prism::CallNode) -> void
@@ -61,6 +73,12 @@ module RubyLsp
61
73
  def on_call_node_leave(node)
62
74
  return unless node.name == :describe && !node.receiver
63
75
 
76
+ current_group = @spec_group_id_stack.last
77
+ return unless current_group.is_a?(DescribeGroup)
78
+
79
+ description = extract_description(node)
80
+ return unless description && current_group.id.end_with?(description)
81
+
64
82
  @spec_group_id_stack.pop
65
83
  end
66
84
 
@@ -76,6 +94,8 @@ module RubyLsp
76
94
  return unless description
77
95
 
78
96
  parent = latest_group
97
+ return unless parent
98
+
79
99
  id = case parent
80
100
  when Requests::Support::TestItem
81
101
  "#{parent.id}::#{description}"
@@ -135,26 +155,50 @@ module RubyLsp
135
155
  end
136
156
  end
137
157
 
138
- #: -> (Requests::Support::TestItem | ResponseBuilders::TestCollection)
158
+ #: -> (Requests::Support::TestItem | ResponseBuilders::TestCollection)?
139
159
  def latest_group
160
+ # If we haven't found anything yet, then return the response builder
140
161
  return @response_builder if @spec_group_id_stack.compact.empty?
162
+ # If we found something that isn't a group last, then we're inside a random module or class, but not a spec
163
+ # group
164
+ return unless @spec_group_id_stack.last
141
165
 
142
- first_class_index = @spec_group_id_stack.rindex { |i| i.is_a?(ClassGroup) } || 0
143
- first_class = @spec_group_id_stack[0] #: as !nil
144
- item = @response_builder[first_class.id] #: as !nil
166
+ # Specs using at least one class as a group require special handling
167
+ closest_class_index = @spec_group_id_stack.rindex { |i| i.is_a?(ClassGroup) }
145
168
 
146
- # Descend into child items from the beginning all the way to the latest class group, ignoring describes
147
- @spec_group_id_stack[1..first_class_index] #: as !nil
148
- .each do |group|
149
- next unless group.is_a?(ClassGroup)
169
+ if closest_class_index
170
+ first_class_index = @spec_group_id_stack.index { |i| i.is_a?(ClassGroup) } #: as !nil
171
+ first_class = @spec_group_id_stack[first_class_index] #: as !nil
172
+ item = @response_builder[first_class.id] #: as !nil
150
173
 
151
- item = item[group.id] #: as !nil
174
+ # Descend into child items from the beginning all the way to the latest class group, ignoring describes
175
+ @spec_group_id_stack[first_class_index + 1..closest_class_index] #: as !nil
176
+ .each do |group|
177
+ next unless group.is_a?(ClassGroup)
178
+
179
+ item = item[group.id] #: as !nil
180
+ end
181
+
182
+ # From the class forward, we must take describes into account
183
+ @spec_group_id_stack[closest_class_index + 1..] #: as !nil
184
+ .each do |group|
185
+ next unless group
186
+
187
+ item = item[group.id] #: as !nil
188
+ end
189
+
190
+ return item
152
191
  end
153
192
 
154
- # From the class forward, we must take describes into account
155
- @spec_group_id_stack[first_class_index + 1..] #: as !nil
193
+ # Specs only using describes
194
+ first_group = @spec_group_id_stack.find { |i| i.is_a?(DescribeGroup) }
195
+ return unless first_group
196
+
197
+ item = @response_builder[first_group.id] #: as !nil
198
+
199
+ @spec_group_id_stack[1..] #: as !nil
156
200
  .each do |group|
157
- next unless group
201
+ next unless group.is_a?(DescribeGroup)
158
202
 
159
203
  item = item[group.id] #: as !nil
160
204
  end
@@ -3,10 +3,8 @@
3
3
 
4
4
  module RubyLsp
5
5
  module Listeners
6
+ # @abstract
6
7
  class TestDiscovery
7
- extend T::Helpers
8
- abstract!
9
-
10
8
  include Requests::Support::Common
11
9
 
12
10
  DYNAMIC_REFERENCE_MARKER = "<dynamic_reference>"
@@ -92,7 +92,7 @@ module RubyLsp
92
92
  #: (String, Hash[String, Hash[Symbol, untyped]]) -> String
93
93
  def handle_minitest_groups(file_path, groups_and_examples)
94
94
  regexes = groups_and_examples.flat_map do |group, info|
95
- examples = info[:examples].map { |e| e.gsub(/test_\d{4}/, "test_\\d{4}") }
95
+ examples = info[:examples].map { |e| Shellwords.escape(e).gsub(/test_\d{4}/, "test_\\d{4}") }
96
96
  group_regex = Shellwords.escape(group).gsub(
97
97
  Shellwords.escape(TestDiscovery::DYNAMIC_REFERENCE_MARKER),
98
98
  ".*",
@@ -18,13 +18,15 @@ module RubyLsp
18
18
  end
19
19
  end
20
20
 
21
- #: (GlobalState global_state, URI::Generic uri, Prism::Dispatcher dispatcher) -> void
22
- def initialize(global_state, uri, dispatcher)
21
+ #: (GlobalState, RubyDocument | ERBDocument, Prism::Dispatcher) -> void
22
+ def initialize(global_state, document, dispatcher)
23
23
  @response_builder = ResponseBuilders::CollectionResponseBuilder
24
24
  .new #: ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens]
25
25
  super()
26
26
 
27
+ @document = document
27
28
  @test_builder = ResponseBuilders::TestCollection.new #: ResponseBuilders::TestCollection
29
+ uri = document.uri
28
30
 
29
31
  if global_state.enabled_feature?(:fullTestDiscovery)
30
32
  Listeners::TestStyle.new(@test_builder, global_state, dispatcher, uri)
@@ -45,6 +47,7 @@ module RubyLsp
45
47
  # @override
46
48
  #: -> Array[Interface::CodeLens]
47
49
  def perform
50
+ @document.cache_set("rubyLsp/discoverTests", @test_builder.response)
48
51
  @response_builder.response + @test_builder.code_lens
49
52
  end
50
53
  end
@@ -101,7 +101,11 @@ module RubyLsp
101
101
  Prism::InstanceVariableReadNode,
102
102
  Prism::InstanceVariableTargetNode,
103
103
  Prism::InstanceVariableWriteNode
104
- RubyIndexer::ReferenceFinder::InstanceVariableTarget.new(target_node.name.to_s)
104
+ receiver_type = @global_state.type_inferrer.infer_receiver_type(node_context)
105
+ return unless receiver_type
106
+
107
+ ancestors = @global_state.index.linearized_ancestors_of(receiver_type.name)
108
+ RubyIndexer::ReferenceFinder::InstanceVariableTarget.new(target_node.name.to_s, ancestors)
105
109
  when Prism::CallNode, Prism::DefNode
106
110
  RubyIndexer::ReferenceFinder::MethodTarget.new(target_node.name.to_s)
107
111
  end
@@ -3,15 +3,12 @@
3
3
 
4
4
  module RubyLsp
5
5
  module Requests
6
+ # @abstract
6
7
  class Request
7
- extend T::Helpers
8
- extend T::Sig
9
-
10
8
  class InvalidFormatter < StandardError; end
11
9
 
12
- abstract!
13
-
14
- sig { abstract.returns(T.anything) }
10
+ # @abstract
11
+ #: -> untyped
15
12
  def perform; end
16
13
 
17
14
  private
@@ -4,13 +4,11 @@
4
4
  module RubyLsp
5
5
  module Requests
6
6
  module Support
7
+ # @requires_ancestor: Kernel
7
8
  module Common
8
9
  # WARNING: Methods in this class may be used by Ruby LSP add-ons such as
9
10
  # https://github.com/Shopify/ruby-lsp-rails, or add-ons by created by developers outside of Shopify, so be
10
11
  # cautious of changing anything.
11
- extend T::Helpers
12
-
13
- requires_ancestor { Kernel }
14
12
 
15
13
  #: (Prism::Node node) -> Interface::Range
16
14
  def range_from_node(node)
@@ -4,24 +4,19 @@
4
4
  module RubyLsp
5
5
  module Requests
6
6
  module Support
7
+ # Empty module to avoid the runtime component. This is an interface defined in sorbet/rbi/shims/ruby_lsp.rbi
8
+ # @interface
7
9
  module Formatter
8
- extend T::Sig
9
- extend T::Helpers
10
-
11
- interface!
12
-
13
- sig { abstract.params(uri: URI::Generic, document: RubyDocument).returns(T.nilable(String)) }
10
+ # @abstract
11
+ #: (URI::Generic, RubyLsp::RubyDocument) -> String?
14
12
  def run_formatting(uri, document); end
15
13
 
16
- sig { abstract.params(uri: URI::Generic, source: String, base_indentation: Integer).returns(T.nilable(String)) }
14
+ # @abstract
15
+ #: (URI::Generic, String, Integer) -> String?
17
16
  def run_range_formatting(uri, source, base_indentation); end
18
17
 
19
- sig do
20
- abstract.params(
21
- uri: URI::Generic,
22
- document: RubyDocument,
23
- ).returns(T.nilable(T::Array[Interface::Diagnostic]))
24
- end
18
+ # @abstract
19
+ #: (URI::Generic, RubyLsp::RubyDocument) -> Array[Interface::Diagnostic]?
25
20
  def run_diagnostic(uri, document); end
26
21
  end
27
22
  end
@@ -3,14 +3,12 @@
3
3
 
4
4
  module RubyLsp
5
5
  module ResponseBuilders
6
+ # @abstract
6
7
  class ResponseBuilder
7
- extend T::Sig
8
- extend T::Helpers
9
8
  extend T::Generic
10
9
 
11
- abstract!
12
-
13
- sig { abstract.returns(T.anything) }
10
+ # @abstract
11
+ #: -> top
14
12
  def response; end
15
13
  end
16
14
  end
@@ -94,16 +94,7 @@ module RubyLsp
94
94
  id: message[:id],
95
95
  response:
96
96
  Addon.addons.map do |addon|
97
- version_method = addon.method(:version)
98
-
99
- # If the add-on doesn't define a `version` method, we'd be calling the abstract method defined by
100
- # Sorbet, which would raise an error.
101
- # Therefore, we only call the method if it's defined by the add-on itself
102
- if version_method.owner != Addon
103
- version = addon.version
104
- end
105
-
106
- { name: addon.name, version: version, errored: addon.error? }
97
+ { name: addon.name, version: addon.version, errored: addon.error? }
107
98
  end,
108
99
  ),
109
100
  )
@@ -512,12 +503,12 @@ module RubyLsp
512
503
  @global_state.index.handle_change(uri) do |index|
513
504
  index.delete(uri, skip_require_paths_tree: true)
514
505
  RubyIndexer::DeclarationListener.new(index, dispatcher, parse_result, uri, collect_comments: true)
515
- code_lens = Requests::CodeLens.new(@global_state, uri, dispatcher)
506
+ code_lens = Requests::CodeLens.new(@global_state, document, dispatcher)
516
507
  dispatcher.dispatch(parse_result.value)
517
508
  end
518
509
  end
519
510
  else
520
- code_lens = Requests::CodeLens.new(@global_state, uri, dispatcher)
511
+ code_lens = Requests::CodeLens.new(@global_state, document, dispatcher)
521
512
  dispatcher.dispatch(parse_result.value)
522
513
  end
523
514
 
@@ -12,9 +12,9 @@ require "digest"
12
12
  require "time"
13
13
  require "uri"
14
14
 
15
- # This file is a script that will configure a composed bundle for the Ruby LSP. The composed bundle allows developers to use
16
- # the Ruby LSP without including the gem in their application's Gemfile while at the same time giving us access to the
17
- # exact locked versions of dependencies.
15
+ # This file is a script that will configure a composed bundle for the Ruby LSP. The composed bundle allows developers to
16
+ # use the Ruby LSP without including the gem in their application's Gemfile while at the same time giving us access to
17
+ # the exact locked versions of dependencies.
18
18
 
19
19
  Bundler.ui.level = :silent
20
20
 
@@ -4,13 +4,10 @@
4
4
  # NOTE: This module is intended to be used by addons for writing their own tests, so keep that in mind if changing.
5
5
 
6
6
  module RubyLsp
7
+ # @requires_ancestor: Kernel
7
8
  module TestHelper
8
9
  class TestError < StandardError; end
9
10
 
10
- extend T::Helpers
11
-
12
- requires_ancestor { Kernel }
13
-
14
11
  #: [T] (?String? source, ?URI::Generic uri, ?stub_no_typechecker: bool, ?load_addons: bool) { (RubyLsp::Server server, URI::Generic uri) -> T } -> T
15
12
  def with_server(source = nil, uri = Kernel.URI("file:///fake.rb"), stub_no_typechecker: false, load_addons: true,
16
13
  &block)
@@ -34,25 +34,22 @@ module RubyLsp
34
34
  BUNDLE_COMPOSE_FAILED_CODE = -33000
35
35
 
36
36
  # A notification to be sent to the client
37
+ # @abstract
37
38
  class Message
38
- extend T::Sig
39
- extend T::Helpers
40
-
41
39
  #: String
42
40
  attr_reader :method
43
41
 
44
42
  #: Object
45
43
  attr_reader :params
46
44
 
47
- abstract!
48
-
49
45
  #: (method: String, params: Object) -> void
50
46
  def initialize(method:, params:)
51
47
  @method = method
52
48
  @params = params
53
49
  end
54
50
 
55
- sig { abstract.returns(T::Hash[Symbol, T.untyped]) }
51
+ # @abstract
52
+ #: -> Hash[Symbol, untyped]
56
53
  def to_hash; end
57
54
  end
58
55
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lsp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.22
4
+ version: 0.23.24
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify