善待Erlang 代碼 -- Xref 實踐


Xref 是一個交叉引用工具,通過分析定義的函數間的調用關系,用於查找函數、 模塊、 應用程序和版本之間的依賴關系。

通俗而言,Xref 可以檢查代碼中函數的調用關系。比如在 moduleA 中的 funA 調用了moduleB 中的funB, 但是moduleB 中並未定義funB,此錯誤在代碼編譯期間不能被發現,但是可以通過Xref 檢查。

栗子

使用reabr 創建一個application ,命名為xref_test,目錄結構如下:

 1 $ tree
 2 .
 3 ├── ebin
 4 │   ├── test.beam
 5 │   ├── xref_test.app
 6 │   ├── xref_test_app.beam
 7 │   └── xref_test_sup.beam
 8 ├── rebar
 9 ├── src
10 │   ├── test.erl
11 │   ├── xref_test.app.src
12 │   ├── xref_test_app.erl
13 │   └── xref_test_sup.erl
14 └── xref.config
15  
16 2 directories, 10 files

其中 test.erl 的代碼為:

1 $ cat ./src/test.erl
2 -module(test).
3 -export([start/0]).
4 start() ->
5     test_2:start().

在test module 中定義start/0  函數,其中調用了test_2:start/0 函數,但是此函數並沒有定義。這種情況,必然會引發錯誤,但是在編譯期間,並不能發現。

1 $ ./rebar com
2 ==> xref_test (compile)
3 Compiled src/xref_test_app.erl
4 Compiled src/test.erl
5 Compiled src/xref_test_sup.erl

OK,上述執行是順利完成的。但是在運行時,必然會發生錯誤。

1 1> test:start().
2 ** exception error: undefined function test_2:start/0

那么,怎樣才能在運行之前發現這個錯誤呢?Xref 就應該隆重登場了。

rebar xref 

在rebar 中,集成了xref 工具,相關的配置信息如下:

 1 {xref_warnings, false}.
 2 %% optional extra paths to include in xref:set_library_path/2.
 3 %% specified relative location of rebar.config.
 4 %% e.g. {xref_extra_paths,["../gtknode/src"]}
 5 {xref_extra_paths,[]}.
 6 %% xref checks to run
 7 {xref_checks, [undefined_function_calls, undefined_functions,
 8                locals_not_used, exports_not_used,
 9                deprecated_function_calls, deprecated_functions]}.
10 %% Optional custom xref queries (xref manual has details) specified as
11 %%     {xref_queries, [{query_string(), expected_query_result()},...]}
12 %% The following for example removes all references to mod:*foo/4
13 %% functions from undefined external function calls as those are in a
14 %% generated module
15 {xref_queries,
16  [{"(XC - UC) || (XU - X - B"
17    " - (\"mod\":\".*foo\"/\"4\"))",[]}]}.

在rebar.config 文件中,配置好這些信息,執行:

1 $ ./rebar xref
2 ==> xref_test (xref)
3 Warning: test_2:start/0 is undefined function (Xref)
4 src/test.erl:5: Warning: test:start/0 calls undefined function test_2:start/0 (Xref)
5 ERROR: xref failed while processing /Users/redink/erlang/test/xref_test: rebar_abort

這個時候,錯誤就能夠清晰的看出來了。

xref_runner

xref_runner 是獨立於rebar xref 的一個工具,支持在非rebar 組織的項目中使用xref ,友好度很高。

https://github.com/inaka/xref_runner

在rebar node 組織的Erlang release 中,可以使用xref_runner 方便的對apps 目錄下的application 進行xref 檢查。

 xrefr.config 定義:

 1 $ cat xrefr.config
 2 [
 3    {xref, [
 4             {config, #{dirs => ["./apps/appname/ebin"],
 5                extra_paths => [
 6                 "./deps/***/ebin"]}},
20             {checks, [
21                      undefined_functions
22                      , undefined_function_calls
23                      , locals_not_used
24                      %%, exports_not_used
25                      , deprecated_function_calls
26                      , deprecated_functions
27                      ]},
28             {xref_default, {verbose}}
29           ]
30    }
31 ].

總結

Xref 非常有用,能幫我們在運行之前盡快的發現代碼的錯誤以及潛在的錯誤。

擴展閱讀:

http://www.erlang.org/doc/apps/tools/xref_chapter.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM