Skip to content

Commit

Permalink
fix(completions): dont leak <- matches from for/with
Browse files Browse the repository at this point in the history
Closes #447
  • Loading branch information
mhanberg committed May 9, 2024
1 parent 5540ee3 commit 9a433eb
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 0 deletions.
23 changes: 23 additions & 0 deletions priv/monkey/_next_ls_private_compiler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1545,6 +1545,29 @@ if Version.match?(System.version(), ">= 1.17.0-dev") do
{{{:., meta, [module, fun]}, meta, args}, state, env}
end

defp expand_local(meta, fun, args, state, env) when fun in [:for, :with] do
{params, blocks} =
Enum.split_while(args, fn
{:<-, _, _} -> true
_ -> false
end)

{_, state, penv} =
for p <- params, reduce: {nil, state, env} do
{_, state, penv} ->
expand_pattern(p, state, penv)
end

{blocks, state} =
for {type, block} <- blocks, reduce: {[], state} do
{acc, state} ->
{res, state, _env} = expand(block, state, penv)
{[{type, res} | acc], state}
end

{blocks, state, env}
end

defp expand_local(meta, fun, args, state, env) do
# A compiler may want to emit a :local_function trace in here.
{args, state, env} = expand_list(args, state, env)
Expand Down
74 changes: 74 additions & 0 deletions test/next_ls/completions_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -735,4 +735,78 @@ defmodule NextLS.CompletionsTest do
assert_match %{"kind" => 6, "label" => "var"} in results
assert_match %{"kind" => 6, "label" => "vim"} in results
end

test "<- matches dont leak from for", %{client: client, foo: foo} do
uri = uri(foo)

did_open(client, foo, """
defmodule Foo do
def run(items) do
names =
for item <- items do
item.name
end
i
end
end
""")

request client, %{
method: "textDocument/completion",
id: 2,
jsonrpc: "2.0",
params: %{
textDocument: %{
uri: uri
},
position: %{
line: 7,
character: 5
}
}
}

assert_result 2, results

assert_match %{"kind" => 6, "label" => "items"} in results
assert_match %{"kind" => 6, "label" => "item"} not in results
end

test "<- matches dont leak from with", %{client: client, foo: foo} do
uri = uri(foo)

did_open(client, foo, """
defmodule Foo do
def run(items) do
names =
with item <- items do
item.name
end
i
end
end
""")

request client, %{
method: "textDocument/completion",
id: 2,
jsonrpc: "2.0",
params: %{
textDocument: %{
uri: uri
},
position: %{
line: 7,
character: 5
}
}
}

assert_result 2, results

assert_match %{"kind" => 6, "label" => "items"} in results
assert_match %{"kind" => 6, "label" => "item"} not in results
end
end

0 comments on commit 9a433eb

Please sign in to comment.