From 038ef255c31003bdc1e601d46cacd103046ef5c6 Mon Sep 17 00:00:00 2001 From: Eksperimental Date: Thu, 15 Jan 2026 07:11:57 -0500 Subject: [PATCH 1/2] Reorder def clause in `Expert.Protocol.Conversions.to_elixir/2` So they are grouped together by structs. --- apps/expert/lib/expert/protocol/conversions.ex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/expert/lib/expert/protocol/conversions.ex b/apps/expert/lib/expert/protocol/conversions.ex index 808669ce..3723b03e 100644 --- a/apps/expert/lib/expert/protocol/conversions.ex +++ b/apps/expert/lib/expert/protocol/conversions.ex @@ -29,14 +29,14 @@ defmodule Expert.Protocol.Conversions do end end - def to_elixir(%LSPosition{} = position, %Document{} = document) do - to_elixir(position, document.lines) - 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 From ebdead1159038f363fd00bbd0f2eb78d844beb66 Mon Sep 17 00:00:00 2001 From: Eksperimental Date: Thu, 15 Jan 2026 07:13:15 -0500 Subject: [PATCH 2/2] Do not crash when `Expert.Protocol.Conversions.to_elixir/2` receives `nil` as document --- apps/expert/lib/expert/protocol/conversions.ex | 14 +++++++++++++- apps/expert/test/conversions_test.exs | 12 ++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/apps/expert/lib/expert/protocol/conversions.ex b/apps/expert/lib/expert/protocol/conversions.ex index 3723b03e..0c4a6b34 100644 --- a/apps/expert/lib/expert/protocol/conversions.ex +++ b/apps/expert/lib/expert/protocol/conversions.ex @@ -29,6 +29,10 @@ defmodule Expert.Protocol.Conversions do end end + def to_elixir(%LSRange{}, nil) do + {:error, {:invalid_document, nil}} + end + def to_elixir(%ElixirPosition{} = position, _) do {:ok, position} end @@ -41,6 +45,10 @@ defmodule Expert.Protocol.Conversions 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