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 +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 +112 -25
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +266 -68
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +13 -32
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +33 -3
- data/lib/ruby_indexer/test/index_test.rb +242 -7
- data/lib/ruby_indexer/test/method_test.rb +21 -1
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +11 -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: 30ab87e9f42251fafcf8c085d14272b6e0cc0fb6e6968db3fc4c304e92000c63
|
4
|
+
data.tar.gz: 305592ad82c3e41b72dff4c0a48ff60e6158ffba6d06b802844418c3873a6ef9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
-
|
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
|
@@ -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[
|
286
|
-
def
|
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
|
-
|
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[
|
299
|
-
def
|
300
|
-
|
301
|
-
|
302
|
-
|
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[
|
310
|
-
attr_reader :
|
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
|
-
|
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,
|
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
|
-
@
|
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
|
-
|
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
|