1
%% -*- erlang-indent-level: 2 -*-
5
%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
7
%% The contents of this file are subject to the Erlang Public License,
8
%% Version 1.1, (the "License"); you may not use this file except in
9
%% compliance with the License. You should have received a copy of the
10
%% Erlang Public License along with this software. If not, it can be
11
%% retrieved online at http://www.erlang.org/.
13
%% Software distributed under the License is distributed on an "AS IS"
14
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
15
%% the License for the specific language governing rights and limitations
20
%%===========================================================================
21
%% File : typer_options.erl
22
%% Author : Bingwen He <Bingwen.He@gmail.com>
23
%% Description : Handles all command-line options given to TypEr
24
%%===========================================================================
26
-module(typer_options).
30
%%---------------------------------------------------------------------------
32
-include("typer.hrl").
34
%%---------------------------------------------------------------------------
36
%%---------------------------------------------------------------------------
38
-spec process() -> {#args{}, #typer_analysis{}}.
41
ArgList = init:get_plain_arguments(),
42
%% io:format("Args is ~p\n",[Args]),
43
{Args, Analysis} = analyze_args(ArgList, #args{}, #typer_analysis{}),
44
%% if the mode has not been set, set it to the default mode (show)
45
{Args, case Analysis#typer_analysis.mode of
46
undefined -> Analysis#typer_analysis{mode = ?SHOW};
47
Mode when is_atom(Mode) -> Analysis
50
%%---------------------------------------------------------------------------
52
%%---------------------------------------------------------------------------
54
analyze_args([], Args, Analysis) ->
56
analyze_args(ArgList, Args, Analysis) ->
57
{Result, Rest} = cl(ArgList),
58
{NewArgs, NewAnalysis} = analyze_result(Result, Args, Analysis),
59
analyze_args(Rest, NewArgs, NewAnalysis).
61
cl(["-h"|_]) -> help_message();
62
cl(["--help"|_]) -> help_message();
63
cl(["-v"|_]) -> version_message();
64
cl(["--version"|_]) -> version_message();
65
cl(["--comments"|Opts]) -> {comments, Opts};
66
cl(["--show"|Opts]) -> {{mode, ?SHOW}, Opts};
67
cl(["--show_exported"|Opts]) -> {{mode, ?SHOW_EXPORTED}, Opts};
68
cl(["--show-exported"|Opts]) -> {{mode, ?SHOW_EXPORTED}, Opts};
69
cl(["--annotate"|Opts]) -> {{mode, ?ANNOTATE}, Opts};
70
cl(["--annotate-inc-files"|Opts]) -> {{mode, ?ANNOTATE_INC_FILES}, Opts};
71
cl(["--plt",Plt|Opts]) -> {{plt, Plt}, Opts};
72
cl(["-D"++Def|Opts]) ->
74
"" -> typer:error("no variable name specified after -D");
76
L = re:split(Def, "=", [{return, list}]),
77
DefPair = process_def_list(L),
78
{{def, DefPair}, Opts}
80
cl(["-I",Dir|Opts]) -> {{inc,Dir}, Opts};
81
cl(["-I"++Dir|Opts]) ->
83
"" -> typer:error("no include directory specified after -I");
84
_ -> {{inc, Dir}, Opts}
87
{Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
89
[] -> typer:error("no file or directory specified after -T");
90
[_|_] -> {{trust, Files}, RestOpts}
93
{Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
94
{{a_dir_r, Files}, RestOpts};
95
cl(["-"++H|_]) -> typer:error("unknown option -"++H);
97
{Args, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
98
{{analyze, Args}, RestOpts}.
100
process_def_list(L) ->
103
{ok, Tokens, _} = erl_scan:string(Value ++ "."),
104
{ok, ErlValue} = erl_parse:parse_term(Tokens),
105
{list_to_atom(Name), ErlValue};
107
{list_to_atom(Name), true}
110
%% Get information about files that the user trusts and wants to analyze
111
analyze_result({analyze, Val}, Args, Analysis) ->
112
NewVal = Args#args.analyze ++ Val,
113
{Args#args{analyze = NewVal}, Analysis};
114
analyze_result({a_dir_r, Val}, Args, Analysis) ->
115
NewVal = Args#args.analyzed_dir_r ++ Val,
116
{Args#args{analyzed_dir_r = NewVal}, Analysis};
117
analyze_result({trust, Val}, Args, Analysis) ->
118
NewVal = Args#args.trust ++ Val,
119
{Args#args{trust = NewVal}, Analysis};
120
analyze_result(comments, Args, Analysis) ->
121
{Args, Analysis#typer_analysis{contracts = false}};
122
%% Get useful information for actual analysis
123
analyze_result({mode, Val}, Args, Analysis) ->
124
case Analysis#typer_analysis.mode of
125
undefined -> {Args, Analysis#typer_analysis{mode = Val}};
128
analyze_result({def, Val}, Args, Analysis) ->
129
NewVal = Analysis#typer_analysis.macros ++ [Val],
130
{Args, Analysis#typer_analysis{macros = NewVal}};
131
analyze_result({inc, Val}, Args, Analysis) ->
132
NewVal = Analysis#typer_analysis.includes ++ [Val],
133
{Args, Analysis#typer_analysis{includes = NewVal}};
134
analyze_result({plt, Plt}, Args, Analysis) ->
135
{Args, Analysis#typer_analysis{plt = Plt}}.
137
%%--------------------------------------------------------------------
139
-spec mode_error() -> no_return().
141
typer:error("can not do \"show\", \"show-exported\", \"annotate\", and \"annotate-inc-files\" at the same time").
143
-spec version_message() -> no_return().
145
io:format("TypEr version "++?VSN++"\n"),
148
-spec help_message() -> no_return().
150
S = " Usage: typer [--help] [--version] [--comments] [--plt PLT]
151
[--show | --show-exported | --annotate | --annotate-inc-files]
152
[-Ddefine]* [-I include_dir]* [-T application]* [-r] file*
156
search directories recursively for .erl files below them
158
Prints type specifications for all functions on stdout.
159
(this is the default behaviour; this option is not really needed)
160
--show-exported (or --show_exported)
161
Same as --show, but prints specifications for exported functions only
162
Specs are displayed sorted alphabetically on the function's name
164
Annotates the specified files with type specifications
166
Same as --annotate but annotates all -include() files as well as
167
all .erl files (use this option with caution - has not been tested much)
169
Prints type information using Edoc comments, not type specs
171
Use the specified dialyzer PLT file rather than the default one
173
The specified file(s) already contain type specifications and these
174
are to be trusted in order to print specs for the rest of the files
175
(Multiple files or dirs, separated by spaces, can be specified.)
176
-Dname (or -Dname=value)
177
pass the defined name(s) to TypEr
178
(The syntax of defines is the same as that used by \"erlc\".)
180
pass the include_dir to TypEr
181
(The syntax of includes is the same as that used by \"erlc\".)
183
prints the Typer version and exits
185
prints this message and exits
188
* denotes that multiple occurrences of these options are possible.