Skip to content

Commit

Permalink
fix invalid vars suggestions in guards
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaszsamson committed Feb 3, 2020
1 parent 7a58141 commit 1037edf
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 3 deletions.
9 changes: 7 additions & 2 deletions lib/elixir_sense/core/metadata_builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ defmodule ElixirSense.Core.MetadataBuilder do
|> result(ast)
end

defp pre_clause({_, [line: line, column: _column], _} = ast, state, lhs) do
defp pre_clause({_clause, [line: line, column: _column], _} = ast, state, lhs) do
state
|> new_alias_scope
|> new_import_scope
Expand Down Expand Up @@ -408,7 +408,7 @@ defmodule ElixirSense.Core.MetadataBuilder do
]},
state
)
when def_name in [:defguard, :defguardp] do
when def_name in @defs do
ast_without_params = {def_name, meta, [{name, add_no_call(meta2), []}, body]}
pre_func(ast_without_params, state, %{line: line, col: column}, name, params)
end
Expand Down Expand Up @@ -1017,6 +1017,11 @@ defmodule ElixirSense.Core.MetadataBuilder do
{ast, [var_info | vars]}
end

# drop right side of guard expression as guards cannot define vars
defp match_var({:when, _, [left, _right]}, vars) do
match_var(left, vars)
end

defp match_var(ast, vars) do
{ast, vars}
end
Expand Down
49 changes: 48 additions & 1 deletion test/elixir_sense/core/metadata_builder_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ defmodule ElixirSense.Core.MetadataBuilderTest do
"""
defmodule MyModule do
var_out1 = 1
def func(%{key1: par1, key2: [par2|[par3, _]]}, par4) do
def func(%{key1: par1, key2: [par2|[par3, _]]}, par4, _par5) do
var_in1 = 1
var_in2 = 1
IO.puts ""
Expand Down Expand Up @@ -150,6 +150,53 @@ defmodule ElixirSense.Core.MetadataBuilderTest do
]
end

test "guards do not define vars" do
state =
"""
defmodule MyModule do
def func1(a) when is_integer(b) do
IO.puts("")
end
def func2(a) when is_integer(b) or is_list(c) do
IO.puts("")
end
def func3(a) when is_integer(b) when is_list(c) do
IO.puts("")
end
case x do
y when is_integer(z) ->
IO.puts("")
end
with x when is_integer(y) <- z do
IO.puts("")
end
def func3(a) when is_integer(b)
end
"""
|> string_to_state

vars = state |> get_line_vars(3)
assert vars == [%VarInfo{is_definition: false, name: :a, positions: [{2, 13}], scope_id: 2}]

vars = state |> get_line_vars(6)
assert vars == [%VarInfo{is_definition: false, name: :a, positions: [{5, 13}], scope_id: 2}]

vars = state |> get_line_vars(9)
assert vars == [%VarInfo{is_definition: false, name: :a, positions: [{8, 13}], scope_id: 2}]

vars = state |> get_line_vars(14)
assert vars == [%VarInfo{is_definition: false, name: :y, positions: [{13, 5}], scope_id: 7}]

vars = state |> get_line_vars(18)
assert vars == [%VarInfo{is_definition: false, name: :x, positions: [{17, 8}], scope_id: 2}]

vars = state |> get_line_vars(21)
assert vars == [%VarInfo{is_definition: false, name: :a, positions: [{21, 13}], scope_id: 2}]
end

test "rebinding vars" do
state =
"""
Expand Down
16 changes: 16 additions & 0 deletions test/elixir_sense/suggestions_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,22 @@ defmodule ElixirSense.SuggestionsTest do
]
end

test "only list defined params in guard" do
buffer = """
defmodule MyServer do
def new(my_var) when is_integer(my
end
"""

list =
ElixirSense.suggestions(buffer, 2, 37)
|> Enum.filter(fn s -> s.type == :variable end)

# TODO hint my_var instead of my

assert list == [%{name: "my_var", type: :variable}]
end

test "lists attributes" do
buffer = """
defmodule MyModule do
Expand Down

0 comments on commit 1037edf

Please sign in to comment.