Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fix error reporting.

Fixes #129.
  • Loading branch information...
commit c8632206e3573986063cf598197eca5abe1cdc80 1 parent ca93672
@kaos kaos authored
View
49 src/erlydtl_compiler.erl
@@ -600,7 +600,9 @@ check_scan({error, Err, State}, Context) ->
check_scan(apply(Context#dtl_context.scanner_module, resume, [NewState]), Context);
ExtRes ->
ExtRes
- end.
+ end;
+check_scan({error, _}=Error, _Context) ->
+ Error.
check_parse({ok, _}=Ok, [], _Context) -> Ok;
check_parse({ok, Parsed}, Acc, _Context) -> {ok, Acc ++ Parsed};
@@ -1949,30 +1951,41 @@ add_warnings(Warnings, Context) ->
Context, Warnings).
get_error_item(Report, Prefix, File, Error) ->
- case Error of
- {Line, ErrorDesc}
- when is_integer(Line) ->
- new_error_item(Report, Prefix, File, Line, ?MODULE, ErrorDesc);
- {Line, Module, ErrorDesc}
- when is_integer(Line), is_atom(Module) ->
- new_error_item(Report, Prefix, File, Line, Module, ErrorDesc);
- {_, InfoList} when is_list(InfoList) -> Error;
- ErrorDesc ->
- new_error_item(Report, Prefix, File, none, ?MODULE, ErrorDesc)
+ case compose_error_desc(Error) of
+ {Pos, Module, ErrorDesc} ->
+ new_error_item(Report, Prefix, File, Pos, Module, ErrorDesc);
+ ErrorItem ->
+ ErrorItem
end.
-
-new_error_item(Report, Prefix, File, Line, Module, ErrorDesc) ->
+
+compose_error_desc({Line, ErrorDesc})
+ when is_integer(Line) ->
+ {Line, ?MODULE, ErrorDesc};
+compose_error_desc({{Line, Col}, Module, _}=ErrorDesc)
+ when is_integer(Line), is_integer(Col), is_atom(Module) ->
+ ErrorDesc;
+compose_error_desc({Line, Module, _}=ErrorDesc)
+ when is_integer(Line), is_atom(Module) ->
+ ErrorDesc;
+compose_error_desc({_, InfoList}=ErrorDesc)
+ when is_list(InfoList) -> ErrorDesc;
+compose_error_desc(ErrorDesc) ->
+ {none, ?MODULE, ErrorDesc}.
+
+new_error_item(Report, Prefix, File, Pos, Module, ErrorDesc) ->
if Report ->
io:format("~s:~s~s~s~n",
- [File, line_info(Line), Prefix,
+ [File, pos_info(Pos), Prefix,
Module:format_error(ErrorDesc)]);
true -> nop
end,
- {File, [{Line, Module, ErrorDesc}]}.
+ {File, [{Pos, Module, ErrorDesc}]}.
-line_info(none) -> " ";
-line_info(Line) when is_integer(Line) ->
- io_lib:format("~b: ", [Line]).
+pos_info(none) -> " ";
+pos_info(Line) when is_integer(Line) ->
+ io_lib:format("~b: ", [Line]);
+pos_info({Line, Col}) when is_integer(Line), is_integer(Col) ->
+ io_lib:format("~b:~b ", [Line, Col]).
pack_error_list(Es) ->
collect_error_info([], Es, []).
View
47 src/erlydtl_scanner.erl
@@ -36,15 +36,15 @@
%%%-------------------------------------------------------------------
-module(erlydtl_scanner).
-%% This file was generated 2013-12-02 15:52:41 UTC by slex 0.1.0-2-gb81b78b.
+%% This file was generated 2014-02-15 07:03:20 UTC by slex 0.2.0-2-g8e71a02.
%% http://github.com/erlydtl/slex
--slex_source("src/erlydtl_scanner.slex").
+-slex_source(["src/erlydtl_scanner.slex"]).
-export([scan/1, scan/4]).
-compile(nowarn_unused_vars).
--export([resume/1]).
+-export([resume/1, format_error/1]).
-record(scanner_state,
{template = [], scanned = [], pos = {1, 1},
@@ -54,6 +54,14 @@ resume(#scanner_state{template = Template,
scanned = Scanned, pos = Pos, state = State}) ->
scan(Template, Scanned, Pos, State).
+return_error(Error, P, T, S, St) ->
+ {error, {P, erlydtl_scanner, Error},
+ #scanner_state{template = T,
+ scanned = post_process(S, err), pos = P, state = St}}.
+
+return_error(Error, P) ->
+ {error, {P, erlydtl_scanner, Error}}.
+
to_atom(L) when is_list(L) -> list_to_atom(L).
to_keyword(L, P) -> {to_atom(L ++ "_keyword"), P, L}.
@@ -130,6 +138,15 @@ is_keyword(open, "blocktrans") -> true;
is_keyword(open, "endblocktrans") -> true;
is_keyword(_, _) -> false.
+format_error({illegal_char, C}) ->
+ io_lib:format("Illegal character '~s'", [[C]]);
+format_error({eof, Where}) ->
+ io_lib:format("Unexpected end of file ~s",
+ [format_where(Where)]).
+
+format_where(in_comment) -> "in comment";
+format_where(in_code) -> "in code block".
+
scan(Template) when is_list(Template) ->
scan(Template, [], {1, 1}, in_text).
@@ -465,11 +482,7 @@ scan([H | T], S, {R, C} = P, {in_code, E})
end,
{in_number, E});
scan([H | T], S, {R, C} = P, {in_code, E} = St) ->
- {error,
- {R, erlydtl_scanner,
- lists:concat(["Illegal character in column ", C])},
- #scanner_state{template = [H | T],
- scanned = post_process(S, err), pos = P, state = St}};
+ return_error({illegal_char, H}, P, [H | T], S, St);
scan([H | T], S, {R, C} = P, {in_number, E} = St)
when H >= $0 andalso H =< $9 ->
scan(T,
@@ -486,12 +499,7 @@ scan([H | T], S, {R, C} = P, {in_number, E} = St)
end,
St);
scan([H | T], S, {R, C} = P, {in_number, E} = St) ->
- {error,
- {R, erlydtl_scanner,
- lists:concat(["Illegal character in column ", C])},
- #scanner_state{template = [H | T],
- scanned = post_process(S, err), pos = P,
- state = {in_code, E}}};
+ return_error({illegal_char, H}, P, [H | T], S, St);
scan([H | T], S, {R, C} = P, {in_identifier, E})
when H >= $a andalso H =< $z orelse
H >= $A andalso H =< $Z orelse
@@ -509,18 +517,13 @@ scan([H | T], S, {R, C} = P, {in_identifier, E})
end,
{in_identifier, E});
scan([H | T], S, {R, C} = P, {in_identifier, E} = St) ->
- {error,
- {R, erlydtl_scanner,
- lists:concat(["Illegal character in column ", C])},
- #scanner_state{template = [H | T],
- scanned = post_process(S, err), pos = P,
- state = {in_code, E}}};
+ return_error({illegal_char, H}, P, [H | T], S, St);
scan([], S, {R, C} = P, in_text = St) ->
{ok, lists:reverse(post_process(S, eof))};
scan([], S, {R, C} = P, {in_comment, E} = St) ->
- {error, "Reached end of file inside a comment."};
+ return_error({eof, in_comment}, P);
scan([], S, {R, C} = P, {_, E} = St) ->
- {error, "Reached end of file inside a code block."}.
+ return_error({eof, in_code}, P).
post_process(_, {string, _, L} = T, _) ->
setelement(3, T, begin L1 = lists:reverse(L), L1 end);
View
54 src/erlydtl_scanner.slex
@@ -37,7 +37,7 @@
-function scan.
-init_state in_text.
form -compile(nowarn_unused_vars) end.
-form -export([resume/1]) end.
+form -export([resume/1, format_error/1]) end.
form \
-record(scanner_state, { \
template=[], \
@@ -230,24 +230,10 @@ end.
(H >= $0 andalso H =< $9) orelse H == $- \
end: number_literal, in_number.
-124 any in_code:
- expr \
- {error, {R, erlydtl_scanner, \
- lists:concat(["Illegal character in column ", C])}, \
- #scanner_state{ template=[H|T], scanned=post_process(S, err), \
- pos=P, state=St } \
- } \
- end.
+124 any in_code: expr return_error({illegal_char, H}, P, [H|T], S, St) end.
130 any in_number, expr H >= $0 andalso H =< $9 end: +number_literal.
-132 any in_number:
- expr \
- {error, {R, erlydtl_scanner, \
- lists:concat(["Illegal character in column ", C])}, \
- #scanner_state{ template=[H|T], scanned=post_process(S, err), \
- pos=P, state={in_code, E} } \
- } \
- end.
+132 any in_number: expr return_error({illegal_char, H}, P, [H|T], S, St) end.
140 any in_identifier,
expr \
@@ -256,22 +242,15 @@ end.
(H >= $0 andalso H =< $9) orelse \
H == $_ \
end: +identifier, in_identifier.
-142 any in_identifier:
- expr \
- {error, {R, erlydtl_scanner, \
- lists:concat(["Illegal character in column ", C])}, \
- #scanner_state{ template=[H|T], scanned=post_process(S, err), \
- pos=P, state={in_code, E} } \
- } \
- end.
+142 any in_identifier: expr return_error({illegal_char, H}, P, [H|T], S, St) end.
200 : in_text- :
expr \
{ok, lists:reverse(post_process(S,eof))} \
end.
-202 : in_comment : expr {error, "Reached end of file inside a comment."} end.
-204 : any : expr {error, "Reached end of file inside a code block."} end.
+202 : in_comment : expr return_error({eof, in_comment}, P) end.
+204 : any : expr return_error({eof, in_code}, P) end.
%% Process tokens as we parse them
@@ -292,6 +271,17 @@ identifier: expr is_keyword(any, T) end.
%% Utility functions
+form return_error(Error, P, T, S, St) -> \
+ {error, \
+ {P, erlydtl_scanner, Error}, \
+ #scanner_state{ template=T, \
+ scanned=post_process(S, err), \
+ pos=P, state=St } \
+ } \
+end.
+
+form return_error(Error, P) -> {error, {P, erlydtl_scanner, Error}} end.
+
form to_atom(L) when is_list(L) -> list_to_atom(L) end.
form to_keyword(L, P) -> {to_atom(L ++ "_keyword"), P, L} end.
form atomize(L, T) -> setelement(3, T, to_atom(L)) end.
@@ -371,3 +361,13 @@ form \
is_keyword(open, "endblocktrans") -> true; \
is_keyword(_, _) -> false \
end.
+
+form format_error({illegal_char, C}) -> \
+ io_lib:format("Illegal character '~s'", [[C]]); \
+ format_error({eof, Where}) -> \
+ io_lib:format("Unexpected end of file ~s", [format_where(Where)]) \
+end.
+
+form format_where(in_comment) -> "in comment"; \
+ format_where(in_code) -> "in code block" \
+end.
View
66 tests/src/erlydtl_unittests.erl
@@ -4,6 +4,13 @@
-record(testrec, {foo, bar, baz}).
+-ifndef(GRP_ERROR_REPORTING_COMPILER_OPTS).
+-define(GRP_ERROR_REPORTING_COMPILER_OPTS,[]).
+%%-define(GRP_ERROR_REPORTING_COMPILER_OPTS,[report]).
+%% define GRP_ERROR_REPORTING_COMPILER_OPTS to [report] to print
+%% tested error messages.
+-endif.
+
tests() ->
[
%% {"scanner",
@@ -1239,9 +1246,54 @@ tests() ->
]},
{"error reporting",
[{"no out dir warning",
- <<"foo bar">>, [], [], [], <<"foo bar">>, [error_info([no_out_dir])]},
+ <<"foo bar">>,
+ [], [], %% Vars, RenderOpts
+ %%[report], %% CompilerOpts
+ ?GRP_ERROR_REPORTING_COMPILER_OPTS,
+ <<"foo bar">>, %% Output
+ [error_info([no_out_dir])] %% Warnings
+ },
{"warnings as errors",
- <<"foo bar">>, [], [], [warnings_as_errors], {error, [error_info([no_out_dir])], []}}
+ <<"foo bar">>,
+ [], [],
+ %%[report, warnings_as_errors],
+ [warnings_as_errors|?GRP_ERROR_REPORTING_COMPILER_OPTS],
+ {error, %% Output...
+ [error_info([no_out_dir])], %% Errors
+ [] %% Warnings
+ }
+ },
+ {"illegal character",
+ <<"{{{">>,
+ [], [],
+ %%[report],
+ ?GRP_ERROR_REPORTING_COMPILER_OPTS,
+ {error,
+ [error_info(
+ [{{1,3},erlydtl_scanner,{illegal_char, ${}}] )],
+ []
+ }
+ },
+ {"unexpected end of file - in code",
+ <<"{{">>,
+ [], [],
+ ?GRP_ERROR_REPORTING_COMPILER_OPTS,
+ {error,
+ [error_info(
+ [{{1,3},erlydtl_scanner,{eof, in_code}}] )],
+ []
+ }
+ },
+ {"unexpected end of file - in comment",
+ <<"{#">>,
+ [], [],
+ ?GRP_ERROR_REPORTING_COMPILER_OPTS,
+ {error,
+ [error_info(
+ [{{1,3},erlydtl_scanner,{eof, in_comment}}] )],
+ []
+ }
+ }
]}
].
@@ -1397,7 +1449,8 @@ process_unit_test({Name, DTL, Vars, RenderOpts, CompilerOpts, Output, Warnings})
[ActualWarnings, Warnings], [{compile, Tcompile}]);
{Tcompile, Output} -> test_pass([{compile, Tcompile}]);
{Tcompile, Err} ->
- test_fail(Name, "Compile error: ~p", [Err], [{compile, Tcompile}])
+ test_fail(Name, "Compile error: ~p~nExpected: ~p",
+ [Err, Output], [{compile, Tcompile}])
end.
@@ -1444,9 +1497,12 @@ error_info(File, Ws) ->
error_info({Line, ErrorDesc})
when is_integer(Line) ->
{Line, erlydtl_compiler, ErrorDesc};
-error_info({Line, Module, ErrorDesc})
+error_info({Line, Module, _}=ErrorDesc)
when is_integer(Line), is_atom(Module) ->
- {Line, Module, ErrorDesc};
+ ErrorDesc;
+error_info({{Line, Col}, Module, _}=ErrorDesc)
+ when is_integer(Line), is_integer(Col), is_atom(Module) ->
+ ErrorDesc;
error_info(Ws) when is_list(Ws) ->
error_info("erlydtl_running_test", Ws);
error_info(ErrorDesc) ->
Please sign in to comment.
Something went wrong with that request. Please try again.