Xref 是一个交叉引用工具,通过分析定义的函数间的调用关系,用于查找函数、 模块、 应用程序和版本之间的依赖关系。

通俗而言,Xref 可以检查代码中函数的调用关系。比如在 moduleA 中的 funA 调用了moduleB 中的funB, 但是moduleB 中并未定义funB,此错误在代码编译期间不能被发现,但是可以通过Xref 检查。

栗子

使用reabr 创建一个application ,命名为xref_test,目录结构如下:

 $ tree
.
├── ebin
│ ├── test.beam
│ ├── xref_test.app
│ ├── xref_test_app.beam
│ └── xref_test_sup.beam
├── rebar
├── src
│ ├── test.erl
│ ├── xref_test.app.src
│ ├── xref_test_app.erl
│ └── xref_test_sup.erl
└── xref.config directories, files

其中 test.erl 的代码为:

 $ cat ./src/test.erl
-module(test).
-export([start/]).
start() ->
test_2:start().

在test module 中定义start/0  函数,其中调用了test_2:start/0 函数,但是此函数并没有定义。这种情况,必然会引发错误,但是在编译期间,并不能发现。

 $ ./rebar com
==> xref_test (compile)
Compiled src/xref_test_app.erl
Compiled src/test.erl
Compiled src/xref_test_sup.erl

OK,上述执行是顺利完成的。但是在运行时,必然会发生错误。

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

那么,怎样才能在运行之前发现这个错误呢?Xref 就应该隆重登场了。

rebar xref

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

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

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

 $ ./rebar xref
==> xref_test (xref)
Warning: test_2:start/ is undefined function (Xref)
src/test.erl:: Warning: test:start/ calls undefined function test_2:start/ (Xref)
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 定义:

 $ cat xrefr.config
[
{xref, [
{config, #{dirs => ["./apps/appname/ebin"],
extra_paths => [
"./deps/***/ebin"]}},
{checks, [
undefined_functions
, undefined_function_calls
, locals_not_used
%%, exports_not_used
, deprecated_function_calls
, deprecated_functions
]},
{xref_default, {verbose}}
]
}
].

总结

Xref 非常有用,能帮我们在运行之前尽快的发现代码的错误以及潜在的错误。

扩展阅读:

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

善待Erlang 代码 -- Xref 实践的更多相关文章

  1. 善待Erlang 代码 -- 巧用 user_default

    这是一篇水文 ----------------------------------------------------- 很好用的一个技巧 http://www.erlang.org/doc/man/ ...

  2. HTML 代码复用实践 (静态页面公共部分提取复用)

    原文:HTML 代码复用实践 上面的链接里面安装配置步骤已经非常详细,这里主要记录我操作过程中遇到的几个问题 gulp-file-include 的使用     按上面的步骤安装之后,node_mod ...

  3. Tsung脚本中使用动态参数(一)---直接在脚本里编写Erlang代码

    杀死一个程序猿,只要改三次需求.同理,杀死一个接口自动化测试人员,只要改三次接口数据处理方式.我目前的状态,改了一次接口数据处理方式,有一种胸闷的感觉. 因为改需求,所以,要改脚本.T_T.所以,才有 ...

  4. elixir 调用erlang 代码

    备注:    项目比较简单,主要是elixir 混合erlang 代码,elixir 调用erlang 模块方法   1. 初始化项目   mix new erlangelixirdemo 项目结构如 ...

  5. 理想的DevOp流程怎么做?看看Slack的代码部署实践 原创 Michael Deng 高可用架构 今天

    理想的DevOp流程怎么做?看看Slack的代码部署实践 原创 Michael Deng  高可用架构  今天

  6. git 操作 :从远程仓库gitLab上拉取指定分支到本地仓库;git如何利用分支进行多人开发 ;多人合作代码提交实践

    例如:将gitLab 上的dev分支拉取到本地 git checkout -b dev origin/dev 在本地创建分支dev并切换到该分支 git pull origin dev 就可以把git ...

  7. 敏捷开发中高质量 Java 代码开发实践

    Java 项目开发过程中,由于开发人员的经验.代码风格各不相同,以及缺乏统一的标准和管理流程,往往导致整个项目的代码质量较差,难于维护,需要较大的测试投入 和周期等问题. 这些问题在一个项目组初建.需 ...

  8. erlang代码片段

    转载自http://blog.csdn.net/sw2wolf/article/details/6797708 .列表操作 lists:foreach(fun(X) -> io:format(& ...

  9. Android ------ 美团的Lint代码检查实践

    概述 Lint是Google提供的Android静态代码检查工具,可以扫描并发现代码中潜在的问题,提醒开发人员及早修正,提高代码质量.除了Android原生提供的几百个Lint规则,还可以开发自定义L ...

随机推荐

  1. uboot能ping通本机无法ping通本机上搭建的虚拟机

    注意 转载请注明出处:https://www.cnblogs.com/dakewei 一.背景 1.1 uboot不能被其它主机ping通,这是由于uboot没有对其它主机发送过来的arp包进行响应, ...

  2. phantomjs学习资料

    http://blog.csdn.net/mecho/article/details/45888465 phantomjs的使用说明,尤其是webpage创建,资源加载前后的处理方法.

  3. Java回顾之反射

    在这一篇文章里,我们关注反射及其相关话题. 反射可以帮助我们查看指定类型中的信息.创建类型的实例,调用类型的方法.我们平时使用框架,例如Spring.EJB.Hibernate等都大量的使用了反射技术 ...

  4. 关闭pm2

    先查找ID pm2 status 然后 pm2 stop id pm2 delete id

  5. session放数据库里解决丢失的问题

    在编程里是会话的意思Session 对象存储特定用户会话所需的信息.这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去. ...

  6. TinyURL

    2018-03-09 15:19:04 TinyURL,短地址,或者叫短链接,指的是一种互联网上的技术与服务.此服务可以提供一个非常短小的URL以代替原来的可能较长的URL,将长的URL地址缩短. 用 ...

  7. javascript中back(-1)和go(-1)的区别

    javascript中back(-1)和go(-1)的区别 一.总结 一句话总结: 数据 history.back(-1):直接返回当前页的上一页,数据全部消息,是个新页面 history.go(-1 ...

  8. gradle ssh 插件

    org.hidetake.ssh Gradle SSH Plugin is a Gradle plugin which provides remote command execution and fi ...

  9. WebApi用Post的方式提交Json时,获取不到值或不进对应方法的问题

    又是一个通宵,终于搞明白了. 被WebApi坑得好惨. 之前用各种方法Post上来,有时可以读到结构,但没值,有时直接就是一个Null,有时连方法都没进就跑了,只是来控制器里看了一下…… 最后好友说还 ...

  10. MVC Ajax Helpers

    在MVC中要实现Ajax有很多的方式,有微软自己的MicrosoftAjax,也可以用JQuery的AJax来实现,如果对其他的JavaScript框架熟悉,还可以采用其他的实现方案,比如说Proto ...