ruby-lsp 0.17.4 → 0.17.6
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 +4 -4
- data/README.md +4 -0
- data/VERSION +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +40 -39
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +120 -25
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +266 -68
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +115 -34
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +33 -3
- data/lib/ruby_indexer/test/index_test.rb +248 -7
- data/lib/ruby_indexer/test/method_test.rb +58 -25
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +259 -0
- data/lib/ruby_indexer/test/test_case.rb +1 -5
- data/lib/ruby_lsp/addon.rb +13 -1
- data/lib/ruby_lsp/document.rb +13 -15
- data/lib/ruby_lsp/erb_document.rb +125 -0
- data/lib/ruby_lsp/global_state.rb +4 -1
- data/lib/ruby_lsp/internal.rb +2 -0
- data/lib/ruby_lsp/listeners/completion.rb +26 -30
- data/lib/ruby_lsp/listeners/definition.rb +24 -17
- data/lib/ruby_lsp/requests/code_action_resolve.rb +2 -2
- data/lib/ruby_lsp/requests/completion.rb +1 -1
- data/lib/ruby_lsp/requests/completion_resolve.rb +2 -7
- data/lib/ruby_lsp/requests/definition.rb +4 -3
- data/lib/ruby_lsp/requests/formatting.rb +2 -0
- data/lib/ruby_lsp/requests/selection_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +3 -2
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +2 -6
- data/lib/ruby_lsp/ruby_document.rb +10 -0
- data/lib/ruby_lsp/server.rb +41 -11
- data/lib/ruby_lsp/store.rb +23 -8
- data/lib/ruby_lsp/test_helper.rb +2 -0
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7299237468ae17d80028a1454903f58b1be4ff34428a6c8a538530b5caad54d1
|
4
|
+
data.tar.gz: 26351e5be1671219a9b3624076b2f50fb68c5838303fe1a021eecb39c4e3e9f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 54cc76a3506a268398cfc51645a70300e2d14bda5b39c12274863270f70ed666b33bfebdf50dac8e013410e8ddba5645f4f435863af795d268710e0ccf9d8814
|
7
|
+
data.tar.gz: 95e52a4aa6f68785495f7435fe54cc395c062809ad3754703f808c68d2599bc34a619578bbb8453cb54de88a8312ac49eff8dd2e72a82bc04554c7b659c477cd
|
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.
|
1
|
+
0.17.6
|
@@ -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
|
-
|
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
|
-
|
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(
|
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
|
-
|
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 = @
|
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
|
-
|
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
|
@@ -251,6 +288,14 @@ module RubyIndexer
|
|
251
288
|
class BlockParameter < Parameter
|
252
289
|
DEFAULT_NAME = T.let(:"<anonymous block>", Symbol)
|
253
290
|
|
291
|
+
class << self
|
292
|
+
extend T::Sig
|
293
|
+
sig { returns(BlockParameter) }
|
294
|
+
def anonymous
|
295
|
+
new(name: DEFAULT_NAME)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
254
299
|
sig { override.returns(Symbol) }
|
255
300
|
def decorated_name
|
256
301
|
:"&#{@name}"
|
@@ -266,6 +311,11 @@ module RubyIndexer
|
|
266
311
|
sig { returns(T.nilable(Entry::Namespace)) }
|
267
312
|
attr_reader :owner
|
268
313
|
|
314
|
+
sig { returns(T::Array[RubyIndexer::Entry::Parameter]) }
|
315
|
+
def parameters
|
316
|
+
T.must(signatures.first).parameters
|
317
|
+
end
|
318
|
+
|
269
319
|
sig do
|
270
320
|
params(
|
271
321
|
name: String,
|
@@ -282,47 +332,72 @@ module RubyIndexer
|
|
282
332
|
@owner = owner
|
283
333
|
end
|
284
334
|
|
285
|
-
sig { abstract.returns(T::Array[
|
286
|
-
def
|
335
|
+
sig { abstract.returns(T::Array[Entry::Signature]) }
|
336
|
+
def signatures; end
|
287
337
|
|
288
|
-
# Returns a string with the decorated names of the parameters of this member. E.g.: `(a, b = 1, c: 2)`
|
289
338
|
sig { returns(String) }
|
290
339
|
def decorated_parameters
|
291
|
-
|
340
|
+
first_signature = signatures.first
|
341
|
+
return "()" unless first_signature
|
342
|
+
|
343
|
+
"(#{first_signature.format})"
|
292
344
|
end
|
293
345
|
end
|
294
346
|
|
295
347
|
class Accessor < Member
|
296
348
|
extend T::Sig
|
297
349
|
|
298
|
-
sig { override.returns(T::Array[
|
299
|
-
def
|
300
|
-
|
301
|
-
|
302
|
-
|
350
|
+
sig { override.returns(T::Array[Signature]) }
|
351
|
+
def signatures
|
352
|
+
@signatures ||= T.let(
|
353
|
+
begin
|
354
|
+
params = []
|
355
|
+
params << RequiredParameter.new(name: name.delete_suffix("=").to_sym) if name.end_with?("=")
|
356
|
+
[Entry::Signature.new(params)]
|
357
|
+
end,
|
358
|
+
T.nilable(T::Array[Signature]),
|
359
|
+
)
|
303
360
|
end
|
304
361
|
end
|
305
362
|
|
306
363
|
class Method < Member
|
307
364
|
extend T::Sig
|
308
365
|
|
309
|
-
sig { override.returns(T::Array[
|
310
|
-
attr_reader :
|
366
|
+
sig { override.returns(T::Array[Signature]) }
|
367
|
+
attr_reader :signatures
|
368
|
+
|
369
|
+
# Returns the location of the method name, excluding parameters or the body
|
370
|
+
sig { returns(Location) }
|
371
|
+
attr_reader :name_location
|
311
372
|
|
312
373
|
sig do
|
313
374
|
params(
|
314
375
|
name: String,
|
315
376
|
file_path: String,
|
316
377
|
location: T.any(Prism::Location, RubyIndexer::Location),
|
378
|
+
name_location: T.any(Prism::Location, Location),
|
317
379
|
comments: T::Array[String],
|
318
|
-
|
380
|
+
signatures: T::Array[Signature],
|
319
381
|
visibility: Visibility,
|
320
382
|
owner: T.nilable(Entry::Namespace),
|
321
383
|
).void
|
322
384
|
end
|
323
|
-
def initialize(name, file_path, location, comments,
|
385
|
+
def initialize(name, file_path, location, name_location, comments, signatures, visibility, owner) # rubocop:disable Metrics/ParameterLists
|
324
386
|
super(name, file_path, location, comments, visibility, owner)
|
325
|
-
@
|
387
|
+
@signatures = signatures
|
388
|
+
@name_location = T.let(
|
389
|
+
if name_location.is_a?(Prism::Location)
|
390
|
+
Location.new(
|
391
|
+
name_location.start_line,
|
392
|
+
name_location.end_line,
|
393
|
+
name_location.start_column,
|
394
|
+
name_location.end_column,
|
395
|
+
)
|
396
|
+
else
|
397
|
+
name_location
|
398
|
+
end,
|
399
|
+
RubyIndexer::Location,
|
400
|
+
)
|
326
401
|
end
|
327
402
|
end
|
328
403
|
|
@@ -437,6 +512,9 @@ module RubyIndexer
|
|
437
512
|
sig { returns(T.any(Member, MethodAlias)) }
|
438
513
|
attr_reader :target
|
439
514
|
|
515
|
+
sig { returns(T.nilable(Entry::Namespace)) }
|
516
|
+
attr_reader :owner
|
517
|
+
|
440
518
|
sig { params(target: T.any(Member, MethodAlias), unresolved_alias: UnresolvedMethodAlias).void }
|
441
519
|
def initialize(target, unresolved_alias)
|
442
520
|
full_comments = ["Alias for #{target.name}\n"]
|
@@ -452,11 +530,7 @@ module RubyIndexer
|
|
452
530
|
)
|
453
531
|
|
454
532
|
@target = target
|
455
|
-
|
456
|
-
|
457
|
-
sig { returns(T.nilable(Entry::Namespace)) }
|
458
|
-
def owner
|
459
|
-
@target.owner
|
533
|
+
@owner = T.let(unresolved_alias.owner, T.nilable(Entry::Namespace))
|
460
534
|
end
|
461
535
|
|
462
536
|
sig { returns(T::Array[Parameter]) }
|
@@ -469,5 +543,26 @@ module RubyIndexer
|
|
469
543
|
@target.decorated_parameters
|
470
544
|
end
|
471
545
|
end
|
546
|
+
|
547
|
+
# Ruby doesn't support method overloading, so a method will have only one signature.
|
548
|
+
# However RBS can represent the concept of method overloading, with different return types based on the arguments
|
549
|
+
# passed, so we need to store all the signatures.
|
550
|
+
class Signature
|
551
|
+
extend T::Sig
|
552
|
+
|
553
|
+
sig { returns(T::Array[Parameter]) }
|
554
|
+
attr_reader :parameters
|
555
|
+
|
556
|
+
sig { params(parameters: T::Array[Parameter]).void }
|
557
|
+
def initialize(parameters)
|
558
|
+
@parameters = parameters
|
559
|
+
end
|
560
|
+
|
561
|
+
# Returns a string with the decorated names of the parameters of this member. E.g.: `(a, b = 1, c: 2)`
|
562
|
+
sig { returns(String) }
|
563
|
+
def format
|
564
|
+
@parameters.map(&:decorated_name).join(", ")
|
565
|
+
end
|
566
|
+
end
|
472
567
|
end
|
473
568
|
end
|