Skip to content

Commit ccfd63b

Browse files
committed
Prevent relative require completion for unsaved files (#3656)
### Motivation If a user is typing a `require_relative` in an unsaved file, we have no way of providing completion since we don't know where the user intends to save the file and the path needs to be relative to that. This currently crashes the request, but we can simply protect the code from this and return empty completions. ### Implementation Started returning early if the `full_path` of the URI is `nil` (which means the file is unsaved and we don't know what the file system path is). ### Automated Tests Added a test that reproduces the same crash.
1 parent 290edfc commit ccfd63b

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

lib/ruby_lsp/listeners/completion.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,11 +445,14 @@ def complete_require_relative(node)
445445
return unless arguments_node
446446

447447
path_node_to_complete = arguments_node.arguments.first
448-
449448
return unless path_node_to_complete.is_a?(Prism::StringNode)
450449

451-
origin_dir = Pathname.new(@uri.to_standardized_path).dirname
450+
# If the file is unsaved (e.g.: untitled:Untitled-1), we can't provide relative completion as we don't know
451+
# where the user intends to save it
452+
full_path = @uri.to_standardized_path
453+
return unless full_path
452454

455+
origin_dir = Pathname.new(full_path).dirname
453456
content = path_node_to_complete.content
454457
# if the path is not a directory, glob all possible next characters
455458
# for example ../somethi| (where | is the cursor position)

test/requests/completion_test.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1761,6 +1761,25 @@ def baz
17611761
end
17621762
end
17631763

1764+
def test_require_relative_returns_empty_result_for_unsaved_files
1765+
prefix = "support/"
1766+
source = <<~RUBY
1767+
require_relative "#{prefix}"
1768+
RUBY
1769+
end_char = source.rindex('"') #: as !nil
1770+
1771+
with_server(source, URI("untitled:Untitled-1")) do |server, uri|
1772+
with_file_structure(server) do
1773+
server.process_message(id: 1, method: "textDocument/completion", params: {
1774+
textDocument: { uri: uri },
1775+
position: { line: 0, character: end_char },
1776+
})
1777+
1778+
assert_empty(server.pop_response.response)
1779+
end
1780+
end
1781+
end
1782+
17641783
private
17651784

17661785
def with_file_structure(server, &block)

0 commit comments

Comments
 (0)