aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/typer/src/Makefile9
-rw-r--r--lib/typer/src/typer.erl176
-rw-r--r--lib/typer/src/typer_options.erl194
3 files changed, 169 insertions, 210 deletions
diff --git a/lib/typer/src/Makefile b/lib/typer/src/Makefile
index 76cd557cc8..f814e943ea 100644
--- a/lib/typer/src/Makefile
+++ b/lib/typer/src/Makefile
@@ -47,8 +47,7 @@ DIALYZER_DIR = $(ERL_TOP)/lib/dialyzer
# ----------------------------------------------------
MODULES = typer \
typer_annotator \
- typer_info \
- typer_options
+ typer_info
HRL_FILES= typer.hrl
ERL_FILES= $(MODULES:%=%.erl)
@@ -84,8 +83,8 @@ clean:
# Special Build Targets
# ----------------------------------------------------
-$(EBIN)/typer_options.$(EMULATOR): typer_options.erl ../vsn.mk Makefile
- erlc -W $(ERL_COMPILE_FLAGS) -DVSN="\"v$(VSN)\"" -o$(EBIN) typer_options.erl
+$(EBIN)/typer.$(EMULATOR): typer.erl ../vsn.mk Makefile
+ erlc -W $(ERL_COMPILE_FLAGS) -DVSN="\"v$(VSN)\"" -o$(EBIN) typer.erl
$(APP_TARGET): $(APP_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
@@ -100,8 +99,6 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
$(EBIN)/typer.beam: typer.hrl
$(EBIN)/typer_annotator.beam: typer.hrl
$(EBIN)/typer_info.beam: typer.hrl
-$(EBIN)/typer_options.beam: typer.hrl
-$(EBIN)/typer_preprocess.beam: typer.hrl
# ----------------------------------------------------
# Release Target
diff --git a/lib/typer/src/typer.erl b/lib/typer/src/typer.erl
index 3f1302ecc9..54818553da 100644
--- a/lib/typer/src/typer.erl
+++ b/lib/typer/src/typer.erl
@@ -80,7 +80,7 @@
-spec start() -> no_return().
start() ->
- {Args, Analysis} = typer_options:process(),
+ {Args, Analysis} = process_cl_args(),
%% io:format("Args: ~p\n", [Args]),
%% io:format("Analysis: ~p\n", [Analysis]),
TrustedFiles = filter_fd(Args#args.trusted, [], fun is_erl_file/1),
@@ -189,8 +189,7 @@ remove_external(CallGraph, PLT) ->
ExtTypes = rcv_ext_types(),
case ExtTypes of
[] -> ok;
- _ ->
- msg(io_lib:format(" Unknown types: ~p\n", [ExtTypes]))
+ _ -> msg(io_lib:format(" Unknown types: ~p\n", [ExtTypes]))
end
end,
StrippedCG.
@@ -211,12 +210,113 @@ get_external(Exts, Plt) ->
lists:foldl(Fun, [], Exts).
%%--------------------------------------------------------------------
+%% Processing of command-line options and arguments.
+%%--------------------------------------------------------------------
+
+-spec process_cl_args() -> {#args{}, #typer_analysis{}}.
+
+process_cl_args() ->
+ ArgList = init:get_plain_arguments(),
+ %% io:format("Args is ~p\n", [ArgList]),
+ {Args, Analysis} = analyze_args(ArgList, #args{}, #typer_analysis{}),
+ %% if the mode has not been set, set it to the default mode (show)
+ {Args, case Analysis#typer_analysis.mode of
+ undefined -> Analysis#typer_analysis{mode = ?SHOW};
+ Mode when is_atom(Mode) -> Analysis
+ end}.
+
+analyze_args([], Args, Analysis) ->
+ {Args, Analysis};
+analyze_args(ArgList, Args, Analysis) ->
+ {Result, Rest} = cl(ArgList),
+ {NewArgs, NewAnalysis} = analyze_result(Result, Args, Analysis),
+ analyze_args(Rest, NewArgs, NewAnalysis).
+
+cl(["-h"|_]) -> help_message();
+cl(["--help"|_]) -> help_message();
+cl(["-v"|_]) -> version_message();
+cl(["--version"|_]) -> version_message();
+cl(["--comments"|Opts]) -> {comments, Opts};
+cl(["--show"|Opts]) -> {{mode, ?SHOW}, Opts};
+cl(["--show_exported"|Opts]) -> {{mode, ?SHOW_EXPORTED}, Opts};
+cl(["--show-exported"|Opts]) -> {{mode, ?SHOW_EXPORTED}, Opts};
+cl(["--annotate"|Opts]) -> {{mode, ?ANNOTATE}, Opts};
+cl(["--annotate-inc-files"|Opts]) -> {{mode, ?ANNOTATE_INC_FILES}, Opts};
+cl(["--no_spec"|Opts]) -> {no_spec, Opts};
+cl(["--plt",Plt|Opts]) -> {{plt, Plt}, Opts};
+cl(["-D"++Def|Opts]) ->
+ case Def of
+ "" -> fatal_error("no variable name specified after -D");
+ _ ->
+ DefPair = process_def_list(re:split(Def, "=", [{return, list}])),
+ {{def, DefPair}, Opts}
+ end;
+cl(["-I",Dir|Opts]) -> {{inc, Dir}, Opts};
+cl(["-I"++Dir|Opts]) ->
+ case Dir of
+ "" -> fatal_error("no include directory specified after -I");
+ _ -> {{inc, Dir}, Opts}
+ end;
+cl(["-T"|Opts]) ->
+ {Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
+ case Files of
+ [] -> fatal_error("no file or directory specified after -T");
+ [_|_] -> {{trusted, Files}, RestOpts}
+ end;
+cl(["-r"|Opts]) ->
+ {Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
+ {{files_r, Files}, RestOpts};
+cl(["-"++H|_]) -> fatal_error("unknown option -"++H);
+cl(Opts) ->
+ {Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
+ {{files, Files}, RestOpts}.
+
+process_def_list(L) ->
+ case L of
+ [Name, Value] ->
+ {ok, Tokens, _} = erl_scan:string(Value ++ "."),
+ {ok, ErlValue} = erl_parse:parse_term(Tokens),
+ {list_to_atom(Name), ErlValue};
+ [Name] ->
+ {list_to_atom(Name), true}
+ end.
+
+%% Get information about files that the user trusts and wants to analyze
+analyze_result({files, Val}, Args, Analysis) ->
+ NewVal = Args#args.files ++ Val,
+ {Args#args{files = NewVal}, Analysis};
+analyze_result({files_r, Val}, Args, Analysis) ->
+ NewVal = Args#args.files_r ++ Val,
+ {Args#args{files_r = NewVal}, Analysis};
+analyze_result({trusted, Val}, Args, Analysis) ->
+ NewVal = Args#args.trusted ++ Val,
+ {Args#args{trusted = NewVal}, Analysis};
+analyze_result(comments, Args, Analysis) ->
+ {Args, Analysis#typer_analysis{contracts = false}};
+%% Get useful information for actual analysis
+analyze_result({mode, Mode}, Args, Analysis) ->
+ case Analysis#typer_analysis.mode of
+ undefined -> {Args, Analysis#typer_analysis{mode = Mode}};
+ OldMode -> mode_error(OldMode, Mode)
+ end;
+analyze_result({def, Val}, Args, Analysis) ->
+ NewVal = Analysis#typer_analysis.macros ++ [Val],
+ {Args, Analysis#typer_analysis{macros = NewVal}};
+analyze_result({inc, Val}, Args, Analysis) ->
+ NewVal = Analysis#typer_analysis.includes ++ [Val],
+ {Args, Analysis#typer_analysis{includes = NewVal}};
+analyze_result({plt, Plt}, Args, Analysis) ->
+ {Args, Analysis#typer_analysis{plt = Plt}};
+analyze_result(no_spec, Args, Analysis) ->
+ {Args, Analysis#typer_analysis{no_spec = true}}.
+
+%%--------------------------------------------------------------------
%% File processing.
%%--------------------------------------------------------------------
-spec get_all_files(#args{}) -> files().
-get_all_files(#args{files = Fs,files_r = Ds}) ->
+get_all_files(#args{files = Fs, files_r = Ds}) ->
case filter_fd(Fs, Ds, fun test_erl_file_exclude_ann/1) of
[] -> fatal_error("no file(s) to analyze");
AllFiles -> AllFiles
@@ -313,12 +413,7 @@ split_dirs_and_files(Elems, Dir) ->
{Dirs, Files} = lists:foldl(Test_Fun, {[], []}, Elems),
{lists:reverse(Dirs), lists:reverse(Files)}.
-%%-----------------------------------------------------------------------
-%% Utilities
-%%-----------------------------------------------------------------------
-
-%% Removes duplicate filenames but it keeps the order of the input list
-
+%% Removes duplicate filenames but keeps the order of the input list
-spec remove_dup(files()) -> files().
remove_dup(Files) ->
@@ -341,6 +436,13 @@ fatal_error(Slogan) ->
msg(io_lib:format("typer: ~s\n", [Slogan])),
erlang:halt(1).
+-spec mode_error(mode(), mode()) -> no_return().
+mode_error(OldMode, NewMode) ->
+ Msg = io_lib:format("Mode was previously set to '~s'; "
+ "can not set it to '~s' now",
+ [OldMode, NewMode]),
+ fatal_error(Msg).
+
-spec compile_error([string()]) -> no_return().
compile_error(Reason) ->
@@ -362,6 +464,60 @@ msg(Msg) ->
end.
%%--------------------------------------------------------------------
+%% Version and help messages.
+%%--------------------------------------------------------------------
+
+-spec version_message() -> no_return().
+version_message() ->
+ io:format("TypEr version "++?VSN++"\n"),
+ erlang:halt(0).
+
+-spec help_message() -> no_return().
+help_message() ->
+ S = " Usage: typer [--help] [--version] [--comments] [--plt PLT]
+ [--show | --show-exported | --annotate | --annotate-inc-files]
+ [-Ddefine]* [-I include_dir]* [-T application]* [-r] file*
+
+ Options:
+ -r dir*
+ search directories recursively for .erl files below them
+ --show
+ Prints type specifications for all functions on stdout.
+ (this is the default behaviour; this option is not really needed)
+ --show-exported (or --show_exported)
+ Same as --show, but prints specifications for exported functions only
+ Specs are displayed sorted alphabetically on the function's name
+ --annotate
+ Annotates the specified files with type specifications
+ --annotate-inc-files
+ Same as --annotate but annotates all -include() files as well as
+ all .erl files (use this option with caution - has not been tested much)
+ --comments
+ Prints type information using Edoc comments, not type specs
+ --plt PLT
+ Use the specified dialyzer PLT file rather than the default one
+ -T file*
+ The specified file(s) already contain type specifications and these
+ are to be trusted in order to print specs for the rest of the files
+ (Multiple files or dirs, separated by spaces, can be specified.)
+ -Dname (or -Dname=value)
+ pass the defined name(s) to TypEr
+ (The syntax of defines is the same as that used by \"erlc\".)
+ -I include_dir
+ pass the include_dir to TypEr
+ (The syntax of includes is the same as that used by \"erlc\".)
+ --version (or -v)
+ prints the Typer version and exits
+ --help (or -h)
+ prints this message and exits
+
+ Note:
+ * denotes that multiple occurrences of these options are possible.
+",
+ io:put_chars(S),
+ erlang:halt(0).
+
+%%--------------------------------------------------------------------
%% Handle messages.
%%--------------------------------------------------------------------
diff --git a/lib/typer/src/typer_options.erl b/lib/typer/src/typer_options.erl
deleted file mode 100644
index b041052cd2..0000000000
--- a/lib/typer/src/typer_options.erl
+++ /dev/null
@@ -1,194 +0,0 @@
-%% -*- erlang-indent-level: 2 -*-
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%===========================================================================
-%% File : typer_options.erl
-%% Author : Bingwen He <[email protected]>
-%% Description : Handles all command-line options given to TypEr
-%%===========================================================================
-
--module(typer_options).
-
--export([process/0]).
-
-%%---------------------------------------------------------------------------
-
--include("typer.hrl").
-
-%%---------------------------------------------------------------------------
-%% Exported functions
-%%---------------------------------------------------------------------------
-
--spec process() -> {#args{}, #typer_analysis{}}.
-
-process() ->
- ArgList = init:get_plain_arguments(),
- %% io:format("Args is ~p\n", [ArgList]),
- {Args, Analysis} = analyze_args(ArgList, #args{}, #typer_analysis{}),
- %% if the mode has not been set, set it to the default mode (show)
- {Args, case Analysis#typer_analysis.mode of
- undefined -> Analysis#typer_analysis{mode = ?SHOW};
- Mode when is_atom(Mode) -> Analysis
- end}.
-
-%%---------------------------------------------------------------------------
-%% Internal functions
-%%---------------------------------------------------------------------------
-
-analyze_args([], Args, Analysis) ->
- {Args, Analysis};
-analyze_args(ArgList, Args, Analysis) ->
- {Result, Rest} = cl(ArgList),
- {NewArgs, NewAnalysis} = analyze_result(Result, Args, Analysis),
- analyze_args(Rest, NewArgs, NewAnalysis).
-
-cl(["-h"|_]) -> help_message();
-cl(["--help"|_]) -> help_message();
-cl(["-v"|_]) -> version_message();
-cl(["--version"|_]) -> version_message();
-cl(["--comments"|Opts]) -> {comments, Opts};
-cl(["--show"|Opts]) -> {{mode, ?SHOW}, Opts};
-cl(["--show_exported"|Opts]) -> {{mode, ?SHOW_EXPORTED}, Opts};
-cl(["--show-exported"|Opts]) -> {{mode, ?SHOW_EXPORTED}, Opts};
-cl(["--annotate"|Opts]) -> {{mode, ?ANNOTATE}, Opts};
-cl(["--annotate-inc-files"|Opts]) -> {{mode, ?ANNOTATE_INC_FILES}, Opts};
-cl(["--no_spec"|Opts]) -> {no_spec, Opts};
-cl(["--plt",Plt|Opts]) -> {{plt, Plt}, Opts};
-cl(["-D"++Def|Opts]) ->
- case Def of
- "" -> typer:fatal_error("no variable name specified after -D");
- _ ->
- DefPair = process_def_list(re:split(Def, "=", [{return, list}])),
- {{def, DefPair}, Opts}
- end;
-cl(["-I",Dir|Opts]) -> {{inc, Dir}, Opts};
-cl(["-I"++Dir|Opts]) ->
- case Dir of
- "" -> typer:fatal_error("no include directory specified after -I");
- _ -> {{inc, Dir}, Opts}
- end;
-cl(["-T"|Opts]) ->
- {Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
- case Files of
- [] -> typer:fatal_error("no file or directory specified after -T");
- [_|_] -> {{trusted, Files}, RestOpts}
- end;
-cl(["-r"|Opts]) ->
- {Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
- {{files_r, Files}, RestOpts};
-cl(["-"++H|_]) -> typer:fatal_error("unknown option -"++H);
-cl(Opts) ->
- {Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
- {{files, Files}, RestOpts}.
-
-process_def_list(L) ->
- case L of
- [Name, Value] ->
- {ok, Tokens, _} = erl_scan:string(Value ++ "."),
- {ok, ErlValue} = erl_parse:parse_term(Tokens),
- {list_to_atom(Name), ErlValue};
- [Name] ->
- {list_to_atom(Name), true}
- end.
-
-%% Get information about files that the user trusts and wants to analyze
-analyze_result({files, Val}, Args, Analysis) ->
- NewVal = Args#args.files ++ Val,
- {Args#args{files = NewVal}, Analysis};
-analyze_result({files_r, Val}, Args, Analysis) ->
- NewVal = Args#args.files_r ++ Val,
- {Args#args{files_r = NewVal}, Analysis};
-analyze_result({trusted, Val}, Args, Analysis) ->
- NewVal = Args#args.trusted ++ Val,
- {Args#args{trusted = NewVal}, Analysis};
-analyze_result(comments, Args, Analysis) ->
- {Args, Analysis#typer_analysis{contracts = false}};
-%% Get useful information for actual analysis
-analyze_result({mode, Val}, Args, Analysis) ->
- case Analysis#typer_analysis.mode of
- undefined -> {Args, Analysis#typer_analysis{mode = Val}};
- _ -> mode_error()
- end;
-analyze_result({def, Val}, Args, Analysis) ->
- NewVal = Analysis#typer_analysis.macros ++ [Val],
- {Args, Analysis#typer_analysis{macros = NewVal}};
-analyze_result({inc, Val}, Args, Analysis) ->
- NewVal = Analysis#typer_analysis.includes ++ [Val],
- {Args, Analysis#typer_analysis{includes = NewVal}};
-analyze_result({plt, Plt}, Args, Analysis) ->
- {Args, Analysis#typer_analysis{plt = Plt}};
-analyze_result(no_spec, Args, Analysis) ->
- {Args, Analysis#typer_analysis{no_spec = true}}.
-
-
-%%--------------------------------------------------------------------
-
--spec mode_error() -> no_return().
-mode_error() ->
- typer:fatal_error("can not do \"show\", \"show-exported\", \"annotate\", and \"annotate-inc-files\" at the same time").
-
--spec version_message() -> no_return().
-version_message() ->
- io:format("TypEr version "++?VSN++"\n"),
- erlang:halt(0).
-
--spec help_message() -> no_return().
-help_message() ->
- S = " Usage: typer [--help] [--version] [--comments] [--plt PLT]
- [--show | --show-exported | --annotate | --annotate-inc-files]
- [-Ddefine]* [-I include_dir]* [-T application]* [-r] file*
-
- Options:
- -r dir*
- search directories recursively for .erl files below them
- --show
- Prints type specifications for all functions on stdout.
- (this is the default behaviour; this option is not really needed)
- --show-exported (or --show_exported)
- Same as --show, but prints specifications for exported functions only
- Specs are displayed sorted alphabetically on the function's name
- --annotate
- Annotates the specified files with type specifications
- --annotate-inc-files
- Same as --annotate but annotates all -include() files as well as
- all .erl files (use this option with caution - has not been tested much)
- --comments
- Prints type information using Edoc comments, not type specs
- --plt PLT
- Use the specified dialyzer PLT file rather than the default one
- -T file*
- The specified file(s) already contain type specifications and these
- are to be trusted in order to print specs for the rest of the files
- (Multiple files or dirs, separated by spaces, can be specified.)
- -Dname (or -Dname=value)
- pass the defined name(s) to TypEr
- (The syntax of defines is the same as that used by \"erlc\".)
- -I include_dir
- pass the include_dir to TypEr
- (The syntax of includes is the same as that used by \"erlc\".)
- --version (or -v)
- prints the Typer version and exits
- --help (or -h)
- prints this message and exits
-
- Note:
- * denotes that multiple occurrences of these options are possible.
-",
- io:put_chars(S),
- erlang:halt(0).