1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
%% This suite is the only hand made and simply
%% checks if we can build and update a plt.
-module(plt_SUITE).
-include_lib("common_test/include/ct.hrl").
-include("dialyzer_test_constants.hrl").
-export([suite/0, all/0, build_plt/1, beam_tests/1, update_plt/1]).
suite() ->
[{timetrap, ?plt_timeout}].
all() -> [build_plt, beam_tests, update_plt].
build_plt(Config) ->
OutDir = ?config(priv_dir, Config),
case dialyzer_common:check_plt(OutDir) of
ok -> ok;
fail -> ct:fail(plt_build_fail)
end.
beam_tests(Config) when is_list(Config) ->
Prog = <<"
-module(no_auto_import).
%% Copied from erl_lint_SUITE.erl, clash6
-export([size/1]).
size([]) ->
0;
size({N,_}) ->
N;
size([_|T]) ->
1+size(T).
">>,
Opts = [no_auto_import],
{ok, BeamFile} = compile(Config, Prog, no_auto_import, Opts),
[] = run_dialyzer([BeamFile]),
ok.
run_dialyzer(Files) ->
dialyzer:run([{analysis_type, plt_build},
{files, Files},
{from, byte_code},
{check_plt, false}]).
%%% [James Fish:]
%%% If a function is removed from a module and the module has previously
%%% been added to a PLT, the function will not be removed from PLT when
%%% the PLT is checked. This results in dialyzer failing to produce a
%%% callgraph warning when doing success typings analysis if the remove
%%% function is still called in another module
%%% As the function is not removed from the PLT a prior warning, such as a
%%% contract types warning, might be emitted when the removed function
%%% nolonger exists.
update_plt(Config) ->
PrivDir = ?config(priv_dir, Config),
Prog1 = <<"-module(plt_gc).
-export([one/0]).
one() ->
one.">>,
{ok, Beam} = compile(Config, Prog1, plt_gc, []),
ErlangBeam = case code:where_is_file("erlang.beam") of
non_existing ->
filename:join([code:root_dir(),
"erts", "preloaded", "ebin",
"erlang.beam"]);
EBeam ->
EBeam
end,
Plt = filename:join(PrivDir, "plt_gc.plt"),
Opts = [{check_plt, true}, {from, byte_code}],
[] = dialyzer:run([{analysis_type, plt_build},
{files, [Beam, ErlangBeam]},
{output_plt, Plt}] ++ Opts),
Prog2 = <<"-module(plt_gc).
-export([two/0]).
two() ->
two.">>,
{ok, Beam} = compile(Config, Prog2, plt_gc, []),
Test = <<"-module(test).
-export([test/0]).
-spec test() -> test.
test() ->
plt_gc:one().">>,
{ok, TestBeam} = compile(Config, Test, test, []),
[{warn_callgraph, _, {call_to_missing, [plt_gc, one, 0]}}] =
dialyzer:run([{analysis_type, succ_typings},
{files, [TestBeam]},
{init_plt, Plt}] ++ Opts),
ok.
compile(Config, Prog, Module, CompileOpts) ->
Source = lists:concat([Module, ".erl"]),
PrivDir = ?config(priv_dir,Config),
Filename = filename:join([PrivDir, Source]),
ok = file:write_file(Filename, Prog),
Opts = [{outdir, PrivDir}, debug_info | CompileOpts],
{ok, Module} = compile:file(Filename, Opts),
{ok, filename:join([PrivDir, lists:concat([Module, ".beam"])])}.
|