Skip to content

Commit

Permalink
fixup! Add experimental/gotoRelevantFile lsp method
Browse files Browse the repository at this point in the history
  • Loading branch information
jenny-codes committed Feb 27, 2025
1 parent c2a6a8b commit b055a21
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 47 deletions.
62 changes: 33 additions & 29 deletions lib/ruby_lsp/requests/goto_relevant_file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,56 +12,60 @@ class GotoRelevantFile < Request

TEST_KEYWORDS = ["test", "spec", "integration_test"]

sig { params(path: String).void }
def initialize(path)
TEST_PREFIX_PATTERN = /^(#{TEST_KEYWORDS.join("_|")}_)/
TEST_SUFFIX_PATTERN = /(_#{TEST_KEYWORDS.join("|_")})$/
TEST_PATTERN = /#{TEST_PREFIX_PATTERN}|#{TEST_SUFFIX_PATTERN}/

TEST_PREFIX_GLOB = T.let("#{TEST_KEYWORDS.join("_,")}_", String)
TEST_SUFFIX_GLOB = T.let("_#{TEST_KEYWORDS.join(",_")}", String)

#: (String path, String workspace_path) -> void
def initialize(path, workspace_path)
super()

@workspace_path = T.let(Dir.pwd, String)
@path = T.let(path.delete_prefix(@workspace_path), String)
@workspace_path = workspace_path
@path = T.let(path.delete_prefix(workspace_path), String)
end

sig { override.returns(T::Array[String]) }
# @override
#: -> Array[String]
def perform
find_relevant_paths
end

private

sig { returns(T::Array[String]) }
#: -> Array[String]
def find_relevant_paths
workspace_path = Dir.pwd
relative_path = @path.delete_prefix(workspace_path)

candidate_paths = Dir.glob(File.join("**", relevant_filename_pattern(relative_path)))
candidate_paths = Dir.glob(File.join("**", relevant_filename_pattern))
return [] if candidate_paths.empty?

find_most_similar_with_jacaard(relative_path, candidate_paths).map { File.join(workspace_path, _1) }
find_most_similar_with_jacaard(candidate_paths).map { File.join(@workspace_path, _1) }
end

sig { params(path: String).returns(String) }
def relevant_filename_pattern(path)
input_basename = File.basename(path, File.extname(path))

test_prefix_pattern = /^(#{TEST_KEYWORDS.join("_|")}_)/
test_suffix_pattern = /(_#{TEST_KEYWORDS.join("|_")})$/
test_pattern = /#{test_prefix_pattern}|#{test_suffix_pattern}/
#: -> String
def relevant_filename_pattern
input_basename = File.basename(@path, File.extname(@path))

relevant_basename_pattern =
if input_basename.match?(test_pattern)
input_basename.gsub(test_pattern, "")
if input_basename.match?(TEST_PATTERN)
input_basename.gsub(TEST_PATTERN, "")
else
test_prefix_glob = "#{TEST_KEYWORDS.join("_,")}_"
test_suffix_glob = "_#{TEST_KEYWORDS.join(",_")}"

"{{#{test_prefix_glob}}#{input_basename},#{input_basename}{#{test_suffix_glob}}}"
"{{#{TEST_PREFIX_GLOB}}#{input_basename},#{input_basename}{#{TEST_SUFFIX_GLOB}}}"
end

"#{relevant_basename_pattern}#{File.extname(path)}"
"#{relevant_basename_pattern}#{File.extname(@path)}"
end

sig { params(path: String, candidates: T::Array[String]).returns(T::Array[String]) }
def find_most_similar_with_jacaard(path, candidates)
dirs = get_dir_parts(path)
# Using the Jaccard algorithm to determine the similarity between the
# input path and the candidate relevant file paths.
# Ref: https://en.wikipedia.org/wiki/Jaccard_index
# The main idea of this algorithm is to take the size of interaction and divide
# it by the size of union between two sets (in our case the elements in each set
# would be the parts of the path separated by path divider.)
#: (Array[String] candidates) -> Array[String]
def find_most_similar_with_jacaard(candidates)
dirs = get_dir_parts(@path)

_, results = candidates
.group_by do |other_path|
Expand All @@ -74,7 +78,7 @@ def find_most_similar_with_jacaard(path, candidates)
results || []
end

sig { params(path: String).returns(T::Set[String]) }
#: (String path) -> Set[String]
def get_dir_parts(path)
Set.new(File.dirname(path).split(File::SEPARATOR))
end
Expand Down
2 changes: 1 addition & 1 deletion lib/ruby_lsp/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1143,7 +1143,7 @@ def experimental_goto_relevant_file(message)
end

response = {
locations: Requests::GotoRelevantFile.new(path).perform,
locations: Requests::GotoRelevantFile.new(path, @global_state.workspace_path).perform,
}
send_message(Result.new(id: message[:id], response: response))
end
Expand Down
30 changes: 13 additions & 17 deletions test/requests/goto_relevant_file_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,13 @@
require "test_helper"

class GotoRelevantFileTest < Minitest::Test
def setup
Dir.stubs(:pwd).returns("/workspace")
end

def test_when_input_is_test_file_returns_array_of_implementation_file_locations
stub_glob_pattern("**/goto_relevant_file.rb", ["lib/ruby_lsp/requests/goto_relevant_file.rb"])

test_file_path = "/workspace/test/requests/goto_relevant_file_test.rb"
expected = ["/workspace/lib/ruby_lsp/requests/goto_relevant_file.rb"]

result = RubyLsp::Requests::GotoRelevantFile.new(test_file_path).perform
result = RubyLsp::Requests::GotoRelevantFile.new(test_file_path, "/workspace").perform
assert_equal(expected, result)
end

Expand All @@ -26,7 +22,7 @@ def test_when_input_is_implementation_file_returns_array_of_test_file_locations
impl_path = "/workspace/lib/ruby_lsp/requests/goto_relevant_file.rb"
expected = ["/workspace/test/requests/goto_relevant_file_test.rb"]

result = RubyLsp::Requests::GotoRelevantFile.new(impl_path).perform
result = RubyLsp::Requests::GotoRelevantFile.new(impl_path, "/workspace").perform
assert_equal(expected, result)
end

Expand All @@ -44,7 +40,7 @@ def test_return_all_file_locations_that_have_the_same_highest_coefficient
"/workspace/test/integration/some_feature_test.rb",
]

result = RubyLsp::Requests::GotoRelevantFile.new(impl_path).perform
result = RubyLsp::Requests::GotoRelevantFile.new(impl_path, "/workspace").perform
assert_equal(expected.sort, result.sort)
end

Expand All @@ -53,7 +49,7 @@ def test_return_empty_array_when_no_filename_matches
stub_glob_pattern(pattern, [])

file_path = "/workspace/lib/ruby_lsp/requests/nonexistent_file.rb"
result = RubyLsp::Requests::GotoRelevantFile.new(file_path).perform
result = RubyLsp::Requests::GotoRelevantFile.new(file_path, "/workspace").perform
assert_empty(result)
end

Expand All @@ -63,7 +59,7 @@ def test_it_finds_implementation_when_file_has_test_suffix
test_path = "/workspace/test/feature_test.rb"
expected = ["/workspace/lib/feature.rb"]

result = RubyLsp::Requests::GotoRelevantFile.new(test_path).perform
result = RubyLsp::Requests::GotoRelevantFile.new(test_path, "/workspace").perform
assert_equal(expected, result)
end

Expand All @@ -73,7 +69,7 @@ def test_it_finds_implementation_when_file_has_spec_suffix
test_path = "/workspace/spec/feature_spec.rb"
expected = ["/workspace/lib/feature.rb"]

result = RubyLsp::Requests::GotoRelevantFile.new(test_path).perform
result = RubyLsp::Requests::GotoRelevantFile.new(test_path, "/workspace").perform
assert_equal(expected, result)
end

Expand All @@ -83,7 +79,7 @@ def test_it_finds_implementation_when_file_has_integration_test_suffix
test_path = "/workspace/test/feature_integration_test.rb"
expected = ["/workspace/lib/feature.rb"]

result = RubyLsp::Requests::GotoRelevantFile.new(test_path).perform
result = RubyLsp::Requests::GotoRelevantFile.new(test_path, "/workspace").perform
assert_equal(expected, result)
end

Expand All @@ -93,7 +89,7 @@ def test_it_finds_implementation_when_file_has_test_prefix
test_path = "/workspace/test/test_feature.rb"
expected = ["/workspace/lib/feature.rb"]

result = RubyLsp::Requests::GotoRelevantFile.new(test_path).perform
result = RubyLsp::Requests::GotoRelevantFile.new(test_path, "/workspace").perform
assert_equal(expected, result)
end

Expand All @@ -103,7 +99,7 @@ def test_it_finds_implementation_when_file_has_spec_prefix
test_path = "/workspace/test/spec_feature.rb"
expected = ["/workspace/lib/feature.rb"]

result = RubyLsp::Requests::GotoRelevantFile.new(test_path).perform
result = RubyLsp::Requests::GotoRelevantFile.new(test_path, "/workspace").perform
assert_equal(expected, result)
end

Expand All @@ -113,7 +109,7 @@ def test_it_finds_implementation_when_file_has_integration_test_prefix
test_path = "/workspace/test/integration_test_feature.rb"
expected = ["/workspace/lib/feature.rb"]

result = RubyLsp::Requests::GotoRelevantFile.new(test_path).perform
result = RubyLsp::Requests::GotoRelevantFile.new(test_path, "/workspace").perform
assert_equal(expected, result)
end

Expand All @@ -124,7 +120,7 @@ def test_it_finds_tests_for_implementation
impl_path = "/workspace/lib/feature.rb"
expected = ["/workspace/test/feature_test.rb"]

result = RubyLsp::Requests::GotoRelevantFile.new(impl_path).perform
result = RubyLsp::Requests::GotoRelevantFile.new(impl_path, "/workspace").perform
assert_equal(expected, result)
end

Expand All @@ -135,7 +131,7 @@ def test_it_finds_specs_for_implementation
impl_path = "/workspace/lib/feature.rb"
expected = ["/workspace/spec/feature_spec.rb"]

result = RubyLsp::Requests::GotoRelevantFile.new(impl_path).perform
result = RubyLsp::Requests::GotoRelevantFile.new(impl_path, "/workspace").perform
assert_equal(expected, result)
end

Expand All @@ -146,7 +142,7 @@ def test_it_finds_integration_tests_for_implementation
impl_path = "/workspace/lib/feature.rb"
expected = ["/workspace/test/feature_integration_test.rb"]

result = RubyLsp::Requests::GotoRelevantFile.new(impl_path).perform
result = RubyLsp::Requests::GotoRelevantFile.new(impl_path, "/workspace").perform
assert_equal(expected, result)
end

Expand Down

0 comments on commit b055a21

Please sign in to comment.