Skip to content

Commit

Permalink
[feat] Loosen find_references (#831)
Browse files Browse the repository at this point in the history
Prior, find references would take the arity into account. This was
because in elixir, a functin is defined by its name and its
arity. However in practice, you more than not want to see a all the
calls of a function with a given name rather than a specific
head. This is especially true for functions with default arguments.

As a result, this change looks for functions with a given name and any arity.
  • Loading branch information
scohen authored Oct 28, 2024
1 parent 661aa46 commit cda5742
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,18 @@ defmodule Lexical.RemoteControl.CodeIntelligence.References do
end

defp find_references(
{:call, module, function_name, arity},
{:call, module, function_name, _arity},
_analysis,
_position,
include_definitions?
) do
subject = Subject.mfa(module, function_name, arity)
subject = Subject.mfa(module, function_name, "")
subtype = subtype(include_definitions?)

query(subject, type: {:function, :_}, subtype: subtype)
case Store.prefix(subject, type: {:function, :_}, subtype: subtype) do
{:ok, entries} -> Enum.map(entries, &to_location/1)
_ -> []
end
end

defp find_references(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,23 @@ defmodule Lexical.RemoteControl.CodeIntelligence.ReferencesTest do
assert [%Location{} = location] = references(project, "Functions.do_map|(a, b)", code)
assert decorate(code, location.range) =~ "def func(x), do: «do_map(x, & &1 + 1)»"
end

test "are found in function definitions with optional arguments", %{project: project} do
referenced = ~q/
defmodule Functions do
def do_map|(a, b, c \\ 3), do: {a, b, c}
def func(x), do: do_map(x, 3, 5)
def func2(x), do: do_map(x, 3)
end
/

{_, code} = pop_cursor(referenced)

references = references(project, referenced, code)
assert [first, second] = Enum.sort_by(references, & &1.range.start.line)
assert decorate(code, first.range) =~ " def func(x), do: «do_map(x, 3, 5)»"
assert decorate(code, second.range) =~ " def func2(x), do: «do_map(x, 3)»"
end
end

describe "module references" do
Expand Down

0 comments on commit cda5742

Please sign in to comment.