Skip to content

Commit 9c7ff4d

Browse files
authored
fix(completions): log source code when env fails to build (#404)
Closes #403
1 parent 1ae8ead commit 9c7ff4d

File tree

4 files changed

+60
-66
lines changed

4 files changed

+60
-66
lines changed

lib/next_ls.ex

+19-1
Original file line numberDiff line numberDiff line change
@@ -577,18 +577,36 @@ defmodule NextLS do
577577
def handle_request(%TextDocumentCompletion{params: %{text_document: %{uri: uri}, position: position}}, lsp) do
578578
document = lsp.assigns.documents[uri]
579579

580-
env =
580+
spliced =
581581
document
582582
|> List.update_at(position.line, fn row ->
583583
{front, back} = String.split_at(row, position.character)
584584
String.slice(front, -1..1) <> "__cursor__()" <> back
585585
end)
586586
|> Enum.join("\n")
587+
588+
env =
589+
spliced
587590
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
588591
|> then(fn
589592
{:ok, ast} -> ast
590593
{:error, ast, _} -> ast
591594
end)
595+
|> NextLS.ASTHelpers.find_cursor()
596+
|> then(fn
597+
{:ok, cursor} ->
598+
cursor
599+
600+
{:error, :not_found} ->
601+
NextLS.Logger.warning(lsp.assigns.logger, "Could not locate cursor when building environment")
602+
603+
NextLS.Logger.warning(
604+
lsp.assigns.logger,
605+
"Source code that produced the above warning: #{spliced}"
606+
)
607+
608+
nil
609+
end)
592610
|> NextLS.ASTHelpers.Env.build()
593611

594612
document_slice =

lib/next_ls/helpers/ast_helpers.ex

+15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
defmodule NextLS.ASTHelpers do
22
@moduledoc false
3+
alias Sourceror.Zipper
34

45
defmodule Attributes do
56
@moduledoc false
@@ -152,4 +153,18 @@ defmodule NextLS.ASTHelpers do
152153
end
153154
end)
154155
end
156+
157+
def find_cursor(ast) do
158+
with nil <-
159+
ast
160+
|> Zipper.zip()
161+
|> Zipper.find(fn
162+
{:__cursor__, _, []} -> true
163+
_ -> false
164+
end) do
165+
{:error, :not_found}
166+
else
167+
zipper -> {:ok, zipper}
168+
end
169+
end
155170
end

lib/next_ls/helpers/ast_helpers/env.ex

+6-9
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,11 @@ defmodule NextLS.ASTHelpers.Env do
66
Sourceror.compare_positions(range.start, position) == :lt && Sourceror.compare_positions(range.end, position) == :gt
77
end
88

9-
def build(ast) do
10-
cursor =
11-
ast
12-
|> Zipper.zip()
13-
|> Zipper.find(fn
14-
{:__cursor__, _, _} -> true
15-
_ -> false
16-
end)
9+
def build(nil) do
10+
%{variables: []}
11+
end
1712

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

@@ -75,7 +71,8 @@ defmodule NextLS.ASTHelpers.Env do
7571
acc
7672
end
7773

78-
{def, _, [{_, _, args} | _]} when def in [:def, :defp, :defmacro, :defmacrop] and args != [] and is_inside ->
74+
{def, _, [{_, _, args} | _]}
75+
when def in [:def, :defp, :defmacro, :defmacrop] and args != [] and is_inside ->
7976
{_, vars} =
8077
Macro.prewalk(args, [], fn node, acc ->
8178
case node do

test/next_ls/helpers/ast_helpers/env_test.exs

+20-56
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,7 @@ defmodule NextLS.ASTHelpers.EnvTest do
1919
end
2020
"""
2121

22-
actual =
23-
code
24-
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
25-
|> then(fn
26-
{:ok, ast} -> ast
27-
{:error, ast, _} -> ast
28-
end)
29-
|> NextLS.ASTHelpers.Env.build()
22+
actual = run(code)
3023

3124
assert actual.variables == ["foo", "bar"]
3225
end
@@ -46,14 +39,7 @@ defmodule NextLS.ASTHelpers.EnvTest do
4639
end
4740
"""
4841

49-
actual =
50-
code
51-
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
52-
|> then(fn
53-
{:ok, ast} -> ast
54-
{:error, ast, _} -> ast
55-
end)
56-
|> NextLS.ASTHelpers.Env.build()
42+
actual = run(code)
5743

5844
assert actual.variables == ["two", "one"]
5945
end
@@ -76,14 +62,7 @@ defmodule NextLS.ASTHelpers.EnvTest do
7662
end
7763
"""
7864

79-
actual =
80-
code
81-
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
82-
|> then(fn
83-
{:ok, ast} -> ast
84-
{:error, ast, _} -> ast
85-
end)
86-
|> NextLS.ASTHelpers.Env.build()
65+
actual = run(code)
8766

8867
assert actual.variables == ["baz", "bar", "foo"]
8968
end
@@ -106,14 +85,7 @@ defmodule NextLS.ASTHelpers.EnvTest do
10685
end
10786
"""
10887

109-
actual =
110-
code
111-
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
112-
|> then(fn
113-
{:ok, ast} -> ast
114-
{:error, ast, _} -> ast
115-
end)
116-
|> NextLS.ASTHelpers.Env.build()
88+
actual = run(code)
11789

11890
assert actual.variables == ["three", "two", "one"]
11991
end
@@ -133,14 +105,7 @@ defmodule NextLS.ASTHelpers.EnvTest do
133105
end
134106
"""
135107

136-
actual =
137-
code
138-
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
139-
|> then(fn
140-
{:ok, ast} -> ast
141-
{:error, ast, _} -> ast
142-
end)
143-
|> NextLS.ASTHelpers.Env.build()
108+
actual = run(code)
144109

145110
assert actual.variables == ["foo", "bar"]
146111
end
@@ -161,14 +126,7 @@ defmodule NextLS.ASTHelpers.EnvTest do
161126
end
162127
"""
163128

164-
actual =
165-
code
166-
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
167-
|> then(fn
168-
{:ok, ast} -> ast
169-
{:error, ast, _} -> ast
170-
end)
171-
|> NextLS.ASTHelpers.Env.build()
129+
actual = run(code)
172130

173131
assert actual.variables == ["baz", "bar", "big_bar"]
174132
end
@@ -194,16 +152,22 @@ defmodule NextLS.ASTHelpers.EnvTest do
194152
end
195153
"""
196154

197-
actual =
198-
code
199-
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
200-
|> then(fn
201-
{:ok, ast} -> ast
202-
{:error, ast, _} -> ast
203-
end)
204-
|> NextLS.ASTHelpers.Env.build()
155+
actual = run(code)
205156

206157
assert actual.variables == ["entries"]
207158
end
208159
end
160+
161+
defp run(code) do
162+
{:ok, zip} =
163+
code
164+
|> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}})
165+
|> then(fn
166+
{:ok, ast} -> ast
167+
{:error, ast, _} -> ast
168+
end)
169+
|> NextLS.ASTHelpers.find_cursor()
170+
171+
NextLS.ASTHelpers.Env.build(zip)
172+
end
209173
end

0 commit comments

Comments
 (0)