Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions lib/ruby_lsp/test_reporters/lsp_reporter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,24 @@ def uri_and_line_for(method_object)
zero_based_line = line ? line - 1 : nil
[uri, zero_based_line]
end

# VS Code stores uri.fsPath keys; Dir.pwd may differ in separators / drive case (#3881).
#: (String) -> String
def normalize_path(path)
path.tr("\\", "/").sub(/\A([A-Za-z]):/) { "#{Regexp.last_match(1).downcase}:" }
end

#: (Hash[String, String], ?String) -> String?
def resolve_reporter_port(db, working_directory = Dir.pwd)
return db[working_directory] if db.key?(working_directory)

normalized_pwd = normalize_path(working_directory)
db.each do |stored_path, port|
return port if normalize_path(stored_path) == normalized_pwd
end

nil
end
end

# https://code.visualstudio.com/api/references/vscode-api#Position
Expand Down Expand Up @@ -64,8 +82,11 @@ def initialize
if port
socket(port)
elsif File.exist?(port_db_path)
db = JSON.load_file(port_db_path)
socket(db[Dir.pwd])
db = JSON.load_file(port_db_path) #: Hash[String, String]
resolved_port = self.class.resolve_reporter_port(db)
raise "No reporter port for #{Dir.pwd}" unless resolved_port

socket(resolved_port)
else
# For tests that don't spawn the TCP server
require "stringio"
Expand Down
42 changes: 42 additions & 0 deletions test/test_reporters/lsp_reporter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -168,5 +168,47 @@ def test_uri_and_line_for_converts_to_zero_based_line

assert_equal(one_based_line - 1, line)
end

def test_resolve_reporter_port_matches_windows_path_variants
db = { "d:\\source\\repos\\myproject" => "12345" }

assert_equal(
"12345",
LspReporter.resolve_reporter_port(db, "D:/source/repos/myproject"),
)
assert_equal(
"12345",
LspReporter.resolve_reporter_port(db, "d:\\source\\repos\\myproject"),
)
assert_nil(LspReporter.resolve_reporter_port(db, "D:/other/project"))
end

def test_socket_connects_using_port_db_despite_windows_path_mismatch
server = TCPServer.new("127.0.0.1", 0)
port = server.addr[1].to_s
thread = Thread.new { server.accept }
io = nil #: Socket?

Dir.mktmpdir("ruby-lsp-3881-") do |tmpdir|
ENV.delete("RUBY_LSP_REPORTER_PORT")
Dir.stubs(:tmpdir).returns(tmpdir)
Dir.stubs(:pwd).returns("D:/source/repos/myproject")

port_db_path = File.join(tmpdir, "ruby-lsp", "test_reporter_port_db.json")
FileUtils.mkdir_p(File.dirname(port_db_path))
File.write(port_db_path, { "d:\\source\\repos\\myproject" => port }.to_json)

reporter = LspReporter.new
io = reporter.instance_variable_get(:@io)

assert_kind_of(Socket, io)

accepted = thread.join(1)&.value #: untyped
accepted&.close
end
ensure
io&.close
server.close
end
end
end
Loading