diff options
Diffstat (limited to 'lib/dialyzer/src/dialyzer_cl.erl')
-rw-r--r-- | lib/dialyzer/src/dialyzer_cl.erl | 142 |
1 files changed, 96 insertions, 46 deletions
diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl index 616e2465dc..8d61216b7a 100644 --- a/lib/dialyzer/src/dialyzer_cl.erl +++ b/lib/dialyzer/src/dialyzer_cl.erl @@ -2,7 +2,7 @@ %%------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2010. All Rights Reserved. +%% 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 @@ -46,7 +46,8 @@ legal_warnings = ordsets:new() :: [dial_warn_tag()], mod_deps = dict:new() :: dict(), output = standard_io :: io:device(), - output_format = formatted :: 'raw' | 'formatted', + output_format = formatted :: format(), + filename_opt = basename :: fopt(), output_plt = none :: 'none' | file:filename(), plt_info = none :: 'none' | dialyzer_plt:plt_info(), report_mode = normal :: rep_mode(), @@ -81,11 +82,15 @@ build_plt(Opts) -> init_opts_for_build(Opts) -> case Opts#options.output_plt =:= none of true -> - case Opts#options.init_plt of - none -> Opts#options{init_plt = none, output_plt = get_default_plt()}; - Plt -> Opts#options{init_plt = none, output_plt = Plt} + case Opts#options.init_plts of + [] -> Opts#options{output_plt = get_default_output_plt()}; + [Plt] -> Opts#options{init_plts = [], output_plt = Plt}; + Plts -> + Msg = io_lib:format("Could not build multiple PLT files: ~s\n", + [format_plts(Plts)]), + error(Msg) end; - false -> Opts#options{init_plt = none} + false -> Opts#options{init_plts = []} end. %%-------------------------------------------------------------------- @@ -98,39 +103,58 @@ add_to_plt(Opts) -> init_opts_for_add(Opts) -> case Opts#options.output_plt =:= none of true -> - case Opts#options.init_plt of - none -> Opts#options{output_plt = get_default_plt(), - init_plt = get_default_plt()}; - Plt -> Opts#options{output_plt = Plt} + case Opts#options.init_plts of + [] -> Opts#options{output_plt = get_default_output_plt(), + init_plts = get_default_init_plt()}; + [Plt] -> Opts#options{output_plt = Plt}; + Plts -> + Msg = io_lib:format("Could not add to multiple PLT files: ~s\n", + [format_plts(Plts)]), + error(Msg) end; false -> - case Opts#options.init_plt =:= none of - true -> Opts#options{init_plt = get_default_plt()}; + case Opts#options.init_plts =:= [] of + true -> Opts#options{init_plts = get_default_init_plt()}; false -> Opts end end. %%-------------------------------------------------------------------- -check_plt(Opts) -> +check_plt(#options{init_plts = []} = Opts) -> Opts1 = init_opts_for_check(Opts), - report_check(Opts), - plt_common(Opts1, [], []). + report_check(Opts1), + plt_common(Opts1, [], []); +check_plt(#options{init_plts = Plts} = Opts) -> + check_plt_aux(Plts, Opts). + +check_plt_aux([_] = Plt, Opts) -> + Opts1 = Opts#options{init_plts = Plt}, + Opts2 = init_opts_for_check(Opts1), + report_check(Opts2), + plt_common(Opts2, [], []); +check_plt_aux([Plt|Plts], Opts) -> + Opts1 = Opts#options{init_plts = [Plt]}, + Opts2 = init_opts_for_check(Opts1), + report_check(Opts2), + plt_common(Opts2, [], []), + check_plt_aux(Plts, Opts). init_opts_for_check(Opts) -> - Plt = - case Opts#options.init_plt of - none -> get_default_plt(); - Plt0 -> Plt0 + InitPlt = + case Opts#options.init_plts of + []-> get_default_init_plt(); + Plt -> Plt end, + [OutputPlt] = InitPlt, Opts#options{files = [], files_rec = [], analysis_type = plt_check, defines = [], from = byte_code, - init_plt = Plt, + init_plts = InitPlt, include_dirs = [], - output_plt = Plt, + output_plt = OutputPlt, use_contracts = true }. @@ -144,23 +168,33 @@ remove_from_plt(Opts) -> init_opts_for_remove(Opts) -> case Opts#options.output_plt =:= none of true -> - case Opts#options.init_plt of - none -> Opts#options{output_plt = get_default_plt(), - init_plt = get_default_plt()}; - Plt -> Opts#options{output_plt = Plt} + case Opts#options.init_plts of + [] -> Opts#options{output_plt = get_default_output_plt(), + init_plts = get_default_init_plt()}; + [Plt] -> Opts#options{output_plt = Plt}; + Plts -> + Msg = io_lib:format("Could not remove from multiple PLT files: ~s\n", + [format_plts(Plts)]), + error(Msg) end; false -> - case Opts#options.init_plt =:= none of - true -> Opts#options{init_plt = get_default_plt()}; + case Opts#options.init_plts =:= [] of + true -> Opts#options{init_plts = get_default_init_plt()}; false -> Opts end end. %%-------------------------------------------------------------------- -plt_common(Opts, RemoveFiles, AddFiles) -> +plt_common(#options{init_plts = [InitPlt]} = Opts, RemoveFiles, AddFiles) -> case check_plt(Opts, RemoveFiles, AddFiles) of ok -> + case Opts#options.output_plt of + none -> ok; + OutPlt -> + {ok, Binary} = file:read_file(InitPlt), + file:write_file(OutPlt, Binary) + end, case Opts#options.report_mode of quiet -> ok; _ -> io:put_chars(" yes\n") @@ -174,7 +208,7 @@ plt_common(Opts, RemoveFiles, AddFiles) -> report_failed_plt_check(Opts, DiffMd5), {AnalFiles, RemovedMods, ModDeps1} = expand_dependent_modules(Md5, DiffMd5, ModDeps), - Plt = clean_plt(Opts#options.init_plt, RemovedMods), + Plt = clean_plt(InitPlt, RemovedMods), case AnalFiles =:= [] of true -> %% Only removed stuff. Just write the PLT. @@ -186,19 +220,19 @@ plt_common(Opts, RemoveFiles, AddFiles) -> end; {error, no_such_file} -> Msg = io_lib:format("Could not find the PLT: ~s\n~s", - [Opts#options.init_plt, default_plt_error_msg()]), + [InitPlt, default_plt_error_msg()]), error(Msg); {error, not_valid} -> Msg = io_lib:format("The file: ~s is not a valid PLT file\n~s", - [Opts#options.init_plt, default_plt_error_msg()]), + [InitPlt, default_plt_error_msg()]), error(Msg); {error, read_error} -> Msg = io_lib:format("Could not read the PLT: ~s\n~s", - [Opts#options.init_plt, default_plt_error_msg()]), + [InitPlt, default_plt_error_msg()]), error(Msg); {error, {no_file_to_remove, F}} -> Msg = io_lib:format("Could not remove the file ~s from the PLT: ~s\n", - [F, Opts#options.init_plt]), + [F, InitPlt]), error(Msg) end. @@ -218,8 +252,7 @@ default_plt_error_msg() -> %%-------------------------------------------------------------------- -check_plt(Opts, RemoveFiles, AddFiles) -> - Plt = Opts#options.init_plt, +check_plt(#options{init_plts = [Plt]} = Opts, RemoveFiles, AddFiles) -> case dialyzer_plt:check_plt(Plt, RemoveFiles, AddFiles) of {old_version, _MD5} = OldVersion -> report_old_version(Opts), @@ -234,14 +267,14 @@ check_plt(Opts, RemoveFiles, AddFiles) -> %%-------------------------------------------------------------------- -report_check(#options{report_mode = ReportMode, init_plt = InitPlt}) -> +report_check(#options{report_mode = ReportMode, init_plts = [InitPlt]}) -> case ReportMode of quiet -> ok; _ -> io:format(" Checking whether the PLT ~s is up-to-date...", [InitPlt]) end. -report_old_version(#options{report_mode = ReportMode, init_plt = InitPlt}) -> +report_old_version(#options{report_mode = ReportMode, init_plts = [InitPlt]}) -> case ReportMode of quiet -> ok; _ -> @@ -264,7 +297,7 @@ report_failed_plt_check(#options{analysis_type = AnalType, report_analysis_start(#options{analysis_type = Type, report_mode = ReportMode, - init_plt = InitPlt, + init_plts = InitPlts, output_plt = OutputPlt}) -> case ReportMode of quiet -> ok; @@ -272,6 +305,7 @@ report_analysis_start(#options{analysis_type = Type, io:format(" "), case Type of plt_add -> + [InitPlt] = InitPlts, case InitPlt =:= OutputPlt of true -> io:format("Adding information to ~s...", [OutputPlt]); false -> io:format("Adding information from ~s to ~s...", @@ -282,6 +316,7 @@ report_analysis_start(#options{analysis_type = Type, plt_check -> io:format("Rebuilding the information in ~s...", [OutputPlt]); plt_remove -> + [InitPlt] = InitPlts, case InitPlt =:= OutputPlt of true -> io:format("Removing information from ~s...", [OutputPlt]); false -> io:format("Removing information from ~s to ~s...", @@ -320,16 +355,28 @@ report_md5_diff(List) -> %%-------------------------------------------------------------------- -get_default_plt() -> +get_default_init_plt() -> + [dialyzer_plt:get_default_plt()]. + +get_default_output_plt() -> dialyzer_plt:get_default_plt(). %%-------------------------------------------------------------------- +format_plts([Plt]) -> Plt; +format_plts([Plt|Plts]) -> + Plt ++ ", " ++ format_plts(Plts). + +%%-------------------------------------------------------------------- + do_analysis(Options) -> Files = get_files_from_opts(Options), - case Options#options.init_plt of - none -> do_analysis(Files, Options, dialyzer_plt:new(), none); - File -> do_analysis(Files, Options, dialyzer_plt:from_file(File), none) + case Options#options.init_plts of + [] -> do_analysis(Files, Options, dialyzer_plt:new(), none); + PltFiles -> + Plts = [dialyzer_plt:from_file(F) || F <- PltFiles], + Plt = dialyzer_plt:merge_plts_or_report_conflicts(PltFiles, Plts), + do_analysis(Files, Options, Plt, none) end. do_analysis(Files, Options, Plt, PltInfo) -> @@ -492,8 +539,10 @@ hc(Mod) -> new_state() -> #cl_state{}. -init_output(State0, #options{output_file = OutFile, output_format = OutFormat}) -> - State = State0#cl_state{output_format = OutFormat}, +init_output(State0, #options{output_file = OutFile, + output_format = OutFormat, + filename_opt = FOpt}) -> + State = State0#cl_state{output_format = OutFormat, filename_opt = FOpt}, case OutFile =:= none of true -> State; @@ -559,7 +608,7 @@ cl_loop(State, LogCache) -> cl_loop(State, LogCache) end. --spec failed_anal_msg(string(), [_]) -> string(). +-spec failed_anal_msg(string(), [_]) -> nonempty_string(). failed_anal_msg(Reason, LogCache) -> Msg = "Analysis failed with error: " ++ Reason ++ "\n", @@ -726,6 +775,7 @@ print_warnings(#cl_state{stored_warnings = []}) -> ok; print_warnings(#cl_state{output = Output, output_format = Format, + filename_opt = FOpt, stored_warnings = Warnings}) -> PrWarnings = process_warnings(Warnings), case PrWarnings of @@ -733,7 +783,7 @@ print_warnings(#cl_state{output = Output, [_|_] -> S = case Format of formatted -> - [dialyzer:format_warning(W) || W <- PrWarnings]; + [dialyzer:format_warning(W, FOpt) || W <- PrWarnings]; raw -> [io_lib:format("~p. \n", [W]) || W <- PrWarnings] end, |