Skip to content

Commit 624ddc6

Browse files
committed
Replace IndexablePath with Uri concept
1 parent 88b85b8 commit 624ddc6

23 files changed

+290
-195
lines changed

exe/ruby-lsp

+3-3
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,9 @@ if options[:doctor]
127127

128128
puts "Globbing for indexable files"
129129

130-
index.configuration.indexables.each do |indexable|
131-
puts "indexing: #{indexable.full_path}"
132-
index.index_single(indexable)
130+
index.configuration.indexables.each do |uri|
131+
puts "indexing: #{uri}"
132+
index.index_single(uri)
133133
end
134134
return
135135
end

exe/ruby-lsp-check

+3-3
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ puts "Verifying that indexing executes successfully. This may take a while..."
4646
index = RubyIndexer::Index.new
4747
indexables = index.configuration.indexables
4848

49-
indexables.each_with_index do |indexable, i|
50-
index.index_single(indexable)
49+
indexables.each_with_index do |uri, i|
50+
index.index_single(uri)
5151
rescue => e
52-
errors[indexable.full_path] = e
52+
errors[uri.to_standarized_path] = e
5353
ensure
5454
print("\033[M\033[0KIndexed #{i + 1}/#{indexables.length}") unless ENV["CI"]
5555
end

lib/ruby_indexer/lib/ruby_indexer/configuration.rb

+7-7
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def initialize
4343
)
4444
end
4545

46-
sig { returns(T::Array[IndexablePath]) }
46+
sig { returns(T::Array[FileUri]) }
4747
def indexables
4848
excluded_gems = @excluded_gems - @included_gems
4949
locked_gems = Bundler.locked_gems&.specs
@@ -65,14 +65,14 @@ def indexables
6565
load_path_entry = $LOAD_PATH.find { |load_path| path.start_with?(load_path) }
6666
end
6767

68-
IndexablePath.new(load_path_entry, path)
68+
Uri.file(path, load_path_entry)
6969
end
7070
end
7171

7272
# Remove user specified patterns
7373
indexables.reject! do |indexable|
7474
@excluded_patterns.any? do |pattern|
75-
File.fnmatch?(pattern, indexable.full_path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
75+
File.fnmatch?(pattern, indexable.to_standardized_path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
7676
end
7777
end
7878

@@ -104,12 +104,12 @@ def indexables
104104
# If the default_path is a directory, we index all the Ruby files in it
105105
indexables.concat(
106106
Dir.glob(File.join(default_path, "**", "*.rb"), File::FNM_PATHNAME | File::FNM_EXTGLOB).map! do |path|
107-
IndexablePath.new(RbConfig::CONFIG["rubylibdir"], path)
107+
Uri.file(path, RbConfig::CONFIG["rubylibdir"])
108108
end,
109109
)
110110
elsif pathname.extname == ".rb"
111111
# If the default_path is a Ruby file, we index it
112-
indexables << IndexablePath.new(RbConfig::CONFIG["rubylibdir"], default_path)
112+
indexables << Uri.file(default_path, RbConfig::CONFIG["rubylibdir"])
113113
end
114114
end
115115

@@ -127,7 +127,7 @@ def indexables
127127
indexables.concat(
128128
spec.require_paths.flat_map do |require_path|
129129
load_path_entry = File.join(spec.full_gem_path, require_path)
130-
Dir.glob(File.join(load_path_entry, "**", "*.rb")).map! { |path| IndexablePath.new(load_path_entry, path) }
130+
Dir.glob(File.join(load_path_entry, "**", "*.rb")).map! { |path| Uri.file(path, load_path_entry) }
131131
end,
132132
)
133133
rescue Gem::MissingSpecError
@@ -136,7 +136,7 @@ def indexables
136136
# just ignore if they're missing
137137
end
138138

139-
indexables.uniq!(&:full_path)
139+
indexables.uniq!(&:to_s)
140140
indexables
141141
end
142142

lib/ruby_indexer/lib/ruby_indexer/index.rb

+56-47
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def initialize
3434
@files_to_entries = T.let({}, T::Hash[String, T::Array[Entry]])
3535

3636
# Holds all require paths for every indexed item so that we can provide autocomplete for requires
37-
@require_paths_tree = T.let(PrefixTree[IndexablePath].new, PrefixTree[IndexablePath])
37+
@require_paths_tree = T.let(PrefixTree[Uri].new, PrefixTree[Uri])
3838

3939
# Holds the linearized ancestors list for every namespace
4040
@ancestors = T.let({}, T::Hash[String, T::Array[String]])
@@ -63,31 +63,35 @@ def register_included_hook(module_name, &hook)
6363
(@included_hooks[module_name] ||= []) << hook
6464
end
6565

66-
sig { params(indexable: IndexablePath).void }
67-
def delete(indexable)
68-
# For each constant discovered in `path`, delete the associated entry from the index. If there are no entries
69-
# left, delete the constant from the index.
70-
@files_to_entries[indexable.full_path]&.each do |entry|
71-
name = entry.name
72-
entries = @entries[name]
73-
next unless entries
74-
75-
# Delete the specific entry from the list for this name
76-
entries.delete(entry)
77-
78-
# If all entries were deleted, then remove the name from the hash and from the prefix tree. Otherwise, update
79-
# the prefix tree with the current entries
80-
if entries.empty?
81-
@entries.delete(name)
82-
@entries_tree.delete(name)
83-
else
84-
@entries_tree.insert(name, entries)
66+
sig { params(uri: Uri).void }
67+
def delete(uri)
68+
path = uri.to_standardized_path
69+
70+
if path
71+
# For each constant discovered in `path`, delete the associated entry from the index. If there are no entries
72+
# left, delete the constant from the index.
73+
@files_to_entries[path]&.each do |entry|
74+
name = entry.name
75+
entries = @entries[name]
76+
next unless entries
77+
78+
# Delete the specific entry from the list for this name
79+
entries.delete(entry)
80+
81+
# If all entries were deleted, then remove the name from the hash and from the prefix tree. Otherwise, update
82+
# the prefix tree with the current entries
83+
if entries.empty?
84+
@entries.delete(name)
85+
@entries_tree.delete(name)
86+
else
87+
@entries_tree.insert(name, entries)
88+
end
8589
end
86-
end
8790

88-
@files_to_entries.delete(indexable.full_path)
91+
@files_to_entries.delete(path)
92+
end
8993

90-
require_path = indexable.require_path
94+
require_path = uri.require_path
9195
@require_paths_tree.delete(require_path) if require_path
9296
end
9397

@@ -105,7 +109,7 @@ def [](fully_qualified_name)
105109
@entries[fully_qualified_name.delete_prefix("::")]
106110
end
107111

108-
sig { params(query: String).returns(T::Array[IndexablePath]) }
112+
sig { params(query: String).returns(T::Array[Uri]) }
109113
def search_require_paths(query)
110114
@require_paths_tree.search(query)
111115
end
@@ -292,49 +296,53 @@ def resolve(name, nesting, seen_names = [])
292296
nil
293297
end
294298

295-
# Index all files for the given indexable paths, which defaults to what is configured. A block can be used to track
296-
# and control indexing progress. That block is invoked with the current progress percentage and should return `true`
297-
# to continue indexing or `false` to stop indexing.
299+
# Index all files for the given uris, which defaults to what is configured. A block can be used to track and control
300+
# indexing progress. That block is invoked with the current progress percentage and should return `true` to continue
301+
# indexing or `false` to stop indexing.
298302
sig do
299303
params(
300-
indexable_paths: T::Array[IndexablePath],
304+
uris: T::Array[Uri],
301305
block: T.nilable(T.proc.params(progress: Integer).returns(T::Boolean)),
302306
).void
303307
end
304-
def index_all(indexable_paths: @configuration.indexables, &block)
308+
def index_all(uris: @configuration.indexables, &block)
305309
RBSIndexer.new(self).index_ruby_core
306310
# Calculate how many paths are worth 1% of progress
307-
progress_step = (indexable_paths.length / 100.0).ceil
311+
progress_step = (uris.length / 100.0).ceil
308312

309-
indexable_paths.each_with_index do |path, index|
313+
uris.each_with_index do |uri, index|
310314
if block && index % progress_step == 0
311315
progress = (index / progress_step) + 1
312316
break unless block.call(progress)
313317
end
314318

315-
index_single(path)
319+
index_single(uri)
316320
end
317321
end
318322

319-
sig { params(indexable_path: IndexablePath, source: T.nilable(String)).void }
320-
def index_single(indexable_path, source = nil)
321-
content = source || File.read(indexable_path.full_path)
323+
sig { params(uri: Uri, source: T.nilable(String)).void }
324+
def index_single(uri, source = nil)
325+
path = uri.to_standardized_path
326+
# Remove once we support indexing non file URIs
327+
return unless path
328+
329+
content = source || File.read(path)
322330
dispatcher = Prism::Dispatcher.new
323331

324332
result = Prism.parse(content)
325333
listener = DeclarationListener.new(
326334
self,
327335
dispatcher,
328336
result,
329-
indexable_path.full_path,
337+
path,
330338
enhancements: @enhancements,
331339
)
332340
dispatcher.dispatch(result.value)
333341

334342
indexing_errors = listener.indexing_errors.uniq
335343

336-
require_path = indexable_path.require_path
337-
@require_paths_tree.insert(require_path, indexable_path) if require_path
344+
require_path = uri.require_path
345+
@require_paths_tree.insert(require_path, uri) if require_path
338346

339347
if indexing_errors.any?
340348
indexing_errors.each do |error|
@@ -346,7 +354,7 @@ def index_single(indexable_path, source = nil)
346354
# it
347355
rescue SystemStackError => e
348356
if e.backtrace&.first&.include?("prism")
349-
$stderr.puts "Prism error indexing #{indexable_path.full_path}: #{e.message}"
357+
$stderr.puts "Prism error indexing #{uri}: #{e.message}"
350358
else
351359
raise
352360
end
@@ -541,16 +549,17 @@ def instance_variable_completion_candidates(name, owner_name)
541549
variables
542550
end
543551

544-
# Synchronizes a change made to the given indexable path. This method will ensure that new declarations are indexed,
545-
# removed declarations removed and that the ancestor linearization cache is cleared if necessary
546-
sig { params(indexable: IndexablePath).void }
547-
def handle_change(indexable)
548-
original_entries = @files_to_entries[indexable.full_path]
552+
# Synchronizes a change made to the given uri. This method will ensure that new declarations are indexed, removed
553+
# declarations removed and that the ancestor linearization cache is cleared if necessary
554+
sig { params(uri: Uri).void }
555+
def handle_change(uri)
556+
path = T.must(uri.to_standardized_path)
557+
original_entries = @files_to_entries[path]
549558

550-
delete(indexable)
551-
index_single(indexable)
559+
delete(uri)
560+
index_single(uri)
552561

553-
updated_entries = @files_to_entries[indexable.full_path]
562+
updated_entries = @files_to_entries[path]
554563

555564
return unless original_entries && updated_entries
556565

lib/ruby_indexer/lib/ruby_indexer/indexable_path.rb

-29
This file was deleted.

0 commit comments

Comments
 (0)