Sparr
Sparr

Reputation: 7712

How can I use erl_lint to syntax check an Erlang module?

I'm trying to use erl_lint() to build a simple Erlang syntax and style checker. I've gotten far enough to load the file and parse it into Forms and to get erl_lint to partially understand it, but then erl_lint complains about undefined functions that are defined. What am I doing wrong?

erlint.erl :

-module(erlint).
-export([lint/1]).

% based on http://stackoverflow.com/a/28086396/13675

lint(File) -> 
    {ok, B} = file:read_file(File),
    Forms = scan(erl_scan:tokens([],binary_to_list(B),1),[]),
    F = fun(X) -> {ok,Y} = erl_parse:parse_form(X), Y end,
    erl_lint:module([F(X) || X <- Forms],File).

scan({done,{ok,T,N},S},Res) ->
    scan(erl_scan:tokens([],S,N),[T|Res]);
scan(_,Res) ->
    lists:reverse(Res).

hello.erl :

-module(hello).
-export([hello_world/0]).

hello_world() -> io:fwrite("hello, world\n").

attempt to use :

1> c(erlint).
{ok,erlint}
2> erlint:lint("hello.erl").
{error,[{"hello.erl",
         [{2,erl_lint,{undefined_function,{hello_world,0}}}]}],
       []}

Upvotes: 2

Views: 428

Answers (1)

Steve Vinoski
Steve Vinoski

Reputation: 20004

I'm not sure this approach fits with your overall plan, but you could instead compile the input file, extract its abstract forms from the resulting beam, and pass them to erl_lint:

-module(erlint).
-export([lint/1]).

lint(File) ->
    {ok,_,Bin} = compile:file(File,[debug_info,binary]),
    {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(Bin,[abstract_code]),
    erl_lint:module(AC,File).

Let's change your hello.erl to include an unused variable:

-module(hello).
-export([hello_world/0]).

hello_world() ->
    X = io:fwrite("hello, world\n").

We see that this version of erlint:lint/1 correctly reports it:

1> erlint:lint("hello.erl").
{ok,[{"hello.erl",[{5,erl_lint,{unused_var,'X'}}]}]}

If you need them for your overall purposes, note that you can retrieve source code forms from the abstract forms variable AC by calling erl_syntax:form_list(AC).

Upvotes: 2

Related Questions