ruby-lsp 0.22.0 → 0.23.0
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/VERSION +1 -1
- data/exe/ruby-lsp +10 -9
- data/exe/ruby-lsp-check +5 -5
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +26 -20
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +131 -23
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +60 -30
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +73 -55
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +16 -14
- data/lib/{core_ext → ruby_indexer/lib/ruby_indexer}/uri.rb +29 -3
- data/lib/ruby_indexer/ruby_indexer.rb +1 -1
- data/lib/ruby_indexer/test/class_variables_test.rb +140 -0
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +11 -6
- data/lib/ruby_indexer/test/configuration_test.rb +116 -51
- data/lib/ruby_indexer/test/enhancements_test.rb +2 -2
- data/lib/ruby_indexer/test/index_test.rb +72 -43
- data/lib/ruby_indexer/test/method_test.rb +80 -0
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +1 -1
- data/lib/ruby_indexer/test/reference_finder_test.rb +1 -1
- data/lib/ruby_indexer/test/test_case.rb +2 -2
- data/lib/ruby_indexer/test/uri_test.rb +72 -0
- data/lib/ruby_lsp/addon.rb +9 -0
- data/lib/ruby_lsp/base_server.rb +15 -6
- data/lib/ruby_lsp/document.rb +10 -1
- data/lib/ruby_lsp/global_state.rb +1 -1
- data/lib/ruby_lsp/internal.rb +1 -1
- data/lib/ruby_lsp/listeners/code_lens.rb +8 -4
- data/lib/ruby_lsp/listeners/completion.rb +73 -4
- data/lib/ruby_lsp/listeners/definition.rb +73 -17
- data/lib/ruby_lsp/listeners/document_symbol.rb +49 -5
- data/lib/ruby_lsp/listeners/folding_ranges.rb +1 -1
- data/lib/ruby_lsp/listeners/hover.rb +57 -0
- data/lib/ruby_lsp/requests/completion.rb +6 -0
- data/lib/ruby_lsp/requests/completion_resolve.rb +2 -1
- data/lib/ruby_lsp/requests/definition.rb +6 -0
- data/lib/ruby_lsp/requests/prepare_rename.rb +51 -0
- data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +1 -1
- data/lib/ruby_lsp/requests/rename.rb +14 -4
- data/lib/ruby_lsp/requests/support/common.rb +1 -5
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +1 -1
- data/lib/ruby_lsp/requests/workspace_symbol.rb +3 -2
- data/lib/ruby_lsp/scripts/compose_bundle.rb +1 -1
- data/lib/ruby_lsp/server.rb +42 -7
- data/lib/ruby_lsp/setup_bundler.rb +54 -46
- data/lib/ruby_lsp/test_helper.rb +45 -11
- data/lib/ruby_lsp/type_inferrer.rb +22 -0
- data/lib/ruby_lsp/utils.rb +3 -0
- metadata +7 -8
- data/lib/ruby_indexer/lib/ruby_indexer/indexable_path.rb +0 -29
@@ -16,8 +16,8 @@ module RubyIndexer
|
|
16
16
|
sig { returns(String) }
|
17
17
|
attr_reader :name
|
18
18
|
|
19
|
-
sig { returns(
|
20
|
-
attr_reader :
|
19
|
+
sig { returns(URI::Generic) }
|
20
|
+
attr_reader :uri
|
21
21
|
|
22
22
|
sig { returns(RubyIndexer::Location) }
|
23
23
|
attr_reader :location
|
@@ -30,14 +30,14 @@ module RubyIndexer
|
|
30
30
|
sig do
|
31
31
|
params(
|
32
32
|
name: String,
|
33
|
-
|
33
|
+
uri: URI::Generic,
|
34
34
|
location: Location,
|
35
35
|
comments: T.nilable(String),
|
36
36
|
).void
|
37
37
|
end
|
38
|
-
def initialize(name,
|
38
|
+
def initialize(name, uri, location, comments)
|
39
39
|
@name = name
|
40
|
-
@
|
40
|
+
@uri = uri
|
41
41
|
@comments = comments
|
42
42
|
@visibility = T.let(Visibility::PUBLIC, Visibility)
|
43
43
|
@location = location
|
@@ -60,14 +60,24 @@ module RubyIndexer
|
|
60
60
|
|
61
61
|
sig { returns(String) }
|
62
62
|
def file_name
|
63
|
-
|
63
|
+
if @uri.scheme == "untitled"
|
64
|
+
T.must(@uri.opaque)
|
65
|
+
else
|
66
|
+
File.basename(T.must(file_path))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
sig { returns(T.nilable(String)) }
|
71
|
+
def file_path
|
72
|
+
@uri.full_path
|
64
73
|
end
|
65
74
|
|
66
75
|
sig { returns(String) }
|
67
76
|
def comments
|
68
77
|
@comments ||= begin
|
69
78
|
# Parse only the comments based on the file path, which is much faster than parsing the entire file
|
70
|
-
|
79
|
+
path = file_path
|
80
|
+
parsed_comments = path ? Prism.parse_file_comments(path) : []
|
71
81
|
|
72
82
|
# Group comments based on whether they belong to a single block of comments
|
73
83
|
grouped = parsed_comments.slice_when do |left, right|
|
@@ -137,18 +147,18 @@ module RubyIndexer
|
|
137
147
|
sig do
|
138
148
|
params(
|
139
149
|
nesting: T::Array[String],
|
140
|
-
|
150
|
+
uri: URI::Generic,
|
141
151
|
location: Location,
|
142
152
|
name_location: Location,
|
143
153
|
comments: T.nilable(String),
|
144
154
|
).void
|
145
155
|
end
|
146
|
-
def initialize(nesting,
|
156
|
+
def initialize(nesting, uri, location, name_location, comments)
|
147
157
|
@name = T.let(nesting.join("::"), String)
|
148
158
|
# The original nesting where this namespace was discovered
|
149
159
|
@nesting = nesting
|
150
160
|
|
151
|
-
super(@name,
|
161
|
+
super(@name, uri, location, comments)
|
152
162
|
|
153
163
|
@name_location = name_location
|
154
164
|
end
|
@@ -186,15 +196,15 @@ module RubyIndexer
|
|
186
196
|
sig do
|
187
197
|
params(
|
188
198
|
nesting: T::Array[String],
|
189
|
-
|
199
|
+
uri: URI::Generic,
|
190
200
|
location: Location,
|
191
201
|
name_location: Location,
|
192
202
|
comments: T.nilable(String),
|
193
203
|
parent_class: T.nilable(String),
|
194
204
|
).void
|
195
205
|
end
|
196
|
-
def initialize(nesting,
|
197
|
-
super(nesting,
|
206
|
+
def initialize(nesting, uri, location, name_location, comments, parent_class) # rubocop:disable Metrics/ParameterLists
|
207
|
+
super(nesting, uri, location, name_location, comments)
|
198
208
|
@parent_class = parent_class
|
199
209
|
end
|
200
210
|
|
@@ -332,15 +342,15 @@ module RubyIndexer
|
|
332
342
|
sig do
|
333
343
|
params(
|
334
344
|
name: String,
|
335
|
-
|
345
|
+
uri: URI::Generic,
|
336
346
|
location: Location,
|
337
347
|
comments: T.nilable(String),
|
338
348
|
visibility: Visibility,
|
339
349
|
owner: T.nilable(Entry::Namespace),
|
340
350
|
).void
|
341
351
|
end
|
342
|
-
def initialize(name,
|
343
|
-
super(name,
|
352
|
+
def initialize(name, uri, location, comments, visibility, owner) # rubocop:disable Metrics/ParameterLists
|
353
|
+
super(name, uri, location, comments)
|
344
354
|
@visibility = visibility
|
345
355
|
@owner = owner
|
346
356
|
end
|
@@ -399,7 +409,7 @@ module RubyIndexer
|
|
399
409
|
sig do
|
400
410
|
params(
|
401
411
|
name: String,
|
402
|
-
|
412
|
+
uri: URI::Generic,
|
403
413
|
location: Location,
|
404
414
|
name_location: Location,
|
405
415
|
comments: T.nilable(String),
|
@@ -408,8 +418,8 @@ module RubyIndexer
|
|
408
418
|
owner: T.nilable(Entry::Namespace),
|
409
419
|
).void
|
410
420
|
end
|
411
|
-
def initialize(name,
|
412
|
-
super(name,
|
421
|
+
def initialize(name, uri, location, name_location, comments, signatures, visibility, owner) # rubocop:disable Metrics/ParameterLists
|
422
|
+
super(name, uri, location, comments, visibility, owner)
|
413
423
|
@signatures = signatures
|
414
424
|
@name_location = name_location
|
415
425
|
end
|
@@ -439,13 +449,13 @@ module RubyIndexer
|
|
439
449
|
target: String,
|
440
450
|
nesting: T::Array[String],
|
441
451
|
name: String,
|
442
|
-
|
452
|
+
uri: URI::Generic,
|
443
453
|
location: Location,
|
444
454
|
comments: T.nilable(String),
|
445
455
|
).void
|
446
456
|
end
|
447
|
-
def initialize(target, nesting, name,
|
448
|
-
super(name,
|
457
|
+
def initialize(target, nesting, name, uri, location, comments) # rubocop:disable Metrics/ParameterLists
|
458
|
+
super(name, uri, location, comments)
|
449
459
|
|
450
460
|
@target = target
|
451
461
|
@nesting = nesting
|
@@ -463,7 +473,7 @@ module RubyIndexer
|
|
463
473
|
def initialize(target, unresolved_alias)
|
464
474
|
super(
|
465
475
|
unresolved_alias.name,
|
466
|
-
unresolved_alias.
|
476
|
+
unresolved_alias.uri,
|
467
477
|
unresolved_alias.location,
|
468
478
|
unresolved_alias.comments,
|
469
479
|
)
|
@@ -476,6 +486,26 @@ module RubyIndexer
|
|
476
486
|
# Represents a global variable e.g.: $DEBUG
|
477
487
|
class GlobalVariable < Entry; end
|
478
488
|
|
489
|
+
# Represents a class variable e.g.: @@a = 1
|
490
|
+
class ClassVariable < Entry
|
491
|
+
sig { returns(T.nilable(Entry::Namespace)) }
|
492
|
+
attr_reader :owner
|
493
|
+
|
494
|
+
sig do
|
495
|
+
params(
|
496
|
+
name: String,
|
497
|
+
uri: URI::Generic,
|
498
|
+
location: Location,
|
499
|
+
comments: T.nilable(String),
|
500
|
+
owner: T.nilable(Entry::Namespace),
|
501
|
+
).void
|
502
|
+
end
|
503
|
+
def initialize(name, uri, location, comments, owner)
|
504
|
+
super(name, uri, location, comments)
|
505
|
+
@owner = owner
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
479
509
|
# Represents an instance variable e.g.: @a = 1
|
480
510
|
class InstanceVariable < Entry
|
481
511
|
sig { returns(T.nilable(Entry::Namespace)) }
|
@@ -484,14 +514,14 @@ module RubyIndexer
|
|
484
514
|
sig do
|
485
515
|
params(
|
486
516
|
name: String,
|
487
|
-
|
517
|
+
uri: URI::Generic,
|
488
518
|
location: Location,
|
489
519
|
comments: T.nilable(String),
|
490
520
|
owner: T.nilable(Entry::Namespace),
|
491
521
|
).void
|
492
522
|
end
|
493
|
-
def initialize(name,
|
494
|
-
super(name,
|
523
|
+
def initialize(name, uri, location, comments, owner)
|
524
|
+
super(name, uri, location, comments)
|
495
525
|
@owner = owner
|
496
526
|
end
|
497
527
|
end
|
@@ -513,13 +543,13 @@ module RubyIndexer
|
|
513
543
|
new_name: String,
|
514
544
|
old_name: String,
|
515
545
|
owner: T.nilable(Entry::Namespace),
|
516
|
-
|
546
|
+
uri: URI::Generic,
|
517
547
|
location: Location,
|
518
548
|
comments: T.nilable(String),
|
519
549
|
).void
|
520
550
|
end
|
521
|
-
def initialize(new_name, old_name, owner,
|
522
|
-
super(new_name,
|
551
|
+
def initialize(new_name, old_name, owner, uri, location, comments) # rubocop:disable Metrics/ParameterLists
|
552
|
+
super(new_name, uri, location, comments)
|
523
553
|
|
524
554
|
@new_name = new_name
|
525
555
|
@old_name = old_name
|
@@ -547,7 +577,7 @@ module RubyIndexer
|
|
547
577
|
|
548
578
|
super(
|
549
579
|
unresolved_alias.new_name,
|
550
|
-
unresolved_alias.
|
580
|
+
unresolved_alias.uri,
|
551
581
|
unresolved_alias.location,
|
552
582
|
full_comments,
|
553
583
|
)
|
@@ -29,13 +29,14 @@ module RubyIndexer
|
|
29
29
|
|
30
30
|
# Holds references to where entries where discovered so that we can easily delete them
|
31
31
|
# {
|
32
|
-
# "
|
33
|
-
# "
|
32
|
+
# "file:///my/project/foo.rb" => [#<Entry::Class>, #<Entry::Class>],
|
33
|
+
# "file:///my/project/bar.rb" => [#<Entry::Class>],
|
34
|
+
# "untitled:Untitled-1" => [#<Entry::Class>],
|
34
35
|
# }
|
35
|
-
@
|
36
|
+
@uris_to_entries = T.let({}, T::Hash[String, T::Array[Entry]])
|
36
37
|
|
37
38
|
# Holds all require paths for every indexed item so that we can provide autocomplete for requires
|
38
|
-
@require_paths_tree = T.let(PrefixTree[
|
39
|
+
@require_paths_tree = T.let(PrefixTree[URI::Generic].new, PrefixTree[URI::Generic])
|
39
40
|
|
40
41
|
# Holds the linearized ancestors list for every namespace
|
41
42
|
@ancestors = T.let({}, T::Hash[String, T::Array[String]])
|
@@ -55,11 +56,12 @@ module RubyIndexer
|
|
55
56
|
(@included_hooks[module_name] ||= []) << hook
|
56
57
|
end
|
57
58
|
|
58
|
-
sig { params(
|
59
|
-
def delete(
|
59
|
+
sig { params(uri: URI::Generic).void }
|
60
|
+
def delete(uri)
|
61
|
+
key = uri.to_s
|
60
62
|
# For each constant discovered in `path`, delete the associated entry from the index. If there are no entries
|
61
63
|
# left, delete the constant from the index.
|
62
|
-
@
|
64
|
+
@uris_to_entries[key]&.each do |entry|
|
63
65
|
name = entry.name
|
64
66
|
entries = @entries[name]
|
65
67
|
next unless entries
|
@@ -77,9 +79,9 @@ module RubyIndexer
|
|
77
79
|
end
|
78
80
|
end
|
79
81
|
|
80
|
-
@
|
82
|
+
@uris_to_entries.delete(key)
|
81
83
|
|
82
|
-
require_path =
|
84
|
+
require_path = uri.require_path
|
83
85
|
@require_paths_tree.delete(require_path) if require_path
|
84
86
|
end
|
85
87
|
|
@@ -88,7 +90,7 @@ module RubyIndexer
|
|
88
90
|
name = entry.name
|
89
91
|
|
90
92
|
(@entries[name] ||= []) << entry
|
91
|
-
(@
|
93
|
+
(@uris_to_entries[entry.uri.to_s] ||= []) << entry
|
92
94
|
@entries_tree.insert(name, T.must(@entries[name])) unless skip_prefix_tree
|
93
95
|
end
|
94
96
|
|
@@ -97,7 +99,7 @@ module RubyIndexer
|
|
97
99
|
@entries[fully_qualified_name.delete_prefix("::")]
|
98
100
|
end
|
99
101
|
|
100
|
-
sig { params(query: String).returns(T::Array[
|
102
|
+
sig { params(query: String).returns(T::Array[URI::Generic]) }
|
101
103
|
def search_require_paths(query)
|
102
104
|
@require_paths_tree.search(query)
|
103
105
|
end
|
@@ -342,16 +344,16 @@ module RubyIndexer
|
|
342
344
|
nil
|
343
345
|
end
|
344
346
|
|
345
|
-
# Index all files for the given
|
346
|
-
#
|
347
|
-
#
|
347
|
+
# Index all files for the given URIs, which defaults to what is configured. A block can be used to track and control
|
348
|
+
# indexing progress. That block is invoked with the current progress percentage and should return `true` to continue
|
349
|
+
# indexing or `false` to stop indexing.
|
348
350
|
sig do
|
349
351
|
params(
|
350
|
-
|
352
|
+
uris: T::Array[URI::Generic],
|
351
353
|
block: T.nilable(T.proc.params(progress: Integer).returns(T::Boolean)),
|
352
354
|
).void
|
353
355
|
end
|
354
|
-
def index_all(
|
356
|
+
def index_all(uris: @configuration.indexable_uris, &block)
|
355
357
|
# When troubleshooting an indexing issue, e.g. through irb, it's not obvious that `index_all` will augment the
|
356
358
|
# existing index values, meaning it may contain 'stale' entries. This check ensures that the user is aware of this
|
357
359
|
# behavior and can take appropriate action.
|
@@ -363,54 +365,48 @@ module RubyIndexer
|
|
363
365
|
|
364
366
|
RBSIndexer.new(self).index_ruby_core
|
365
367
|
# Calculate how many paths are worth 1% of progress
|
366
|
-
progress_step = (
|
368
|
+
progress_step = (uris.length / 100.0).ceil
|
367
369
|
|
368
|
-
|
370
|
+
uris.each_with_index do |uri, index|
|
369
371
|
if block && index % progress_step == 0
|
370
372
|
progress = (index / progress_step) + 1
|
371
373
|
break unless block.call(progress)
|
372
374
|
end
|
373
375
|
|
374
|
-
|
376
|
+
index_file(uri, collect_comments: false)
|
375
377
|
end
|
376
378
|
end
|
377
379
|
|
378
|
-
sig { params(
|
379
|
-
def index_single(
|
380
|
-
content = source || File.read(indexable_path.full_path)
|
380
|
+
sig { params(uri: URI::Generic, source: String, collect_comments: T::Boolean).void }
|
381
|
+
def index_single(uri, source, collect_comments: true)
|
381
382
|
dispatcher = Prism::Dispatcher.new
|
382
383
|
|
383
|
-
result = Prism.parse(
|
384
|
-
listener = DeclarationListener.new(
|
385
|
-
self,
|
386
|
-
dispatcher,
|
387
|
-
result,
|
388
|
-
indexable_path.full_path,
|
389
|
-
collect_comments: collect_comments,
|
390
|
-
)
|
384
|
+
result = Prism.parse(source)
|
385
|
+
listener = DeclarationListener.new(self, dispatcher, result, uri, collect_comments: collect_comments)
|
391
386
|
dispatcher.dispatch(result.value)
|
392
387
|
|
393
|
-
|
394
|
-
|
395
|
-
require_path = indexable_path.require_path
|
396
|
-
@require_paths_tree.insert(require_path, indexable_path) if require_path
|
388
|
+
require_path = uri.require_path
|
389
|
+
@require_paths_tree.insert(require_path, uri) if require_path
|
397
390
|
|
398
|
-
|
399
|
-
|
400
|
-
$stderr.puts error
|
401
|
-
end
|
402
|
-
end
|
403
|
-
rescue Errno::EISDIR, Errno::ENOENT
|
404
|
-
# If `path` is a directory, just ignore it and continue indexing. If the file doesn't exist, then we also ignore
|
405
|
-
# it
|
391
|
+
indexing_errors = listener.indexing_errors.uniq
|
392
|
+
indexing_errors.each { |error| $stderr.puts(error) } if indexing_errors.any?
|
406
393
|
rescue SystemStackError => e
|
407
394
|
if e.backtrace&.first&.include?("prism")
|
408
|
-
$stderr.puts "Prism error indexing #{
|
395
|
+
$stderr.puts "Prism error indexing #{uri}: #{e.message}"
|
409
396
|
else
|
410
397
|
raise
|
411
398
|
end
|
412
399
|
end
|
413
400
|
|
401
|
+
# Indexes a File URI by reading the contents from disk
|
402
|
+
sig { params(uri: URI::Generic, collect_comments: T::Boolean).void }
|
403
|
+
def index_file(uri, collect_comments: true)
|
404
|
+
index_single(uri, File.read(T.must(uri.full_path)), collect_comments: collect_comments)
|
405
|
+
rescue Errno::EISDIR, Errno::ENOENT
|
406
|
+
# If `path` is a directory, just ignore it and continue indexing. If the file doesn't exist, then we also ignore
|
407
|
+
# it
|
408
|
+
end
|
409
|
+
|
414
410
|
# Follows aliases in a namespace. The algorithm keeps checking if the name is an alias and then recursively follows
|
415
411
|
# it. The idea is that we test the name in parts starting from the complete name to the first namespace. For
|
416
412
|
# `Foo::Bar::Baz`, we would test:
|
@@ -588,6 +584,17 @@ module RubyIndexer
|
|
588
584
|
entries.select { |e| ancestors.include?(e.owner&.name) }
|
589
585
|
end
|
590
586
|
|
587
|
+
sig { params(variable_name: String, owner_name: String).returns(T.nilable(T::Array[Entry::ClassVariable])) }
|
588
|
+
def resolve_class_variable(variable_name, owner_name)
|
589
|
+
entries = self[variable_name]&.grep(Entry::ClassVariable)
|
590
|
+
return unless entries&.any?
|
591
|
+
|
592
|
+
ancestors = linearized_ancestors_of(owner_name)
|
593
|
+
return if ancestors.empty?
|
594
|
+
|
595
|
+
entries.select { |e| ancestors.include?(e.owner&.name) }
|
596
|
+
end
|
597
|
+
|
591
598
|
# Returns a list of possible candidates for completion of instance variables for a given owner name. The name must
|
592
599
|
# include the `@` prefix
|
593
600
|
sig { params(name: String, owner_name: String).returns(T::Array[Entry::InstanceVariable]) }
|
@@ -600,16 +607,27 @@ module RubyIndexer
|
|
600
607
|
variables
|
601
608
|
end
|
602
609
|
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
610
|
+
sig { params(name: String, owner_name: String).returns(T::Array[Entry::ClassVariable]) }
|
611
|
+
def class_variable_completion_candidates(name, owner_name)
|
612
|
+
entries = T.cast(prefix_search(name).flatten, T::Array[Entry::ClassVariable])
|
613
|
+
ancestors = linearized_ancestors_of(owner_name)
|
614
|
+
|
615
|
+
variables = entries.select { |e| ancestors.any?(e.owner&.name) }
|
616
|
+
variables.uniq!(&:name)
|
617
|
+
variables
|
618
|
+
end
|
619
|
+
|
620
|
+
# Synchronizes a change made to the given URI. This method will ensure that new declarations are indexed, removed
|
621
|
+
# declarations removed and that the ancestor linearization cache is cleared if necessary
|
622
|
+
sig { params(uri: URI::Generic, source: String).void }
|
623
|
+
def handle_change(uri, source)
|
624
|
+
key = uri.to_s
|
625
|
+
original_entries = @uris_to_entries[key]
|
608
626
|
|
609
|
-
delete(
|
610
|
-
index_single(
|
627
|
+
delete(uri)
|
628
|
+
index_single(uri, source)
|
611
629
|
|
612
|
-
updated_entries = @
|
630
|
+
updated_entries = @uris_to_entries[key]
|
613
631
|
|
614
632
|
return unless original_entries && updated_entries
|
615
633
|
|
@@ -661,7 +679,7 @@ module RubyIndexer
|
|
661
679
|
|
662
680
|
singleton = Entry::SingletonClass.new(
|
663
681
|
[full_singleton_name],
|
664
|
-
attached_ancestor.
|
682
|
+
attached_ancestor.uri,
|
665
683
|
attached_ancestor.location,
|
666
684
|
attached_ancestor.name_location,
|
667
685
|
nil,
|
@@ -675,12 +693,12 @@ module RubyIndexer
|
|
675
693
|
|
676
694
|
sig do
|
677
695
|
type_parameters(:T).params(
|
678
|
-
|
696
|
+
uri: String,
|
679
697
|
type: T.nilable(T::Class[T.all(T.type_parameter(:T), Entry)]),
|
680
698
|
).returns(T.nilable(T.any(T::Array[Entry], T::Array[T.type_parameter(:T)])))
|
681
699
|
end
|
682
|
-
def entries_for(
|
683
|
-
entries = @
|
700
|
+
def entries_for(uri, type = nil)
|
701
|
+
entries = @uris_to_entries[uri.to_s]
|
684
702
|
return entries unless type
|
685
703
|
|
686
704
|
entries&.grep(type)
|
@@ -43,7 +43,7 @@ module RubyIndexer
|
|
43
43
|
handle_class_or_module_declaration(declaration, pathname)
|
44
44
|
when RBS::AST::Declarations::Constant
|
45
45
|
namespace_nesting = declaration.name.namespace.path.map(&:to_s)
|
46
|
-
handle_constant(declaration, namespace_nesting, pathname.to_s)
|
46
|
+
handle_constant(declaration, namespace_nesting, URI::Generic.from_path(path: pathname.to_s))
|
47
47
|
when RBS::AST::Declarations::Global
|
48
48
|
handle_global_variable(declaration, pathname)
|
49
49
|
else # rubocop:disable Style/EmptyElse
|
@@ -56,23 +56,25 @@ module RubyIndexer
|
|
56
56
|
end
|
57
57
|
def handle_class_or_module_declaration(declaration, pathname)
|
58
58
|
nesting = [declaration.name.name.to_s]
|
59
|
-
|
59
|
+
uri = URI::Generic.from_path(path: pathname.to_s)
|
60
60
|
location = to_ruby_indexer_location(declaration.location)
|
61
61
|
comments = comments_to_string(declaration)
|
62
62
|
entry = if declaration.is_a?(RBS::AST::Declarations::Class)
|
63
63
|
parent_class = declaration.super_class&.name&.name&.to_s
|
64
|
-
Entry::Class.new(nesting,
|
64
|
+
Entry::Class.new(nesting, uri, location, location, comments, parent_class)
|
65
65
|
else
|
66
|
-
Entry::Module.new(nesting,
|
66
|
+
Entry::Module.new(nesting, uri, location, location, comments)
|
67
67
|
end
|
68
|
+
|
68
69
|
add_declaration_mixins_to_entry(declaration, entry)
|
69
70
|
@index.add(entry)
|
71
|
+
|
70
72
|
declaration.members.each do |member|
|
71
73
|
case member
|
72
74
|
when RBS::AST::Members::MethodDefinition
|
73
75
|
handle_method(member, entry)
|
74
76
|
when RBS::AST::Declarations::Constant
|
75
|
-
handle_constant(member, nesting,
|
77
|
+
handle_constant(member, nesting, uri)
|
76
78
|
when RBS::AST::Members::Alias
|
77
79
|
# In RBS, an alias means that two methods have the same signature.
|
78
80
|
# It does not mean the same thing as a Ruby alias.
|
@@ -115,7 +117,7 @@ module RubyIndexer
|
|
115
117
|
sig { params(member: RBS::AST::Members::MethodDefinition, owner: Entry::Namespace).void }
|
116
118
|
def handle_method(member, owner)
|
117
119
|
name = member.name.name
|
118
|
-
|
120
|
+
uri = URI::Generic.from_path(path: member.location.buffer.name)
|
119
121
|
location = to_ruby_indexer_location(member.location)
|
120
122
|
comments = comments_to_string(member)
|
121
123
|
|
@@ -132,7 +134,7 @@ module RubyIndexer
|
|
132
134
|
signatures = signatures(member)
|
133
135
|
@index.add(Entry::Method.new(
|
134
136
|
name,
|
135
|
-
|
137
|
+
uri,
|
136
138
|
location,
|
137
139
|
location,
|
138
140
|
comments,
|
@@ -260,12 +262,12 @@ module RubyIndexer
|
|
260
262
|
# Complex::I = ... # Complex::I is a top-level constant
|
261
263
|
#
|
262
264
|
# And we need to handle their nesting differently.
|
263
|
-
sig { params(declaration: RBS::AST::Declarations::Constant, nesting: T::Array[String],
|
264
|
-
def handle_constant(declaration, nesting,
|
265
|
+
sig { params(declaration: RBS::AST::Declarations::Constant, nesting: T::Array[String], uri: URI::Generic).void }
|
266
|
+
def handle_constant(declaration, nesting, uri)
|
265
267
|
fully_qualified_name = [*nesting, declaration.name.name.to_s].join("::")
|
266
268
|
@index.add(Entry::Constant.new(
|
267
269
|
fully_qualified_name,
|
268
|
-
|
270
|
+
uri,
|
269
271
|
to_ruby_indexer_location(declaration.location),
|
270
272
|
comments_to_string(declaration),
|
271
273
|
))
|
@@ -274,13 +276,13 @@ module RubyIndexer
|
|
274
276
|
sig { params(declaration: RBS::AST::Declarations::Global, pathname: Pathname).void }
|
275
277
|
def handle_global_variable(declaration, pathname)
|
276
278
|
name = declaration.name.to_s
|
277
|
-
|
279
|
+
uri = URI::Generic.from_path(path: pathname.to_s)
|
278
280
|
location = to_ruby_indexer_location(declaration.location)
|
279
281
|
comments = comments_to_string(declaration)
|
280
282
|
|
281
283
|
@index.add(Entry::GlobalVariable.new(
|
282
284
|
name,
|
283
|
-
|
285
|
+
uri,
|
284
286
|
location,
|
285
287
|
comments,
|
286
288
|
))
|
@@ -288,14 +290,14 @@ module RubyIndexer
|
|
288
290
|
|
289
291
|
sig { params(member: RBS::AST::Members::Alias, owner_entry: Entry::Namespace).void }
|
290
292
|
def handle_signature_alias(member, owner_entry)
|
291
|
-
|
293
|
+
uri = URI::Generic.from_path(path: member.location.buffer.name)
|
292
294
|
comments = comments_to_string(member)
|
293
295
|
|
294
296
|
entry = Entry::UnresolvedMethodAlias.new(
|
295
297
|
member.new_name.to_s,
|
296
298
|
member.old_name.to_s,
|
297
299
|
owner_entry,
|
298
|
-
|
300
|
+
uri,
|
299
301
|
to_ruby_indexer_location(member.location),
|
300
302
|
comments,
|
301
303
|
)
|
@@ -13,8 +13,15 @@ module URI
|
|
13
13
|
class << self
|
14
14
|
extend T::Sig
|
15
15
|
|
16
|
-
sig
|
17
|
-
|
16
|
+
sig do
|
17
|
+
params(
|
18
|
+
path: String,
|
19
|
+
fragment: T.nilable(String),
|
20
|
+
scheme: String,
|
21
|
+
load_path_entry: T.nilable(String),
|
22
|
+
).returns(URI::Generic)
|
23
|
+
end
|
24
|
+
def from_path(path:, fragment: nil, scheme: "file", load_path_entry: nil)
|
18
25
|
# On Windows, if the path begins with the disk name, we need to add a leading slash to make it a valid URI
|
19
26
|
escaped_path = if /^[A-Z]:/i.match?(path)
|
20
27
|
PARSER.escape("/#{path}")
|
@@ -25,10 +32,27 @@ module URI
|
|
25
32
|
PARSER.escape(path)
|
26
33
|
end
|
27
34
|
|
28
|
-
build(scheme: scheme, path: escaped_path, fragment: fragment)
|
35
|
+
uri = build(scheme: scheme, path: escaped_path, fragment: fragment)
|
36
|
+
|
37
|
+
if load_path_entry
|
38
|
+
uri.require_path = path.delete_prefix("#{load_path_entry}/").delete_suffix(".rb")
|
39
|
+
end
|
40
|
+
|
41
|
+
uri
|
29
42
|
end
|
30
43
|
end
|
31
44
|
|
45
|
+
sig { returns(T.nilable(String)) }
|
46
|
+
attr_accessor :require_path
|
47
|
+
|
48
|
+
sig { params(load_path_entry: String).void }
|
49
|
+
def add_require_path_from_load_entry(load_path_entry)
|
50
|
+
path = to_standardized_path
|
51
|
+
return unless path
|
52
|
+
|
53
|
+
self.require_path = path.delete_prefix("#{load_path_entry}/").delete_suffix(".rb")
|
54
|
+
end
|
55
|
+
|
32
56
|
sig { returns(T.nilable(String)) }
|
33
57
|
def to_standardized_path
|
34
58
|
parsed_path = path
|
@@ -44,5 +68,7 @@ module URI
|
|
44
68
|
unescaped_path
|
45
69
|
end
|
46
70
|
end
|
71
|
+
|
72
|
+
alias_method :full_path, :to_standardized_path
|
47
73
|
end
|
48
74
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
require "yaml"
|
5
5
|
require "did_you_mean"
|
6
6
|
|
7
|
-
require "ruby_indexer/lib/ruby_indexer/
|
7
|
+
require "ruby_indexer/lib/ruby_indexer/uri"
|
8
8
|
require "ruby_indexer/lib/ruby_indexer/declaration_listener"
|
9
9
|
require "ruby_indexer/lib/ruby_indexer/reference_finder"
|
10
10
|
require "ruby_indexer/lib/ruby_indexer/enhancement"
|