Skip to content

Commit

Permalink
Swap all usages of indexable path for URI
Browse files Browse the repository at this point in the history
  • Loading branch information
vinistock committed Nov 27, 2024
1 parent f80b3e1 commit 1af4abb
Show file tree
Hide file tree
Showing 25 changed files with 209 additions and 217 deletions.
6 changes: 3 additions & 3 deletions exe/ruby-lsp
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ if options[:doctor]

puts "Globbing for indexable files"

index.configuration.indexables.each do |indexable|
puts "indexing: #{indexable.full_path}"
index.index_single(indexable)
index.configuration.indexables.each do |uri|
puts "indexing: #{uri.full_path}"
index.index_single(uri)
end
return
end
Expand Down
6 changes: 3 additions & 3 deletions exe/ruby-lsp-check
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ puts "Verifying that indexing executes successfully. This may take a while..."
index = RubyIndexer::Index.new
indexables = index.configuration.indexables

indexables.each_with_index do |indexable, i|
index.index_single(indexable)
indexables.each_with_index do |uri, i|
index.index_single(uri)
rescue => e
errors[indexable.full_path] = e
errors[uri.full_path] = e
ensure
print("\033[M\033[0KIndexed #{i + 1}/#{indexables.length}") unless ENV["CI"]
end
Expand Down
2 changes: 1 addition & 1 deletion lib/ruby_indexer/lib/ruby_indexer/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def indexables
# Remove user specified patterns
indexables.reject! do |indexable|
excluded_patterns.any? do |pattern|
File.fnmatch?(pattern, indexable.full_path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
File.fnmatch?(pattern, T.must(indexable.full_path), File::FNM_PATHNAME | File::FNM_EXTGLOB)
end
end

Expand Down
69 changes: 39 additions & 30 deletions lib/ruby_indexer/lib/ruby_indexer/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def initialize
@files_to_entries = T.let({}, T::Hash[String, T::Array[Entry]])

# Holds all require paths for every indexed item so that we can provide autocomplete for requires
@require_paths_tree = T.let(PrefixTree[IndexablePath].new, PrefixTree[IndexablePath])
@require_paths_tree = T.let(PrefixTree[URI::Generic].new, PrefixTree[URI::Generic])

# Holds the linearized ancestors list for every namespace
@ancestors = T.let({}, T::Hash[String, T::Array[String]])
Expand All @@ -55,11 +55,14 @@ def register_included_hook(module_name, &hook)
(@included_hooks[module_name] ||= []) << hook
end

sig { params(indexable: IndexablePath).void }
def delete(indexable)
sig { params(uri: URI::Generic).void }
def delete(uri)
full_path = uri.full_path
return unless full_path

# For each constant discovered in `path`, delete the associated entry from the index. If there are no entries
# left, delete the constant from the index.
@files_to_entries[indexable.full_path]&.each do |entry|
@files_to_entries[full_path]&.each do |entry|
name = entry.name
entries = @entries[name]
next unless entries
Expand All @@ -77,9 +80,9 @@ def delete(indexable)
end
end

@files_to_entries.delete(indexable.full_path)
@files_to_entries.delete(full_path)

require_path = indexable.require_path
require_path = uri.require_path
@require_paths_tree.delete(require_path) if require_path
end

Expand All @@ -97,7 +100,7 @@ def [](fully_qualified_name)
@entries[fully_qualified_name.delete_prefix("::")]
end

sig { params(query: String).returns(T::Array[IndexablePath]) }
sig { params(query: String).returns(T::Array[URI::Generic]) }
def search_require_paths(query)
@require_paths_tree.search(query)
end
Expand Down Expand Up @@ -342,16 +345,16 @@ def resolve(name, nesting, seen_names = [])
nil
end

# Index all files for the given indexable paths, which defaults to what is configured. A block can be used to track
# and control indexing progress. That block is invoked with the current progress percentage and should return `true`
# to continue indexing or `false` to stop indexing.
# Index all files for the given URIs, which defaults to what is configured. A block can be used to track and control
# indexing progress. That block is invoked with the current progress percentage and should return `true` to continue
# indexing or `false` to stop indexing.
sig do
params(
indexable_paths: T::Array[IndexablePath],
uris: T::Array[URI::Generic],
block: T.nilable(T.proc.params(progress: Integer).returns(T::Boolean)),
).void
end
def index_all(indexable_paths: @configuration.indexables, &block)
def index_all(uris: @configuration.indexables, &block)
# When troubleshooting an indexing issue, e.g. through irb, it's not obvious that `index_all` will augment the
# existing index values, meaning it may contain 'stale' entries. This check ensures that the user is aware of this
# behavior and can take appropriate action.
Expand All @@ -363,37 +366,40 @@ def index_all(indexable_paths: @configuration.indexables, &block)

RBSIndexer.new(self).index_ruby_core
# Calculate how many paths are worth 1% of progress
progress_step = (indexable_paths.length / 100.0).ceil
progress_step = (uris.length / 100.0).ceil

indexable_paths.each_with_index do |path, index|
uris.each_with_index do |uri, index|
if block && index % progress_step == 0
progress = (index / progress_step) + 1
break unless block.call(progress)
end

index_single(path, collect_comments: false)
index_single(uri, collect_comments: false)
end
end

sig { params(indexable_path: IndexablePath, source: T.nilable(String), collect_comments: T::Boolean).void }
def index_single(indexable_path, source = nil, collect_comments: true)
content = source || File.read(indexable_path.full_path)
sig { params(uri: URI::Generic, source: T.nilable(String), collect_comments: T::Boolean).void }
def index_single(uri, source = nil, collect_comments: true)
full_path = uri.full_path
return unless full_path

content = source || File.read(full_path)
dispatcher = Prism::Dispatcher.new

result = Prism.parse(content)
listener = DeclarationListener.new(
self,
dispatcher,
result,
indexable_path.full_path,
full_path,
collect_comments: collect_comments,
)
dispatcher.dispatch(result.value)

indexing_errors = listener.indexing_errors.uniq

require_path = indexable_path.require_path
@require_paths_tree.insert(require_path, indexable_path) if require_path
require_path = uri.require_path
@require_paths_tree.insert(require_path, uri) if require_path

if indexing_errors.any?
indexing_errors.each do |error|
Expand All @@ -405,7 +411,7 @@ def index_single(indexable_path, source = nil, collect_comments: true)
# it
rescue SystemStackError => e
if e.backtrace&.first&.include?("prism")
$stderr.puts "Prism error indexing #{indexable_path.full_path}: #{e.message}"
$stderr.puts "Prism error indexing #{T.must(full_path)}: #{e.message}"
else
raise
end
Expand Down Expand Up @@ -600,16 +606,19 @@ def instance_variable_completion_candidates(name, owner_name)
variables
end

# Synchronizes a change made to the given indexable path. This method will ensure that new declarations are indexed,
# removed declarations removed and that the ancestor linearization cache is cleared if necessary
sig { params(indexable: IndexablePath).void }
def handle_change(indexable)
original_entries = @files_to_entries[indexable.full_path]
# Synchronizes a change made to the given URI. This method will ensure that new declarations are indexed, removed
# declarations removed and that the ancestor linearization cache is cleared if necessary
sig { params(uri: URI::Generic).void }
def handle_change(uri)
full_path = uri.full_path
return unless full_path

original_entries = @files_to_entries[full_path]

delete(indexable)
index_single(indexable)
delete(uri)
index_single(uri)

updated_entries = @files_to_entries[indexable.full_path]
updated_entries = @files_to_entries[full_path]

return unless original_entries && updated_entries

Expand Down
29 changes: 0 additions & 29 deletions lib/ruby_indexer/lib/ruby_indexer/indexable_path.rb

This file was deleted.

8 changes: 8 additions & 0 deletions lib/ruby_indexer/lib/ruby_indexer/uri.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ def from_path(path:, fragment: nil, scheme: "file", load_path_entry: nil)
sig { returns(T.nilable(String)) }
attr_accessor :require_path

sig { params(load_path_entry: String).void }
def add_require_path_from_load_entry(load_path_entry)
path = to_standardized_path
return unless path

self.require_path = path.delete_prefix("#{load_path_entry}/").delete_suffix(".rb")
end

sig { returns(T.nilable(String)) }
def to_standardized_path
parsed_path = path
Expand Down
1 change: 0 additions & 1 deletion lib/ruby_indexer/ruby_indexer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
require "did_you_mean"

require "ruby_indexer/lib/ruby_indexer/uri"
require "ruby_indexer/lib/ruby_indexer/indexable_path"
require "ruby_indexer/lib/ruby_indexer/declaration_listener"
require "ruby_indexer/lib/ruby_indexer/reference_finder"
require "ruby_indexer/lib/ruby_indexer/enhancement"
Expand Down
17 changes: 11 additions & 6 deletions lib/ruby_indexer/test/classes_and_modules_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ class Foo

assert_entry("Foo", Entry::Class, "/fake/path/foo.rb:0-0:1-3")

@index.delete(IndexablePath.new(nil, "/fake/path/foo.rb"))
@index.delete(URI::Generic.from_path(path: "/fake/path/foo.rb"))
refute_entry("Foo")

assert_no_indexed_entries
Expand Down Expand Up @@ -618,10 +618,12 @@ class ::Qux
end

def test_lazy_comment_fetching_uses_correct_line_breaks_for_rendering
path = "lib/ruby_lsp/node_context.rb"
indexable = IndexablePath.new("#{Dir.pwd}/lib", path)
uri = URI::Generic.from_path(
load_path_entry: "#{Dir.pwd}/lib",
path: "#{Dir.pwd}/lib/ruby_lsp/node_context.rb",
)

@index.index_single(indexable, collect_comments: false)
@index.index_single(uri, collect_comments: false)

entry = @index["RubyLsp::NodeContext"].first

Expand All @@ -632,9 +634,12 @@ def test_lazy_comment_fetching_uses_correct_line_breaks_for_rendering
end

def test_lazy_comment_fetching_does_not_fail_if_file_gets_deleted
indexable = IndexablePath.new("#{Dir.pwd}/lib", "lib/ruby_lsp/does_not_exist.rb")
uri = URI::Generic.from_path(
load_path_entry: "#{Dir.pwd}/lib",
path: "#{Dir.pwd}/lib/ruby_lsp/does_not_exist.rb",
)

@index.index_single(indexable, <<~RUBY, collect_comments: false)
@index.index_single(uri, <<~RUBY, collect_comments: false)
class Foo
end
RUBY
Expand Down
Loading

0 comments on commit 1af4abb

Please sign in to comment.