ruby-lsp 0.17.4 → 0.17.5

Sign up to get free protection for your applications and to get access to all the features.
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