diff --git a/apps/expert/lib/expert/protocol/conversions.ex b/apps/expert/lib/expert/protocol/conversions.ex index 808669ce..0c4a6b34 100644 --- a/apps/expert/lib/expert/protocol/conversions.ex +++ b/apps/expert/lib/expert/protocol/conversions.ex @@ -29,18 +29,26 @@ defmodule Expert.Protocol.Conversions do end end - def to_elixir(%LSPosition{} = position, %Document{} = document) do - to_elixir(position, document.lines) + def to_elixir(%LSRange{}, nil) do + {:error, {:invalid_document, nil}} end def to_elixir(%ElixirPosition{} = position, _) do {:ok, position} end + def to_elixir(%LSPosition{} = position, %Document{} = document) do + to_elixir(position, document.lines) + end + def to_elixir(%LSPosition{line: line} = position, _) when line < 0 do {:error, {:invalid_position, position}} end + def to_elixir(%LSPosition{}, nil) do + {:error, {:invalid_document, nil}} + end + def to_elixir(%LSPosition{} = position, %Lines{} = lines) do line_count = Lines.size(lines) # we need to handle out of bounds line numbers, because it's possible to build a document @@ -68,7 +76,7 @@ defmodule Expert.Protocol.Conversions do end end - def to_elixir(%{range: %{start: start_pos, end: end_pos}}, document) do + def to_elixir(%{range: %{start: start_pos, end: end_pos}}, %Document{} = document) do # this is actually an elixir sense range... note that it's a bare map with # column keys rather than character keys. %{line: start_line, column: start_col} = start_pos @@ -83,6 +91,10 @@ defmodule Expert.Protocol.Conversions do {:ok, range} end + def to_elixir(%{range: %{start: _start_pos, end: _end_pos}}, nil) do + {:error, {:invalid_document, nil}} + end + def to_lsp(%LSRange{start: %LSPosition{}, end: %LSPosition{}} = ls_range) do {:ok, ls_range} end diff --git a/apps/expert/test/conversions_test.exs b/apps/expert/test/conversions_test.exs index 6cfab18a..b4626298 100644 --- a/apps/expert/test/conversions_test.exs +++ b/apps/expert/test/conversions_test.exs @@ -64,6 +64,18 @@ defmodule Expert.Protocol.ConversionsTest do assert {:ok, pos} = Conversions.to_elixir(lsp_position(8, 2), doc("abcde\n1234")) assert %ExPosition{line: 3, character: 1} = pos end + + test "document is nil" do + assert Conversions.to_elixir( + %GenLSP.Structures.Range{end: lsp_position(0, 0), start: lsp_position(0, 0)}, + nil + ) == {:error, {:invalid_document, nil}} + + assert Conversions.to_elixir(lsp_position(0, 0), nil) == {:error, {:invalid_document, nil}} + + assert Conversions.to_elixir(%{range: %{start: 0, end: 0}}, nil) == + {:error, {:invalid_document, nil}} + end end describe "to_lsp/2 for positions" do