1
1
%% -*- erlang-indent-level: 2 -*-
2
2
%%--------------------------------------------------------------------
5
%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
5
%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
7
7
%% The contents of this file are subject to the Erlang Public License,
8
8
%% Version 1.1, (the "License"); you may not use this file except in
9
9
%% compliance with the License. You should have received a copy of the
10
10
%% Erlang Public License along with this software. If not, it can be
11
11
%% retrieved online at http://www.erlang.org/.
13
13
%% Software distributed under the License is distributed on an "AS IS"
14
14
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
15
15
%% the License for the specific language governing rights and limitations
16
16
%% under the License.
44
44
plt :: dialyzer_plt:plt(),
45
45
start_from = byte_code :: start_from(),
46
use_contracts = true :: boolean()
46
use_contracts = true :: boolean(),
47
behaviours = {false,[]} :: {boolean(),[atom()]}
49
50
-record(server_state, {parent :: pid(), legal_warnings :: [dial_warn_tag()]}).
57
58
start(Parent, LegalWarnings, Analysis) ->
58
59
RacesOn = ordsets:is_element(?WARN_RACE_CONDITION, LegalWarnings),
59
Analysis0 = Analysis#analysis{race_detection = RacesOn},
60
BehavOn = ordsets:is_element(?WARN_BEHAVIOUR, LegalWarnings),
61
Analysis0 = Analysis#analysis{race_detection = RacesOn,
62
behaviours_chk = BehavOn},
60
63
Analysis1 = expand_files(Analysis0),
61
64
Analysis2 = run_analysis(Analysis1),
62
65
State = #server_state{parent = Parent, legal_warnings = LegalWarnings},
94
97
{AnalPid, ext_calls, NewExtCalls} ->
95
98
loop(State, Analysis, NewExtCalls);
99
{AnalPid, unknown_behaviours, UnknownBehaviour} ->
100
send_unknown_behaviours(Parent, UnknownBehaviour),
101
loop(State, Analysis, ExtCalls);
96
102
{AnalPid, mod_deps, ModDeps} ->
97
103
send_mod_deps(Parent, ModDeps),
98
104
loop(State, Analysis, ExtCalls);
118
124
start_from = Analysis#analysis.start_from,
119
use_contracts = Analysis#analysis.use_contracts
125
use_contracts = Analysis#analysis.use_contracts,
126
behaviours = {Analysis#analysis.behaviours_chk,
121
129
Files = ordsets:from_list(Analysis#analysis.files),
122
130
{Callgraph, NoWarn, TmpCServer0} = compile_and_store(Files, State),
167
175
State#analysis_state{plt = NewPlt};
169
177
NoWarn = State#analysis_state.no_warn_unused,
178
{BehavioursChk, _Known} = State#analysis_state.behaviours,
170
179
DocPlt = State#analysis_state.doc_plt,
171
180
Callgraph1 = dialyzer_callgraph:finalize(Callgraph),
172
181
{Warnings, NewPlt, NewDocPlt} =
173
182
dialyzer_succ_typings:get_warnings(Callgraph1, Plt, DocPlt,
174
Codeserver, NoWarn, Parent),
183
Codeserver, NoWarn, Parent,
175
185
dialyzer_callgraph:delete(Callgraph1),
176
186
send_warnings(State#analysis_state.parent, Warnings),
177
187
State#analysis_state{plt = NewPlt, doc_plt = NewDocPlt}
186
196
include_dirs = Dirs,
188
198
use_contracts = UseContracts,
189
start_from = StartFrom} = State) ->
199
start_from = StartFrom,
200
behaviours = {BehChk, _}
190
202
send_log(Parent, "Reading files and computing callgraph... "),
191
203
{T1, _} = statistics(runtime),
192
204
Includes = [{i, D} || D <- Dirs],
234
246
{T2, _} = statistics(runtime),
235
247
Msg1 = io_lib:format("done in ~.2f secs\nRemoving edges... ", [(T2-T1)/1000]),
236
248
send_log(Parent, Msg1),
237
NewCallgraph2 = cleanup_callgraph(State, NewCServer, NewCallgraph1, Modules),
249
{KnownBehaviours, UnknownBehaviours} =
250
dialyzer_behaviours:get_behaviours(Modules, NewCServer),
251
if UnknownBehaviours =:= [] -> ok;
252
true -> send_unknown_behaviours(Parent, UnknownBehaviours)
254
State1 = State#analysis_state{behaviours = {BehChk,KnownBehaviours}},
255
NewCallgraph2 = cleanup_callgraph(State1, NewCServer, NewCallgraph1, Modules),
238
256
{T3, _} = statistics(runtime),
239
257
Msg2 = io_lib:format("done in ~.2f secs\n", [(T3-T2)/1000]),
240
258
send_log(Parent, Msg2),
241
259
{NewCallgraph2, sets:from_list(NoWarn), NewCServer}.
243
261
cleanup_callgraph(#analysis_state{plt = InitPlt, parent = Parent,
244
codeserver = CodeServer},
262
codeserver = CodeServer,
263
behaviours = {BehChk, KnownBehaviours}
245
265
CServer, Callgraph, Modules) ->
246
266
ModuleDeps = dialyzer_callgraph:module_deps(Callgraph),
247
267
send_mod_deps(Parent, ModuleDeps),
248
268
{Callgraph1, ExtCalls} = dialyzer_callgraph:remove_external(Callgraph),
271
dialyzer_behaviours:get_behaviour_apis(KnownBehaviours),
272
BehaviourAPICalls = [Call || {_From, To} = Call <- ExtCalls,
273
lists:member(To, RelevantAPICalls)],
275
dialyzer_callgraph:put_behaviour_api_calls(BehaviourAPICalls,
278
Callgraph2 = Callgraph1
249
280
ExtCalls1 = [Call || Call = {_From, To} <- ExtCalls,
250
281
not dialyzer_plt:contains_mfa(InitPlt, To)],
251
282
{BadCalls1, RealExtCalls} =
269
300
send_ext_calls(Parent, lists:usort([To || {_From, To} <- RealExtCalls]))
273
304
compile_src(File, Includes, Defines, Callgraph, CServer, UseContracts) ->
274
305
DefaultIncludes = default_includes(filename:dirname(File)),
445
476
Parent ! {self(), ext_calls, ExtCalls},
479
send_unknown_behaviours(Parent, UnknownBehaviours) ->
480
Parent ! {self(), unknown_behaviours, UnknownBehaviours},
448
483
send_codeserver_plt(Parent, CServer, Plt ) ->
449
484
Parent ! {self(), cserver, CServer, Plt},