Skip to content

Commit 3cecf51

Browse files
authoredMay 9, 2024··
fix(completions): dont leak <- matches from for/with (#454)
Closes #447
1 parent 5540ee3 commit 3cecf51

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed
 

‎priv/monkey/_next_ls_private_compiler.ex

+23
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,29 @@ if Version.match?(System.version(), ">= 1.17.0-dev") do
15451545
{{{:., meta, [module, fun]}, meta, args}, state, env}
15461546
end
15471547

1548+
defp expand_local(meta, fun, args, state, env) when fun in [:for, :with] do
1549+
{params, blocks} =
1550+
Enum.split_while(args, fn
1551+
{:<-, _, _} -> true
1552+
_ -> false
1553+
end)
1554+
1555+
{_, state, penv} =
1556+
for p <- params, reduce: {nil, state, env} do
1557+
{_, state, penv} ->
1558+
expand_pattern(p, state, penv)
1559+
end
1560+
1561+
{blocks, state} =
1562+
for {type, block} <- blocks, reduce: {[], state} do
1563+
{acc, state} ->
1564+
{res, state, _env} = expand(block, state, penv)
1565+
{[{type, res} | acc], state}
1566+
end
1567+
1568+
{blocks, state, env}
1569+
end
1570+
15481571
defp expand_local(meta, fun, args, state, env) do
15491572
# A compiler may want to emit a :local_function trace in here.
15501573
{args, state, env} = expand_list(args, state, env)

‎test/next_ls/completions_test.exs

+74
Original file line numberDiff line numberDiff line change
@@ -735,4 +735,78 @@ defmodule NextLS.CompletionsTest do
735735
assert_match %{"kind" => 6, "label" => "var"} in results
736736
assert_match %{"kind" => 6, "label" => "vim"} in results
737737
end
738+
739+
test "<- matches dont leak from for", %{client: client, foo: foo} do
740+
uri = uri(foo)
741+
742+
did_open(client, foo, """
743+
defmodule Foo do
744+
def run(items) do
745+
names =
746+
for item <- items do
747+
item.name
748+
end
749+
750+
i
751+
end
752+
end
753+
""")
754+
755+
request client, %{
756+
method: "textDocument/completion",
757+
id: 2,
758+
jsonrpc: "2.0",
759+
params: %{
760+
textDocument: %{
761+
uri: uri
762+
},
763+
position: %{
764+
line: 7,
765+
character: 5
766+
}
767+
}
768+
}
769+
770+
assert_result 2, results
771+
772+
assert_match %{"kind" => 6, "label" => "items"} in results
773+
assert_match %{"kind" => 6, "label" => "item"} not in results
774+
end
775+
776+
test "<- matches dont leak from with", %{client: client, foo: foo} do
777+
uri = uri(foo)
778+
779+
did_open(client, foo, """
780+
defmodule Foo do
781+
def run(items) do
782+
names =
783+
with item <- items do
784+
item.name
785+
end
786+
787+
i
788+
end
789+
end
790+
""")
791+
792+
request client, %{
793+
method: "textDocument/completion",
794+
id: 2,
795+
jsonrpc: "2.0",
796+
params: %{
797+
textDocument: %{
798+
uri: uri
799+
},
800+
position: %{
801+
line: 7,
802+
character: 5
803+
}
804+
}
805+
}
806+
807+
assert_result 2, results
808+
809+
assert_match %{"kind" => 6, "label" => "items"} in results
810+
assert_match %{"kind" => 6, "label" => "item"} not in results
811+
end
738812
end

0 commit comments

Comments
 (0)
Please sign in to comment.