2016-03-15 25 views
2

下面是示例Phoenix應用程序的路由器模塊。我想在宏之後注​​入模塊的完整代碼注入函數。如何使用Elixir宏獲取模塊的完整生成代碼

我試過類似Macro.to_string (Macro.expand (Code.string_to_quoted! File.read!("web/router.ex")), __ENV__)的東西,但是它並沒有完全展開這些宏。我如何遞歸地擴展每個宏,即pipeline,plug,scope, pipe_throughget

感謝

defmodule HelloPhoenix.Router do 
    use HelloPhoenix.Web, :router 

    pipeline :browser do 
    plug :accepts, ["html"] 
    plug :fetch_session 
    plug :fetch_flash 
    plug :protect_from_forgery 
    plug :put_secure_browser_headers 
    end 

    pipeline :api do 
    plug :accepts, ["json"] 
    end 

    scope "/", HelloPhoenix do 
    pipe_through :browser # Use the default browser stack 

    get "/", PageController, :index 
    end 

end 

回答

0

這段代碼將反射光束文件回erlang。我沒有針對基於插件的模塊運行它,所以我不知道結果會有多糟糕,但是這會給你任何模塊的最終結果。

def disassemble(beam_file) do 
    beam_file = String.to_char_list(beam_file) 
    {:ok, 
     {_, [{:abstract_code, {_, ac}}]}} = :beam_lib.chunks(beam_file, 
                  [:abstract_code]) 
    :io.fwrite('~s~n', [:erl_prettypr.format(:erl_syntax.form_list(ac))]) 
    end 

原始出處,並詳細信息:http://erlang.org/doc/man/beam_lib.html

注意,此方法需要[模塊]的文件路徑 .beam

+0

太糟糕了,我們不能有靈藥代碼,但因爲我可以讀erlang比elixir更適合我:)謝謝 – niahoo

3

正如你已經正確觀察到的,你需要使用遞歸Macro.expand/1真正擴大所有宏觀層面。有一個內置的設施來達到這個目的:Macro.prewalk/2。這應該讓你開始:

ast 
|> Macro.prewalk(&Macro.expand(&1, __ENV__)) 
|> Macro.to_string 
|> IO.puts 
+0

我不能使它發揮作用。我還發現了一個名爲Mex的包,它似乎無法打印完整的代碼。但是,無論如何感謝,我會修補更多 – niahoo

+0

哦,它似乎檢查模塊不是那麼簡單,對不起。如果你想得到一個快速和骯髒的解決方案,你可以嘗試手動將檢查代碼注入模塊本身,以便你的'__ENV__'在模塊內。現在無法檢查,但您可能會獲得一些成功。 –

相關問題