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 +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
|