Skip to content

Instantly share code, notes, and snippets.

@kleinernik
Forked from wojtekmach/0_README.md
Last active April 18, 2020 14:59
Show Gist options
  • Save kleinernik/95e6a2c4c4358c1b4d6673db9a86088b to your computer and use it in GitHub Desktop.
Save kleinernik/95e6a2c4c4358c1b4d6673db9a86088b to your computer and use it in GitHub Desktop.
defmodule Import2Alias.CallerTracer do
def trace({:imported_function, meta, module, name, arity}, env) do
Import2Alias.Server.record(env.file, meta[:line], meta[:column], module, name, arity)
:ok
end
def trace(_event, _env) do
:ok
end
end
defmodule Import2Alias.Server do
use Agent
def start_link(module) do
Agent.start_link(fn -> %{module: module, entries: %{}} end, name: __MODULE__)
end
def record(file, line, column, module, name, arity) do
Agent.update(__MODULE__, fn state ->
the_module = state.module
if match?({^the_module, _, _}, {module, name, arity}) do
entry = {line, column, module, name, arity}
Map.update!(state, :entries, fn entries ->
Map.update(entries, file, [entry], &[entry | &1])
end)
else
state
end
end)
end
def entries() do
Agent.get(__MODULE__, & &1.entries)
end
end
defmodule Import2Alias do
def import2alias(alias, entries) do
for {file, entries} <- entries do
lines = File.read!(file) |> String.split("\n")
lines =
Enum.reduce(entries, lines, fn entry, acc ->
{line, column, module, name, arity} = entry
List.update_at(acc, line - 1, fn string ->
if column do
pre = String.slice(string, 0, column - 1)
offset = column - 1 + String.length("#{name}")
post = String.slice(string, offset, String.length(string))
pre <> "#{inspect(alias)}.#{name}" <> post
else
file = Path.relative_to(file, File.cwd!())
IO.puts(
"skipping #{file}:#{line} #{inspect(module)}.#{name}/#{arity}: no column info"
)
string
end
end)
end)
File.write!(file, Enum.join(lines, "\n"))
end
end
end
unless Process.whereis(Mix.State) do
raise("Can't run using elixir import2alias.exs, use mix run")
end
unless Version.match?(System.version(), ">= 1.10.0-rc") do
Mix.raise("Elixir v1.10+ is required!")
end
{module, alias} =
case System.argv() do
[module, alias] -> {Module.concat([module]), Module.concat([alias])}
_ -> Mix.raise("Usage: import2alias.exs MOD ALIAS")
end
Mix.Task.reenable("compile.protocols")
Mix.Task.run("compile.protocols")
{:ok, _} = Import2Alias.Server.start_link(module)
Code.compiler_options(tracers: [Import2Alias.CallerTracer], parser_options: [columns: true])
Mix.Task.reenable("compile.elixir")
Mix.Task.run("compile.elixir", ["--force"])
entries = Import2Alias.Server.entries()
Import2Alias.import2alias(alias, entries)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment