ruby-lsp 0.17.4 → 0.17.5

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: 71204369ec5201376f1af11875a2e1bf16df56a31719ea78932a7f5f6e9c7e5c
4
- data.tar.gz: d83e299ade275415fe4cac25abe78f7ee7ec622c47cc1699d42b3b772816fdba
3
+ metadata.gz: 30ab87e9f42251fafcf8c085d14272b6e0cc0fb6e6968db3fc4c304e92000c63
4
+ data.tar.gz: 305592ad82c3e41b72dff4c0a48ff60e6158ffba6d06b802844418c3873a6ef9
5
5
  SHA512:
6
- metadata.gz: f3ac517cb1c711dc1a5ddf2c4027f705e393e30028b9ae7063b18a5f51362fd4d7277607d19d8ca7a9a3c9146960bd612a02ed4a8933c8223a42daf3dfe5e63b
7
- data.tar.gz: 0c4408865d1894547aeedfc0441fa558a8281f54e7e26c38b619e67fd67bfc3bed49aa27dc06d8b89924c7ee8db4452b5cd2f810c0dfb01157eef127910b2182
6
+ metadata.gz: 3a38745ee99e4e62843f3bc2a698ec8c447d9bbb39091e158b2a64e36e46a1612962d1062635a007e13aabd3709733b9726a302ef680bd2881673e6abd48e038
7
+ data.tar.gz: 57b5327b0f17af4530b21ba3c51eb2bff13912e76df77f78284cd9644cebef252e1cbdd38b960de19cc64a68d9daf3788c6e78ef3b95b4bb5d6dc7f97e56c58f
data/README.md CHANGED
@@ -109,6 +109,10 @@ features. This is the mechanism that powers addons like
109
109
  - [Ruby LSP RSpec](https://github.com/st0012/ruby-lsp-rspec)
110
110
  - [Ruby LSP rubyfmt](https://github.com/jscharf/ruby-lsp-rubyfmt)
111
111
 
112
+ Additionally, some tools may include a Ruby LSP addon directly, like
113
+
114
+ - [Standard Ruby (from v1.39.1)](https://github.com/standardrb/standard/wiki/IDE:-vscode#using-ruby-lsp)
115
+
112
116
  Other community driven addons can be found in [rubygems](https://rubygems.org/search?query=name%3A+ruby-lsp) by
113
117
  searching for the `ruby-lsp` prefix.
114
118
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.17.4
1
+ 0.17.5
@@ -64,7 +64,8 @@ module RubyIndexer
64
64
  sig { params(node: Prism::ClassNode).void }
65
65
  def on_class_node_enter(node)
66
66
  @visibility_stack.push(Entry::Visibility::PUBLIC)
67
- name = node.constant_path.location.slice
67
+ constant_path = node.constant_path
68
+ name = constant_path.slice
68
69
 
69
70
  comments = collect_comments(node)
70
71
 
@@ -93,6 +94,7 @@ module RubyIndexer
93
94
  nesting,
94
95
  @file_path,
95
96
  node.location,
97
+ constant_path.location,
96
98
  comments,
97
99
  parent_class,
98
100
  )
@@ -112,12 +114,13 @@ module RubyIndexer
112
114
  sig { params(node: Prism::ModuleNode).void }
113
115
  def on_module_node_enter(node)
114
116
  @visibility_stack.push(Entry::Visibility::PUBLIC)
115
- name = node.constant_path.location.slice
117
+ constant_path = node.constant_path
118
+ name = constant_path.slice
116
119
 
117
120
  comments = collect_comments(node)
118
121
 
119
122
  nesting = name.start_with?("::") ? [name.delete_prefix("::")] : @stack + [name.delete_prefix("::")]
120
- entry = Entry::Module.new(nesting, @file_path, node.location, comments)
123
+ entry = Entry::Module.new(nesting, @file_path, node.location, constant_path.location, comments)
121
124
 
122
125
  @owner_stack << entry
123
126
  @index.add(entry)
@@ -145,9 +148,16 @@ module RubyIndexer
145
148
 
146
149
  if existing_entries
147
150
  entry = T.must(existing_entries.first)
148
- entry.update_singleton_information(node.location, collect_comments(node))
151
+ entry.update_singleton_information(node.location, expression.location, collect_comments(node))
149
152
  else
150
- entry = Entry::SingletonClass.new(@stack, @file_path, node.location, collect_comments(node), nil)
153
+ entry = Entry::SingletonClass.new(
154
+ @stack,
155
+ @file_path,
156
+ node.location,
157
+ expression.location,
158
+ collect_comments(node),
159
+ nil,
160
+ )
151
161
  @index.add(entry, skip_prefix_tree: true)
152
162
  end
153
163
 
@@ -297,25 +307,29 @@ module RubyIndexer
297
307
  method_name,
298
308
  @file_path,
299
309
  node.location,
310
+ node.name_loc,
300
311
  comments,
301
- list_params(node.parameters),
312
+ [Entry::Signature.new(list_params(node.parameters))],
302
313
  current_visibility,
303
314
  @owner_stack.last,
304
315
  ))
305
316
  when Prism::SelfNode
306
- singleton = singleton_klass
317
+ owner = @owner_stack.last
318
+
319
+ if owner
320
+ singleton = @index.existing_or_new_singleton_class(owner.name)
321
+
322
+ @index.add(Entry::Method.new(
323
+ method_name,
324
+ @file_path,
325
+ node.location,
326
+ node.name_loc,
327
+ comments,
328
+ [Entry::Signature.new(list_params(node.parameters))],
329
+ current_visibility,
330
+ singleton,
331
+ ))
307
332
 
308
- @index.add(Entry::Method.new(
309
- method_name,
310
- @file_path,
311
- node.location,
312
- comments,
313
- list_params(node.parameters),
314
- current_visibility,
315
- singleton,
316
- ))
317
-
318
- if singleton
319
333
  @owner_stack << singleton
320
334
  @stack << "<Class:#{@stack.last}>"
321
335
  end
@@ -393,7 +407,12 @@ module RubyIndexer
393
407
 
394
408
  # When instance variables are declared inside the class body, they turn into class instance variables rather than
395
409
  # regular instance variables
396
- owner = @inside_def ? @owner_stack.last : singleton_klass
410
+ owner = @owner_stack.last
411
+
412
+ if owner && !@inside_def
413
+ owner = @index.existing_or_new_singleton_class(owner.name)
414
+ end
415
+
397
416
  @index.add(Entry::InstanceVariable.new(name, @file_path, loc, collect_comments(node), owner))
398
417
  end
399
418
 
@@ -593,7 +612,8 @@ module RubyIndexer
593
612
  when :prepend
594
613
  owner.mixin_operations << Entry::Prepend.new(node.full_name)
595
614
  when :extend
596
- owner.mixin_operations << Entry::Extend.new(node.full_name)
615
+ singleton = @index.existing_or_new_singleton_class(owner.name)
616
+ singleton.mixin_operations << Entry::Include.new(node.full_name)
597
617
  end
598
618
  rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
599
619
  Prism::ConstantPathNode::MissingNodesInConstantPathError
@@ -689,24 +709,5 @@ module RubyIndexer
689
709
  :"(#{names_with_commas})"
690
710
  end
691
711
  end
692
-
693
- sig { returns(T.nilable(Entry::Class)) }
694
- def singleton_klass
695
- attached_class = @owner_stack.last
696
- return unless attached_class
697
-
698
- # Return the existing singleton class if available
699
- owner = T.cast(
700
- @index["#{attached_class.name}::<Class:#{attached_class.name}>"],
701
- T.nilable(T::Array[Entry::SingletonClass]),
702
- )
703
- return owner.first if owner
704
-
705
- # If not available, create the singleton class lazily
706
- nesting = @stack + ["<Class:#{@stack.last}>"]
707
- entry = Entry::SingletonClass.new(nesting, @file_path, attached_class.location, [], nil)
708
- @index.add(entry, skip_prefix_tree: true)
709
- entry
710
- end
711
712
  end
712
713
  end
@@ -22,6 +22,8 @@ module RubyIndexer
22
22
  sig { returns(RubyIndexer::Location) }
23
23
  attr_reader :location
24
24
 
25
+ alias_method :name_location, :location
26
+
25
27
  sig { returns(T::Array[String]) }
26
28
  attr_reader :comments
27
29
 
@@ -57,6 +59,16 @@ module RubyIndexer
57
59
  )
58
60
  end
59
61
 
62
+ sig { returns(T::Boolean) }
63
+ def public?
64
+ visibility == Visibility::PUBLIC
65
+ end
66
+
67
+ sig { returns(T::Boolean) }
68
+ def protected?
69
+ visibility == Visibility::PROTECTED
70
+ end
71
+
60
72
  sig { returns(T::Boolean) }
61
73
  def private?
62
74
  visibility == Visibility::PRIVATE
@@ -84,7 +96,6 @@ module RubyIndexer
84
96
 
85
97
  class Include < ModuleOperation; end
86
98
  class Prepend < ModuleOperation; end
87
- class Extend < ModuleOperation; end
88
99
 
89
100
  class Namespace < Entry
90
101
  extend T::Sig
@@ -95,20 +106,39 @@ module RubyIndexer
95
106
  sig { returns(T::Array[String]) }
96
107
  attr_reader :nesting
97
108
 
109
+ # Returns the location of the constant name, excluding the parent class or the body
110
+ sig { returns(Location) }
111
+ attr_reader :name_location
112
+
98
113
  sig do
99
114
  params(
100
115
  nesting: T::Array[String],
101
116
  file_path: String,
102
117
  location: T.any(Prism::Location, RubyIndexer::Location),
118
+ name_location: T.any(Prism::Location, Location),
103
119
  comments: T::Array[String],
104
120
  ).void
105
121
  end
106
- def initialize(nesting, file_path, location, comments)
122
+ def initialize(nesting, file_path, location, name_location, comments)
107
123
  @name = T.let(nesting.join("::"), String)
108
124
  # The original nesting where this namespace was discovered
109
125
  @nesting = nesting
110
126
 
111
127
  super(@name, file_path, location, comments)
128
+
129
+ @name_location = T.let(
130
+ if name_location.is_a?(Prism::Location)
131
+ Location.new(
132
+ name_location.start_line,
133
+ name_location.end_line,
134
+ name_location.start_column,
135
+ name_location.end_column,
136
+ )
137
+ else
138
+ name_location
139
+ end,
140
+ RubyIndexer::Location,
141
+ )
112
142
  end
113
143
 
114
144
  sig { returns(T::Array[String]) }
@@ -146,12 +176,13 @@ module RubyIndexer
146
176
  nesting: T::Array[String],
147
177
  file_path: String,
148
178
  location: T.any(Prism::Location, RubyIndexer::Location),
179
+ name_location: T.any(Prism::Location, Location),
149
180
  comments: T::Array[String],
150
181
  parent_class: T.nilable(String),
151
182
  ).void
152
183
  end
153
- def initialize(nesting, file_path, location, comments, parent_class)
154
- super(nesting, file_path, location, comments)
184
+ def initialize(nesting, file_path, location, name_location, comments, parent_class) # rubocop:disable Metrics/ParameterLists
185
+ super(nesting, file_path, location, name_location, comments)
155
186
  @parent_class = parent_class
156
187
  end
157
188
 
@@ -164,8 +195,8 @@ module RubyIndexer
164
195
  class SingletonClass < Class
165
196
  extend T::Sig
166
197
 
167
- sig { params(location: Prism::Location, comments: T::Array[String]).void }
168
- def update_singleton_information(location, comments)
198
+ sig { params(location: Prism::Location, name_location: Prism::Location, comments: T::Array[String]).void }
199
+ def update_singleton_information(location, name_location, comments)
169
200
  # Create a new RubyIndexer::Location object from the Prism location
170
201
  @location = Location.new(
171
202
  location.start_line,
@@ -173,6 +204,12 @@ module RubyIndexer
173
204
  location.start_column,
174
205
  location.end_column,
175
206
  )
207
+ @name_location = Location.new(
208
+ name_location.start_line,
209
+ name_location.end_line,
210
+ name_location.start_column,
211
+ name_location.end_column,
212
+ )
176
213
  @comments.concat(comments)
177
214
  end
178
215
  end
@@ -266,6 +303,11 @@ module RubyIndexer
266
303
  sig { returns(T.nilable(Entry::Namespace)) }
267
304
  attr_reader :owner
268
305
 
306
+ sig { returns(T::Array[RubyIndexer::Entry::Parameter]) }
307
+ def parameters
308
+ T.must(signatures.first).parameters
309
+ end
310
+
269
311
  sig do
270
312
  params(
271
313
  name: String,
@@ -282,47 +324,72 @@ module RubyIndexer
282
324
  @owner = owner
283
325
  end
284
326
 
285
- sig { abstract.returns(T::Array[Parameter]) }
286
- def parameters; end
327
+ sig { abstract.returns(T::Array[Entry::Signature]) }
328
+ def signatures; end
287
329
 
288
- # Returns a string with the decorated names of the parameters of this member. E.g.: `(a, b = 1, c: 2)`
289
330
  sig { returns(String) }
290
331
  def decorated_parameters
291
- "(#{parameters.map(&:decorated_name).join(", ")})"
332
+ first_signature = signatures.first
333
+ return "()" unless first_signature
334
+
335
+ "(#{first_signature.format})"
292
336
  end
293
337
  end
294
338
 
295
339
  class Accessor < Member
296
340
  extend T::Sig
297
341
 
298
- sig { override.returns(T::Array[Parameter]) }
299
- def parameters
300
- params = []
301
- params << RequiredParameter.new(name: name.delete_suffix("=").to_sym) if name.end_with?("=")
302
- params
342
+ sig { override.returns(T::Array[Signature]) }
343
+ def signatures
344
+ @signatures ||= T.let(
345
+ begin
346
+ params = []
347
+ params << RequiredParameter.new(name: name.delete_suffix("=").to_sym) if name.end_with?("=")
348
+ [Entry::Signature.new(params)]
349
+ end,
350
+ T.nilable(T::Array[Signature]),
351
+ )
303
352
  end
304
353
  end
305
354
 
306
355
  class Method < Member
307
356
  extend T::Sig
308
357
 
309
- sig { override.returns(T::Array[Parameter]) }
310
- attr_reader :parameters
358
+ sig { override.returns(T::Array[Signature]) }
359
+ attr_reader :signatures
360
+
361
+ # Returns the location of the method name, excluding parameters or the body
362
+ sig { returns(Location) }
363
+ attr_reader :name_location
311
364
 
312
365
  sig do
313
366
  params(
314
367
  name: String,
315
368
  file_path: String,
316
369
  location: T.any(Prism::Location, RubyIndexer::Location),
370
+ name_location: T.any(Prism::Location, Location),
317
371
  comments: T::Array[String],
318
- parameters: T::Array[Parameter],
372
+ signatures: T::Array[Signature],
319
373
  visibility: Visibility,
320
374
  owner: T.nilable(Entry::Namespace),
321
375
  ).void
322
376
  end
323
- def initialize(name, file_path, location, comments, parameters, visibility, owner) # rubocop:disable Metrics/ParameterLists
377
+ def initialize(name, file_path, location, name_location, comments, signatures, visibility, owner) # rubocop:disable Metrics/ParameterLists
324
378
  super(name, file_path, location, comments, visibility, owner)
325
- @parameters = parameters
379
+ @signatures = signatures
380
+ @name_location = T.let(
381
+ if name_location.is_a?(Prism::Location)
382
+ Location.new(
383
+ name_location.start_line,
384
+ name_location.end_line,
385
+ name_location.start_column,
386
+ name_location.end_column,
387
+ )
388
+ else
389
+ name_location
390
+ end,
391
+ RubyIndexer::Location,
392
+ )
326
393
  end
327
394
  end
328
395
 
@@ -437,6 +504,9 @@ module RubyIndexer
437
504
  sig { returns(T.any(Member, MethodAlias)) }
438
505
  attr_reader :target
439
506
 
507
+ sig { returns(T.nilable(Entry::Namespace)) }
508
+ attr_reader :owner
509
+
440
510
  sig { params(target: T.any(Member, MethodAlias), unresolved_alias: UnresolvedMethodAlias).void }
441
511
  def initialize(target, unresolved_alias)
442
512
  full_comments = ["Alias for #{target.name}\n"]
@@ -452,11 +522,7 @@ module RubyIndexer
452
522
  )
453
523
 
454
524
  @target = target
455
- end
456
-
457
- sig { returns(T.nilable(Entry::Namespace)) }
458
- def owner
459
- @target.owner
525
+ @owner = T.let(unresolved_alias.owner, T.nilable(Entry::Namespace))
460
526
  end
461
527
 
462
528
  sig { returns(T::Array[Parameter]) }
@@ -469,5 +535,26 @@ module RubyIndexer
469
535
  @target.decorated_parameters
470
536
  end
471
537
  end
538
+
539
+ # Ruby doesn't support method overloading, so a method will have only one signature.
540
+ # However RBS can represent the concept of method overloading, with different return types based on the arguments
541
+ # passed, so we need to store all the signatures.
542
+ class Signature
543
+ extend T::Sig
544
+
545
+ sig { returns(T::Array[Parameter]) }
546
+ attr_reader :parameters
547
+
548
+ sig { params(parameters: T::Array[Parameter]).void }
549
+ def initialize(parameters)
550
+ @parameters = parameters
551
+ end
552
+
553
+ # Returns a string with the decorated names of the parameters of this member. E.g.: `(a, b = 1, c: 2)`
554
+ sig { returns(String) }
555
+ def format
556
+ @parameters.map(&:decorated_name).join(", ")
557
+ end
558
+ end
472
559
  end
473
560
  end