Skip to content

Commit

Permalink
fix(completions): log source code when env fails to build (#404)
Browse files Browse the repository at this point in the history
Closes #403
  • Loading branch information
mhanberg authored Apr 1, 2024
1 parent 1ae8ead commit 9c7ff4d
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 66 deletions.
20 changes: 19 additions & 1 deletion lib/next_ls.ex
Original file line number Diff line number Diff line change
Expand Up @@ -577,18 +577,36 @@ defmodule NextLS do
def handle_request(%TextDocumentCompletion{params: %{text_document: %{uri: uri}, position: position}}, lsp) do
document = lsp.assigns.documents[uri]

env =
spliced =
document
|> List.update_at(position.line, fn row ->
{front, back} = String.split_at(row, position.character)
String.slice(front, -1..1) <> "__cursor__()" <> back
end)
|> Enum.join("\n")

env =
spliced
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
|> then(fn
{:ok, ast} -> ast
{:error, ast, _} -> ast
end)
|> NextLS.ASTHelpers.find_cursor()
|> then(fn
{:ok, cursor} ->
cursor

{:error, :not_found} ->
NextLS.Logger.warning(lsp.assigns.logger, "Could not locate cursor when building environment")

NextLS.Logger.warning(
lsp.assigns.logger,
"Source code that produced the above warning: #{spliced}"
)

nil
end)
|> NextLS.ASTHelpers.Env.build()

document_slice =
Expand Down
15 changes: 15 additions & 0 deletions lib/next_ls/helpers/ast_helpers.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule NextLS.ASTHelpers do
@moduledoc false
alias Sourceror.Zipper

defmodule Attributes do
@moduledoc false
Expand Down Expand Up @@ -152,4 +153,18 @@ defmodule NextLS.ASTHelpers do
end
end)
end

def find_cursor(ast) do
with nil <-
ast
|> Zipper.zip()
|> Zipper.find(fn
{:__cursor__, _, []} -> true
_ -> false
end) do
{:error, :not_found}
else
zipper -> {:ok, zipper}
end
end
end
15 changes: 6 additions & 9 deletions lib/next_ls/helpers/ast_helpers/env.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,11 @@ defmodule NextLS.ASTHelpers.Env do
Sourceror.compare_positions(range.start, position) == :lt && Sourceror.compare_positions(range.end, position) == :gt
end

def build(ast) do
cursor =
ast
|> Zipper.zip()
|> Zipper.find(fn
{:__cursor__, _, _} -> true
_ -> false
end)
def build(nil) do
%{variables: []}
end

def build(cursor) do
position = cursor |> Zipper.node() |> Sourceror.get_range() |> Map.get(:start)
zipper = Zipper.prev(cursor)

Expand Down Expand Up @@ -75,7 +71,8 @@ defmodule NextLS.ASTHelpers.Env do
acc
end

{def, _, [{_, _, args} | _]} when def in [:def, :defp, :defmacro, :defmacrop] and args != [] and is_inside ->
{def, _, [{_, _, args} | _]}
when def in [:def, :defp, :defmacro, :defmacrop] and args != [] and is_inside ->
{_, vars} =
Macro.prewalk(args, [], fn node, acc ->
case node do
Expand Down
76 changes: 20 additions & 56 deletions test/next_ls/helpers/ast_helpers/env_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,7 @@ defmodule NextLS.ASTHelpers.EnvTest do
end
"""

actual =
code
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
|> then(fn
{:ok, ast} -> ast
{:error, ast, _} -> ast
end)
|> NextLS.ASTHelpers.Env.build()
actual = run(code)

assert actual.variables == ["foo", "bar"]
end
Expand All @@ -46,14 +39,7 @@ defmodule NextLS.ASTHelpers.EnvTest do
end
"""

actual =
code
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
|> then(fn
{:ok, ast} -> ast
{:error, ast, _} -> ast
end)
|> NextLS.ASTHelpers.Env.build()
actual = run(code)

assert actual.variables == ["two", "one"]
end
Expand All @@ -76,14 +62,7 @@ defmodule NextLS.ASTHelpers.EnvTest do
end
"""

actual =
code
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
|> then(fn
{:ok, ast} -> ast
{:error, ast, _} -> ast
end)
|> NextLS.ASTHelpers.Env.build()
actual = run(code)

assert actual.variables == ["baz", "bar", "foo"]
end
Expand All @@ -106,14 +85,7 @@ defmodule NextLS.ASTHelpers.EnvTest do
end
"""

actual =
code
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
|> then(fn
{:ok, ast} -> ast
{:error, ast, _} -> ast
end)
|> NextLS.ASTHelpers.Env.build()
actual = run(code)

assert actual.variables == ["three", "two", "one"]
end
Expand All @@ -133,14 +105,7 @@ defmodule NextLS.ASTHelpers.EnvTest do
end
"""

actual =
code
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
|> then(fn
{:ok, ast} -> ast
{:error, ast, _} -> ast
end)
|> NextLS.ASTHelpers.Env.build()
actual = run(code)

assert actual.variables == ["foo", "bar"]
end
Expand All @@ -161,14 +126,7 @@ defmodule NextLS.ASTHelpers.EnvTest do
end
"""

actual =
code
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
|> then(fn
{:ok, ast} -> ast
{:error, ast, _} -> ast
end)
|> NextLS.ASTHelpers.Env.build()
actual = run(code)

assert actual.variables == ["baz", "bar", "big_bar"]
end
Expand All @@ -194,16 +152,22 @@ defmodule NextLS.ASTHelpers.EnvTest do
end
"""

actual =
code
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
|> then(fn
{:ok, ast} -> ast
{:error, ast, _} -> ast
end)
|> NextLS.ASTHelpers.Env.build()
actual = run(code)

assert actual.variables == ["entries"]
end
end

defp run(code) do
{:ok, zip} =
code
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
|> then(fn
{:ok, ast} -> ast
{:error, ast, _} -> ast
end)
|> NextLS.ASTHelpers.find_cursor()

NextLS.ASTHelpers.Env.build(zip)
end
end

0 comments on commit 9c7ff4d

Please sign in to comment.