aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer/src/dialyzer.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dialyzer/src/dialyzer.erl')
-rw-r--r--lib/dialyzer/src/dialyzer.erl71
1 files changed, 49 insertions, 22 deletions
diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl
index c1897ed892..3b7b68e8c4 100644
--- a/lib/dialyzer/src/dialyzer.erl
+++ b/lib/dialyzer/src/dialyzer.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2006-2010. 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%
%%
@@ -379,7 +379,7 @@ message_to_string({spec_missing_fun, [M, F, A]}) ->
[M, F, A]);
%%----- Warnings for opaque type violations -------------------
message_to_string({call_with_opaque, [M, F, Args, ArgNs, ExpArgs]}) ->
- io_lib:format("The call ~w:~w~s contains ~s when ~s\n",
+ io_lib:format("The call ~w:~w~s contains ~s argument when ~s\n",
[M, F, Args, form_positions(ArgNs), form_expected(ExpArgs)]);
message_to_string({call_without_opaque, [M, F, Args, ExpectedTriples]}) ->
io_lib:format("The call ~w:~w~s does not have ~s\n",
@@ -403,8 +403,25 @@ message_to_string({opaque_type_test, [Fun, Opaque]}) ->
io_lib:format("The type test ~s(~s) breaks the opaqueness of the term ~s\n", [Fun, Opaque, Opaque]);
%%----- Warnings for concurrency errors --------------------
message_to_string({race_condition, [M, F, Args, Reason]}) ->
- io_lib:format("The call ~w:~w~s ~s\n", [M, F, Args, Reason]).
-
+ io_lib:format("The call ~w:~w~s ~s\n", [M, F, Args, Reason]);
+%%----- Warnings for behaviour errors --------------------
+message_to_string({callback_type_mismatch, [B, F, A, O]}) ->
+ io_lib:format("The inferred return type of the ~w/~w callback includes the"
+ " type ~s which is not a valid return for the ~w behaviour\n",
+ [F, A, erl_types:t_to_string(O), B]);
+message_to_string({callback_arg_type_mismatch, [B, F, A, N, O]}) ->
+ io_lib:format("The inferred type of the ~s argument of ~w/~w callback"
+ " includes the type ~s which is not valid for the ~w behaviour"
+ "\n", [ordinal(N), F, A, erl_types:t_to_string(O), B]);
+message_to_string({callback_missing, [B, F, A]}) ->
+ io_lib:format("Undefined callback function ~w/~w (behaviour '~w')\n",
+ [F, A, B]);
+message_to_string({invalid_spec, [B, F, A, R]}) ->
+ io_lib:format("The spec for the ~w:~w/~w callback is not correct: ~s\n",
+ [B, F, A, R]);
+message_to_string({spec_missing, [B, F, A]}) ->
+ io_lib:format("Type info about ~w:~w/~w callback is not available\n",
+ [B, F, A]).
%%-----------------------------------------------------------------------------
%% Auxiliary functions below
@@ -421,8 +438,8 @@ call_or_apply_to_string(ArgNs, FailReason, SigArgs, SigRet,
io_lib:format("will never return since the success typing arguments"
" are ~s\n", [SigArgs]);
false ->
- io_lib:format("will never return since it differs in argument"
- " ~s from the success typing arguments: ~s\n",
+ io_lib:format("will never return since it differs in the ~s argument"
+ " from the success typing arguments: ~s\n",
[PositionString, SigArgs])
end;
only_contract ->
@@ -431,7 +448,7 @@ call_or_apply_to_string(ArgNs, FailReason, SigArgs, SigRet,
%% We do not know which arguments caused the failure
io_lib:format("breaks the contract ~s\n", [Contract]);
false ->
- io_lib:format("breaks the contract ~s in argument ~s\n",
+ io_lib:format("breaks the contract ~s in the ~s argument\n",
[Contract, PositionString])
end;
both ->
@@ -441,22 +458,26 @@ call_or_apply_to_string(ArgNs, FailReason, SigArgs, SigRet,
form_positions(ArgNs) ->
case ArgNs of
- [_] -> "an opaque term in ";
- [_,_|_] -> "opaque terms in "
- end ++ form_position_string(ArgNs).
+ [_] -> "an opaque term as ";
+ [_,_|_] -> "opaque terms as "
+ end ++ form_position_string(ArgNs) ++
+ case ArgNs of
+ [_] -> " argument";
+ [_,_|_] -> " arguments"
+ end.
%% We know which positions N are to blame;
%% the list of triples will never be empty.
form_expected_without_opaque([{N, T, TStr}]) ->
case erl_types:t_is_opaque(T) of
true ->
- io_lib:format("an opaque term of type ~s in ", [TStr]);
+ io_lib:format("an opaque term of type ~s as ", [TStr]);
false ->
- io_lib:format("a term of type ~s (with opaque subterms) in ", [TStr])
- end ++ form_position_string([N]);
+ io_lib:format("a term of type ~s (with opaque subterms) as ", [TStr])
+ end ++ form_position_string([N]) ++ " argument";
form_expected_without_opaque(ExpectedTriples) -> %% TODO: can do much better here
{ArgNs, _Ts, _TStrs} = lists:unzip3(ExpectedTriples),
- "opaque terms in " ++ form_position_string(ArgNs).
+ "opaque terms as " ++ form_position_string(ArgNs) ++ " arguments".
form_expected(ExpectedArgs) ->
case ExpectedArgs of
@@ -472,9 +493,15 @@ form_expected(ExpectedArgs) ->
form_position_string(ArgNs) ->
case ArgNs of
[] -> "";
- [N1] -> io_lib:format("position ~w", [N1]);
+ [N1] -> ordinal(N1);
[_,_|_] ->
- " and"++ArgString = lists:flatten([io_lib:format(" and ~w", [N])
- || N <- ArgNs]),
- "positions" ++ ArgString
+ [Last|Prevs] = lists:reverse(ArgNs),
+ ", " ++ Head = lists:flatten([io_lib:format(", ~s",[ordinal(N)]) ||
+ N <- lists:reverse(Prevs)]),
+ Head ++ " and " ++ ordinal(Last)
end.
+
+ordinal(1) -> "1st";
+ordinal(2) -> "2nd";
+ordinal(3) -> "3rd";
+ordinal(N) when is_integer(N) -> io_lib:format("~wth",[N]).