某天使用erlang的重构工具wrangler进行重构的时候,发现有一个文件里的代码总是没有被重构。感到很蛋疼的我以为莫非是我的重构脚本出问题了?于是仔细检查,没有问题。那就是wrangler出问题了?然后查看了wrangler返回的结果,发现是在解析该文件的时候出错了,即parse的时候出现错误,返回了解析出错。好吧,那我们来调试wrangler。
wrangler代码简单分析
wrangler是用erlang写的erlang重构服务,他启动之后会在epmd注册一个wrangler服务,我们重构的时候只需要告诉他,在哪个文件的哪一行,我想要重构成什么即可。举个例子,比如我们想重明明某个变量,只需要通过erlang原生rpc调用
wrangler_refacs:rename_var(FileName, Line, Col, NewName, SearchPaths, Context, TabWidth)
(由于版本不同,该函数名称可能会有差异)
即可完成预重构,此时会创造一个重构好的副本,而不是直接修改源文件。然后发送一个confirm指令,将重构Legacy in the grammar
Try to use "query" as an atom in Erlang, e.g. {query, "SELECT * FROM foobar"}. What happens?
syntax error before: ','
This is because 'query' is a reserved word which was reserved for Mnemosyne queries. Never heard of Mnemosyne? That's because it's an archaic way of querying Erlang's built-in database, Mnesia, and has been replaced with Query List Comprehensions (QLC). However, it remains around for backwards compatibility.
You can't use "query" as a function name. You can't tag a tuple with "query". You can't do anything with "query" except invoke a deprecated legacy API which no one uses anymore.
实施到当前文档,也就是修改下文件名。
wrangler本身使用rebar进行编译,所以如果你
现在以重构变量名为例,他的调用过程如下:
wrangler_refacs:rename_var
wrangler_refacs:try_refac
wrangler_refacs:try_to_apply
refac_rename_var:rename_var
wrangler_ast_server:parse_annotate_file
....
在refac_rename_var:rename_var里面,进行了新变量名的合法性判断,然后就开始parse_annotate_file,即解析目标文件。
在对该函数进行调试之后,发现该函数在解析道query的时候出错。query这个关键字是我在mysql库里面作为sql语句执行函数引进的,该库在运行环境中是可以稳定运行的,所以至少该文件是可以通过编译并且稳定使用的。那么为什么wrangler认为query有问题呢?为了简化问题,我建了一个只有一个query函数的erl文件,调用重构函数,发现重构失败,然后将query改成其它名称,重构成功。看来query就是问题所在了。
核对query的问题
Try to use "query" as an atom in Erlang, e.g. {query, "SELECT * FROM foobar"}. What happens?
syntax error before: ','
This is because 'query' is a reserved word which was reserved for Mnemosyne queries. Never heard of Mnemosyne? That's because it's an archaic way of querying Erlang's built-in database, Mnesia, and has been replaced with Query List Comprehensions (QLC). However, it remains around for backwards compatibility.
You can't use "query" as a function name. You can't tag a tuple with "query". You can't do anything with "query" except invoke a deprecated legacy API which no one uses anymore.