Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't find definition when module is aliased in a macro #156

Closed
lexun opened this issue May 12, 2022 · 2 comments
Closed

Can't find definition when module is aliased in a macro #156

lexun opened this issue May 12, 2022 · 2 comments

Comments

@lexun
Copy link

lexun commented May 12, 2022

The metadata builder currently expands calls to use, updating the Env to account for aliases made within a __using__ macro, which is great! However, the same thing does not appear to be done for other macros that may create aliases. This means we are unable to find the definition of functions for which the module was aliased in any macro besides __using__.

This is what currently works, given my_code.ex:

defmodule MyMacro do
  defmacro __using__(node) do
    quote do
      alias unquote(node)
    end
  end
end

defmodule Namespace.MyDep do
  def my_function(), do: "Hello"
end
iex(1)> buffer = """
defmodule MyCaller do
  use MyMacro, Namespace.MyDep

  def call() do
    MyDep.my_function()
    #        ^
  end
end
"""

iex(2)> ElixirSense.definition(buffer, 5, 14)
%ElixirSense.Location{
  column: 7,
  file: "./my_code.ex",
  line: 10,
  type: :function
}

As for what's lacking, note this very similar version of my_code.ex:

defmodule MyMacro do
  defmacro my_alias(node) do
    quote do
      alias unquote(node)
    end
  end
end

defmodule Namespace.MyDep do
  def my_function(), do: "Hello"
end
iex(1)> buffer = """
defmodule MyCaller do
  import MyMacro
  my_alias Namespace.MyDep

  def call() do
    MyDep.my_function()
    #        ^
  end
end
"""

iex(2)> ElixirSense.definition(buffer, 6, 14)
nil

Does anyone see a reason we couldn't or shouldn't do the same thing for all macro calls? Would a pull request be welcome?

My motivation for this is that I'm working on an experimental dependency injection library that currently suffers from not being able to jump to the definition of functions belonging to injected modules. Addressing this seems like it would be one way to solve at least part of the problem.

@lukaszsamson
Copy link
Collaborator

Well, it may be possible to expand more macros but it would require care. Please note that a lot of elixir keywords are macros and currently MatadataBuilder has special rules for them. The expansion should probably have lower priority than elixir keywords. Moreover, the AST after expansion is not like the standard elixir AST and doe's not alow for getting as much info as the standard one.
The mechanism is also quite fragile - see elixir-lsp/elixir-ls#193

@lexun
Copy link
Author

lexun commented May 16, 2022

Thank you for the info, it's much appreciated! I've got some other things to investigate before I can decide where to go with this, so I may or may not circle back later. I'll close the issue for now, but feel free to re-open if it's something you'd like to track.

@lexun lexun closed this as completed May 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants