aboutsummaryrefslogtreecommitdiffstats
path: root/lib/test_server/src/erl2html2.erl
diff options
context:
space:
mode:
authorSiri Hansen <[email protected]>2012-11-19 15:13:47 +0100
committerSiri Hansen <[email protected]>2012-11-19 18:07:33 +0100
commita908160088b654e436bdcdd32369c29603ca5fa7 (patch)
treea5444eccddaa7c80a10db0987582b764254d0e51 /lib/test_server/src/erl2html2.erl
parenta7af6cae44d1837d0c6cb35b99feff1260659102 (diff)
downloadotp-a908160088b654e436bdcdd32369c29603ca5fa7.tar.gz
otp-a908160088b654e436bdcdd32369c29603ca5fa7.tar.bz2
otp-a908160088b654e436bdcdd32369c29603ca5fa7.zip
[test_server] Fix erl2html2.erl to handle badly indented files
Line numbering of erlang files that were not correctly indented could be wrong after coverting to html with erl2html2:convert/[2,3]. This has been corrected. This commit also fixes the following: * There are now link targets for each line and not only for each 10th line - meaning that links from test logs are now to the exact line, and not to the last number for which N rem 10 == 0. * there will only be one link target per function, i.e. the faulty link targets for function clauses are removed. * link targets for function now includes the arity (e.g. func/1 has a link target "func-1") And some tests are added.
Diffstat (limited to 'lib/test_server/src/erl2html2.erl')
-rw-r--r--lib/test_server/src/erl2html2.erl228
1 files changed, 102 insertions, 126 deletions
diff --git a/lib/test_server/src/erl2html2.erl b/lib/test_server/src/erl2html2.erl
index 6891e87e48..290acc5040 100644
--- a/lib/test_server/src/erl2html2.erl
+++ b/lib/test_server/src/erl2html2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. 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
@@ -18,19 +18,9 @@
%%
%%%------------------------------------------------------------------
-%%% Purpose:Convert Erlang files to html. (Pretty faaast... :-)
+%%% Purpose:Convert Erlang files to html.
%%%------------------------------------------------------------------
-%--------------------------------------------------------------------
-% Some stats (Sparc5@110Mhz):
-% 4109 lines (erl_parse.erl): 3.00 secs
-% 1847 lines (application_controller.erl): 0.57 secs
-% 3160 lines (test_server.erl): 1.00 secs
-% 1199 lines (ts_estone.erl): 0.35 secs
-%
-% Avg: ~4.5e-4s/line, or ~0.45s/1000 lines, or ~2200 lines/sec.
-%--------------------------------------------------------------------
-
-module(erl2html2).
-export([convert/2, convert/3]).
@@ -54,132 +44,118 @@ convert(File, Dest) ->
convert(File, Dest, Header).
convert(File, Dest, Header) ->
- case file:read_file(File) of
- {ok, Bin} ->
- Code=binary_to_list(Bin),
- statistics(runtime),
- {Html1, Lines} = root(Code, [], 1),
- Html = [Header,
- "<pre>\n", Html1, "</pre>\n",
- footer(Lines),"</body>\n</html>\n"],
- file:write_file(Dest, Html);
- {error, Reason} ->
- {error, Reason}
+ %% statistics(runtime),
+ case parse_file(File) of
+ {ok,Functions} ->
+ %% io:format("~p~n",[Functions]),
+ case file:read_file(File) of
+ {ok,Bin} ->
+ {Html,Lines} = build_html(Bin,Functions),
+ Html1 = [Header,"<pre>\n",Html,"</pre>\n",
+ footer(Lines),"</body>\n</html>\n"],
+ file:write_file(Dest,Html1);
+ Error ->
+ Error
+ end;
+ Error ->
+ Error
end.
-root([], Res, Line) ->
- {Res, Line};
-root([Char0|Code], Res, Line0) ->
- Char = [Char0],
- case Char of
- "-" ->
- {Match, Line1, NewCode0, AttName} =
- read_to_char(Line0+1, Code, [], [$(, $.]),
- {_, Line2, NewCode, Stuff} = read_to_char(Line1, NewCode0, [], $\n),
- NewRes = [Res,linenum(Line0),"-<b>",AttName,
- "</b>",Match, Stuff, "\n"],
- root(NewCode, NewRes, Line2);
- "%" ->
- {_, Line, NewCode, Stuff} = read_to_char(Line0+1, Code, [], $\n),
- NewRes = [Res,linenum(Line0),"<i>%",Stuff,"</i>\n"],
- root(NewCode, NewRes, Line);
- "\n" ->
- root(Code, [Res,linenum(Line0), "\n"], Line0+1);
- " " ->
- {_, Line, NewCode, Stuff} = read_to_char(Line0+1, Code, [], $\n),
- root(NewCode, [Res,linenum(Line0)," ",Stuff, "\n"],
- Line);
- "\t" ->
- {_, Line, NewCode, Stuff} = read_to_char(Line0+1, Code, [], $\n),
- root(NewCode, [Res,linenum(Line0),"\t",Stuff, "\n"],
- Line);
- [Chr|_] when Chr>96, Chr<123 ->
- %% Assumed to be function/clause start.
- %% FIXME: This will trivially generate non-unique anchors
- %% (one for each clause) --- which is illegal HTML.
- {_, Line1, NewCode0, FName0} = read_to_char(Line0+1, Code, [], $(),
- {_, Line2, NewCode, Stuff} =
- read_to_char(Line1,NewCode0, [], $\n),
- FuncName = [[Chr],FName0],
- NewRes=[Res,"<a name=",FuncName,">",
- linenum(Line0),"<b>",FuncName,"</b></a>",
- "(",Stuff, "\n"],
- root(NewCode, NewRes, Line2);
- Chr ->
- {_, Line, NewCode, Stuff} = read_to_char(Line0+1, Code, [], $\n),
- root(NewCode, [Res,linenum(Line0),Chr,Stuff, "\n"],
- Line)
+%%%-----------------------------------------------------------------
+%%% Parse the input file to get the line numbers for all function
+%%% definitions. This will be used when creating link targets for each
+%%% function in build_html/5.
+%%%
+%%% All function clauses are also marked in order to allow
+%%% possibly_enhance/2 to write these in bold.
+parse_file(File) ->
+ case epp:parse_file(File,[],[]) of
+ {ok,Forms} ->
+ {ok,get_functions(Forms,File,false)};
+ Error ->
+ Error
end.
-read_to_char(Line0, [], Res, _Chr) ->
- {nomatch, Line0, [], Res};
-read_to_char(Line0, [Char|Code], Res, Chr) ->
- case Char of
- Chr -> {Char, Line0, Code, Res};
- _ when is_list(Chr) ->
- case lists:member(Char,Chr) of
- true ->
- {Char, Line0, Code, Res};
- false ->
- {Line,NewCode,NewRes} = maybe_convert(Line0,Code,Res,Char),
- read_to_char(Line, NewCode, NewRes, Chr)
- end;
- _ ->
- {Line,NewCode,NewRes} = maybe_convert(Line0,Code,Res,Char),
- read_to_char(Line,NewCode, NewRes, Chr)
- end.
+get_functions([{attribute,_,file,{File,_}}|Forms],File,_) ->
+ get_functions(Forms,File,true);
+get_functions([{attribute,_,file,{_OtherFile,_}}|Forms],File,_) ->
+ get_functions(Forms,File,false);
+get_functions([{function,L,F,A,[_|C]}|Forms],File,true) ->
+ Clauses = [{clause,CL} || {clause,CL,_,_,_} <- C],
+ [{atom_to_list(F),A,L} | Clauses] ++ get_functions(Forms,File,true);
+get_functions([_|Forms],File,InCorrectFile) ->
+ get_functions(Forms,File,InCorrectFile);
+get_functions([],_,_) ->
+ [].
-maybe_convert(Line0,Code,Res,Chr) ->
- case Chr of
- %% Quoted stuff should not have the highlighting like normal code
- %% FIXME: unbalanced quotes (e.g. in comments) will cause trouble with
- %% highlighting and line numbering in the rest of the module.
- $" ->
- {_, Line1, NewCode, Stuff0} = read_to_char(Line0, Code, [], $"),
- {Line2,Stuff} = add_linenumbers(Line1,lists:flatten(Stuff0),[]),
- {Line2,NewCode,[Res,$",Stuff,$"]};
- %% These chars have meaning in HTML, and *must* *not* be
- %% written as themselves.
- $& ->
- {Line0, Code, [Res,"&amp;"]};
- $< ->
- {Line0, Code, [Res,"&lt;"]};
- $> ->
- {Line0, Code, [Res,"&gt;"]};
- %% Everything else is simply copied.
- OtherChr ->
- {Line0, Code, [Res,OtherChr]}
- end.
+%%%-----------------------------------------------------------------
+%%% Add a link target for each line and one for each function definition.
+build_html(Bin,Functions) ->
+ build_html(binary:split(Bin,<<"\n">>),1,Functions,false,[]).
-add_linenumbers(Line,[Chr|Chrs],Res) ->
- case Chr of
- $\n -> add_linenumbers(Line+1,Chrs,[Res,$\n,linenum(Line)]);
- _ -> add_linenumbers(Line,Chrs,[Res,Chr])
- end;
-add_linenumbers(Line,[],Res) ->
- {Line,Res}.
+build_html(Split,L,[{F,A,L}|Functions],_IsFuncDef,Acc) ->
+ FALink = http_uri:encode(F++"-"++integer_to_list(A)),
+ NewAcc = [Acc,"<a name=\"",FALink,"\"/>"],
+ build_html(Split,L,Functions,true,NewAcc);
+build_html(Split,L,[{clause,L}|Functions],_IsFuncDef,Acc) ->
+ build_html(Split,L,Functions,true,Acc);
+build_html([Line,Bin],L,Functions,IsFuncDef,Acc) ->
+ NewAcc = [Acc,line_number(L),line(binary_to_list(Line),IsFuncDef),$\n],
+ build_html(binary:split(Bin,<<"\n">>),L+1,Functions,false,NewAcc);
+build_html([Line],L,Functions,IsFuncDef,Acc) ->
+ {[Acc,line_number(L),line(binary_to_list(Line),IsFuncDef)],L}.
-%% Make nicely indented line numbers.
-linenum(Line) ->
- Num = integer_to_list(Line),
- A = case Line rem 10 of
- 0 -> "<a name=\"" ++ Num ++"\"></a>";
- _ -> []
- end,
+line_number(L) ->
+ LStr = integer_to_list(L),
Pred =
- case length(Num) of
+ case length(LStr) of
Length when Length < 5 ->
lists:duplicate(5-Length,$\s);
_ ->
[]
end,
- [A,Pred,integer_to_list(Line),":"].
+ ["<a name=\"",LStr,"\"/>",Pred,LStr,": "].
+
+line(Str,IsFuncDef) ->
+ Str1 = htmlize(Str),
+ possibly_enhance(Str1,IsFuncDef).
+
+%%%-----------------------------------------------------------------
+%%% Substitute special characters that should not appear in HTML
+htmlize([$<|Str]) ->
+ [$&,$l,$t,$;|htmlize(Str)];
+htmlize([$>|Str]) ->
+ [$&,$g,$t,$;|htmlize(Str)];
+htmlize([$&|Str]) ->
+ [$&,$a,$m,$p,$;|htmlize(Str)];
+htmlize([$"|Str]) ->
+ [$&,$q,$u,$o,$t,$;|htmlize(Str)];
+htmlize([Ch|Str]) ->
+ [Ch|htmlize(Str)];
+htmlize([]) ->
+ [].
+
+%%%-----------------------------------------------------------------
+%%% Write comments in italic and function definitions in bold.
+possibly_enhance(Str,true) ->
+ case lists:splitwith(fun($() -> false; (_) -> true end, Str) of
+ {_,[]} -> Str;
+ {F,A} -> ["<b>",F,"</b>",A]
+ end;
+possibly_enhance([$%|_]=Str,_) ->
+ ["<i>",Str,"</i>"];
+possibly_enhance([$-|_]=Str,_) ->
+ possibly_enhance(Str,true);
+possibly_enhance(Str,false) ->
+ Str.
+%%%-----------------------------------------------------------------
+%%% End of the file
footer(_Lines) ->
- "".
-%% {_, Time} = statistics(runtime),
-%% io:format("Converted ~p lines in ~.2f Seconds.~n",
-%% [Lines, Time/1000]),
-%% S = "<i>The transformation of this file (~p lines) took ~.2f seconds</i>",
-%% F = lists:flatten(io_lib:format(S, [Lines, Time/1000])),
-%% ["<hr size=1>",F,"<br>\n"].
+ "".
+ %% {_, Time} = statistics(runtime),
+ %% io:format("Converted ~p lines in ~.2f Seconds.~n",
+ %% [_Lines, Time/1000]),
+ %% S = "<i>The transformation of this file (~p lines) took ~.2f seconds</i>",
+ %% F = lists:flatten(io_lib:format(S, [_Lines, Time/1000])),
+ %% ["<hr size=1>",F,"<br>\n"].