aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Valim <[email protected]>2019-05-17 19:24:29 +0200
committerHans Bolinder <[email protected]>2019-06-25 14:31:00 +0200
commitdd9a4d6f559cac28fd74dac0ff62d27bfed66e64 (patch)
tree914f49897eb150a253a6d64d72849baa141344ad
parent4319a7f8bc93388ec540e954eb9bb73ea1eec4ef (diff)
downloadotp-dd9a4d6f559cac28fd74dac0ff62d27bfed66e64.tar.gz
otp-dd9a4d6f559cac28fd74dac0ff62d27bfed66e64.tar.bz2
otp-dd9a4d6f559cac28fd74dac0ff62d27bfed66e64.zip
Always fallback to source when we can't parse AST
This commit fixes a bug in Dialyzer where it would assume all Erlang AST can be converted back to valid Erlang code. A case where this was is no true was already documented in the source code, in relation to opaque types, but this can also be true when it comes to other BEAM languages.
-rw-r--r--lib/dialyzer/src/dialyzer.erl48
1 files changed, 21 insertions, 27 deletions
diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl
index d4fe064edd..c1bc5ff597 100644
--- a/lib/dialyzer/src/dialyzer.erl
+++ b/lib/dialyzer/src/dialyzer.erl
@@ -605,11 +605,9 @@ ordinal(N) when is_integer(N) -> io_lib:format("~wth", [N]).
%% Functions that parse type strings, literal strings, and contract
%% strings. Return strings formatted by erl_pp.
-%% If lib/hipe/cerl/erl_types.erl is compiled with DEBUG=true,
-%% the contents of opaque types are showed inside brackets.
-%% Since erl_parse:parse_form() cannot handle the bracket syntax,
-%% no indentation is done.
-%%-define(DEBUG , true).
+%% Note we always have to catch any error when trying to parse
+%% the syntax because other BEAM languages may not emit an
+%% Erlang AST that transforms into valid Erlang Source Code.
-define(IND, 10).
@@ -620,13 +618,15 @@ con(M, F, Src, I) ->
sig(Src, false) ->
Src;
sig(Src, true) ->
- Str = lists:flatten(io_lib:format("-spec ~w:~tw~ts.", [a, b, Src])),
- {ok, Tokens, _EndLocation} = erl_scan:string(Str),
- exec(fun() ->
- {ok, {attribute, _, spec, {_MFA, Types}}} =
- erl_parse:parse_form(Tokens),
- indentation(?IND) ++ pp_spec(Types)
- end, Src).
+ try
+ Str = lists:flatten(io_lib:format("-spec ~w:~tw~ts.", [a, b, Src])),
+ {ok, Tokens, _EndLocation} = erl_scan:string(Str),
+ {ok, {attribute, _, spec, {_MFA, Types}}} =
+ erl_parse:parse_form(Tokens),
+ indentation(?IND) ++ pp_spec(Types)
+ catch
+ _:_ -> Src
+ end.
%% Argument(list)s are a mix of types and Erlang code. Note: sometimes
%% (contract_range, call_without_opaque, opaque_type_test), the initial
@@ -681,21 +681,15 @@ ts(Src) ->
[C1|Src1] = Src, % $< (product) or $( (arglist)
[C2|RevSrc2] = lists:reverse(Src1),
Src2 = lists:reverse(RevSrc2),
- exec(fun() ->
- Types = parse_types_and_literals(Src2),
- CommaInd = [$, | Ind],
- (indentation(?IND-1) ++
- [C1 | lists:join(CommaInd, [pp_type(Type) || Type <- Types])] ++
- [C2])
- end, Src).
-
--ifdef(DEBUG).
-exec(F, R) ->
- try F() catch _:_ -> R end.
--else.
-exec(F, _) ->
- F().
--endif.
+ try
+ Types = parse_types_and_literals(Src2),
+ CommaInd = [$, | Ind],
+ (indentation(?IND-1) ++
+ [C1 | lists:join(CommaInd, [pp_type(Type) || Type <- Types])] ++
+ [C2])
+ catch
+ _:_ -> Src
+ end.
indentation(I) ->
[$\n | lists:duplicate(I, $\s)].