defmodule MyModule do
# ...
myfunc args do
# ... some code
end
# ...
end
I want to write a mix task that replaces the function call with something else (let’s say a pre-defined string). As far as I know, there is no way to detect where the funcion call ends (that is, the location of the end keyword that closes the do block.
I could make some assumptions, like matching the first end keyword that matches the indentation of the function, but that’s not very safe.
How should I proceed? Should I use the elixir tokenizer on the file and match the do ... end pair? Is there anything in the new code formatter I can use to help me here? Should I just go with my heuristic above?
Not exactly. A macro takes up an AST and returns another AST. What I want is to change the contents of the file so that the function/macro call is replaced by something else. It doesn’t even have to be at compile time. In fact, what I have in mind is a mix task that does the replacement independently of the compilation.
@tmbb How about convert file contents to AST, parse it and traverse? I have created a topic on forum for that, but I did not receive good response. Last time I got an idea how I could write such traverse function myself.
Firstly you need path. With it you can read its contents using File.read/1 function. Then you can use Code.string_to_quoted and finally write a code to perform a lookup for your patterns.
It’s important to remember that same code written differently have slightly different AST, so you need to handle all of it’s cases.
def my_func, do: :ok:
# have different AST than it's equivalent
def my_func do
:ok
end
Anyway if you know all of its cases and handle them in your traverse function then you can do it without problem.
You can translate your AST back to String using Macro.to_string.
If I were to use this approach I’d only work on the AST of the function I want to replace, not the whole module. Doing this to the whole module removes comments from the module. And before printing tbe string you should run the code formatter through it.