ruby-lsp 0.17.4 → 0.17.6
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 +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
|