Skip to content

Commit

Permalink
Merge branch 'hb/types_and_specs_for_docs/OTP-8720' into dev
Browse files Browse the repository at this point in the history
* hb/types_and_specs_for_docs/OTP-8720:
  Prepare erl_docgen for using Dialyzer specs and types
  • Loading branch information
uabboli committed Dec 1, 2010
2 parents e2191e8 + 2f93254 commit 49b581e
Show file tree
Hide file tree
Showing 16 changed files with 2,326 additions and 276 deletions.
5 changes: 4 additions & 1 deletion Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ endif
# ---------------------------------------------------------------
# Target only used when building commercial ERTS patches
# ---------------------------------------------------------------
release_docs docs:
release_docs docs: mod2app
ifeq ($(OTP_SMALL_BUILD),true)
cd $(ERL_TOP)/lib && \
ERL_TOP=$(ERL_TOP) $(MAKE) TESTROOT=$(RELEASE_ROOT) $@
Expand All @@ -408,6 +408,9 @@ endif
cd $(ERL_TOP)/system/doc && \
ERL_TOP=$(ERL_TOP) $(MAKE) TESTROOT=$(RELEASE_ROOT) $@

mod2app:
$(ERL_TOP)/lib/erl_docgen/priv/bin/xref_mod_app.escript -topdir $(ERL_TOP) -outfile $(ERL_TOP)/make/$(TARGET)/mod2app.xml

# ----------------------------------------------------------------------
ERLANG_EARS=$(BOOTSTRAP_ROOT)/bootstrap/erts
ELINK=$(BOOTSTRAP_ROOT)/bootstrap/erts/bin/elink
Expand Down
19 changes: 11 additions & 8 deletions lib/erl_docgen/Makefile
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
# ``The contents of this file are subject to the Erlang Public License,
#
# %CopyrightBegin%
#
# Copyright Ericsson AB 1996-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 via the world wide web at http://www.erlang.org/.
# 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.
#
# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
#
# $Id$
# %CopyrightEnd%
#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
Expand All @@ -22,9 +23,11 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
#

SUB_DIRECTORIES = priv
SUB_DIRECTORIES = src priv
#doc/src

include vsn.mk
VSN = $(ERL_DOCGEN_VSN)

SPECIAL_TARGETS =

Expand Down
Empty file added lib/erl_docgen/ebin/.gitignore
Empty file.
129 changes: 129 additions & 0 deletions lib/erl_docgen/priv/bin/specs_gen.escript
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#!/usr/bin/env escript
%% -*- erlang -*-
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 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%

%%% <script> [-I<dir>]... [-o<dir>] [-module Module] [File]
%%%
%%% Use EDoc and the layout module 'otp_specs' to create an XML file
%%% containing Dialyzer types and specifications (-type, -spec).
%%%
%%% Options:
%%%
%%% "-o<dir>" The output directory for the created file.
%%% Default is ".".
%%% "-I<dir>" Directory to be searched when including a file.
%%% "-module Module"
%%% Module name to use when there is no File argument.
%%% A temporary file will be created.
%%% Exactly one of -module Module and File must be given.
%%%
%%% The name of the generated file is "specs_<module>.xml". Its exact
%%% format is not further described here.

main(Args) ->
case catch parse(Args, [], ".", no_module) of
{ok, FileSpec, InclFs, Dir} ->
call_edoc(FileSpec, InclFs, Dir);
{error, Msg} ->
io:format("~s\n", [Msg]),
usage()
end.

parse(["-o"++Dir | Opts], InclFs, _, Module) ->
parse(Opts, InclFs, Dir, Module);
parse(["-I"++I | Opts], InclFs, Dir, Module) ->
parse(Opts, [I | InclFs], Dir, Module);
parse(["-module", Module | Opts], InclFs, Dir, _) ->
parse(Opts, InclFs, Dir, Module);
parse([File], InclFs, Dir, no_module) ->
{ok, {file, File}, lists:reverse(InclFs), Dir};
parse([_], _, _, _) ->
{error, io_lib:format("Cannot have both -module option and file", [])};
parse([], _, _, no_module) ->
{error, io_lib:format("Missing -module option or file", [])};
parse([], InclFs, Dir, Module) ->
{ok, {module, Module}, lists:reverse(InclFs), Dir};
parse(Args, _, _, _) ->
{error, io_lib:format("Bad arguments: ~p", [Args])}.

usage() ->
io:format("usage: ~s [-I<include_dir>]... [-o<out_dir>] "
"[-module <module>] [file]\n", [escript:script_name()]),
halt(1).

call_edoc(FileSpec, InclFs, Dir) ->
Incl = [{includes, InclFs}],
Pre = [{preprocess, true}],
Choice = [{dialyzer_specs, all}],
DirOpt = [{dir, Dir}],
Pretty = [{pretty_print, erl_pp}],
Layout = [{layout, otp_specs},
{file_suffix, ".specs"},
{stylesheet, ""}],
Warn = [{report_missing_type, false},
{report_type_mismatch, false}],
OptionList = (DirOpt ++ Choice ++ Pre ++ Warn ++ Pretty ++ Layout ++ Incl),
{File, TmpFile} = case FileSpec of
{file, File0} ->
{File0, false};
{module, Module} ->
{create_tmp_file(Dir, Module), true}
end,
try edoc:files([File], OptionList) of
ok ->
clean_up(Dir, File, TmpFile),
rename(Dir, File)
catch
_:_ ->
io:format("EDoc could not process file '~s'\n", [File]),
clean_up(Dir, File, TmpFile),
halt(3)
end.

rename(Dir, F) ->
Mod = filename:basename(F, ".erl"),
Old = filename:join(Dir, Mod ++ ".specs"),
New = filename:join(Dir, "specs_" ++ Mod ++ ".xml"),
case file:rename(Old, New) of
ok ->
ok;
{error, R} ->
R1 = file:format_error(R),
io:format("could not rename file '~s': ~s\n", [New, R1]),
halt(2)
end.

clean_up(Dir, File, TmpFile) ->
[file:delete(File) || TmpFile],
_ = [file:delete(filename:join(Dir, F)) ||
F <- ["packages-frame.html",
"overview-summary.html",
"modules-frame.html",
"index.html", "erlang.png", "edoc-info"]],
ok.

create_tmp_file(Dir, Module) ->
TmpFile = filename:join(Dir, Module++".erl"),
case file:write_file(TmpFile, "-module(" ++ Module ++ ").\n") of
ok ->
TmpFile;
{error, R} ->
R1 = file:format_error(R),
io:format("could not write file '~s': ~s\n", [TmpFile, R1]),
halt(2)
end.
107 changes: 107 additions & 0 deletions lib/erl_docgen/priv/bin/xref_mod_app.escript
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/usr/bin/env escript
%% -*- erlang -*-
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 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%

%%% Find all applications and all modules given a root directory.
%%% Output an XML file that can be used for finding which application
%%% a given module belongs to.
%%%
%%% Options:
%%%
%%% "-topdir <D>" Applications are found under D/lib/.
%%% The default value is $ERL_TOP.
%%%
%%% "-outfile <F>" Output is written onto F.
%%% The default value is "mod2app.xml".
%%%
%%% The output file has the following format:
%%%
%%% <?xml version="1.0"?>
%%% <mod2app>
%%% <module name="ModName1">AppName1</module>
%%% ...
%%% <mod2app>
%%%
%%% meaning that module ModName1 resides in application AppName1.

main(Args) ->
case catch parse(Args, os:getenv("ERL_TOP"), "mod2app.xml") of
{ok, TopDir, OutFile} ->
case modapp(TopDir) of
[] ->
io:format("no applications found\n"),
halt(3);
MA ->
Layout = layout(MA),
XML = xmerl:export_simple(Layout, xmerl_xml),
write_file(XML, OutFile)
end;
{error, Msg} ->
io:format("~s\n", [Msg]),
usage()
end.

parse(["-topdir", TopDir | Opts], _, OutFile) ->
parse(Opts, TopDir, OutFile);
parse(["-outfile", OutFile | Opts], TopDir, _) ->
parse(Opts, TopDir, OutFile);
parse([], TopDir, OutFile) ->
{ok, TopDir, OutFile};
parse([Opt | _], _, _) ->
{error, io_lib:format("Bad option: ~p", [Opt])}.

usage() ->
io:format("usage: ~s [-topdir <dir>] [-outfile <file>]\n",
[escript:script_name()]),
halt(1).

modapp(TopDir) ->
AppDirs = filelib:wildcard(filename:join([TopDir,"lib","*"])),
AM = [appmods(D) || D <- AppDirs],
lists:keysort(1, [{M,A} || {A,Ms} <- AM, M <- Ms]).

%% It's OK if too much data is generated as long as all applications
%% and all modules are mentioned.
appmods(D) ->
ErlFiles = filelib:wildcard(filename:join([D,"src","*.erl"])),
AppV = filename:basename(D),
App = case string:rstr(AppV, "-") of
0 -> AppV;
P -> string:sub_string(AppV, 1, P-1)
end,
{App, [filename:basename(EF, ".erl") || EF <- ErlFiles]}.

-include_lib("xmerl/include/xmerl.hrl").

-define(IND(N), lists:duplicate(N, $\s)).
-define(NL, "\n").

layout(MAL) ->
ML = lists:append([[?IND(2),{module,[{name,M}],[A]},?NL] || {M,A} <- MAL]),
[?NL,{mod2app,[?NL|ML]},?NL].

write_file(Text, File) ->
case file:open(File, [write]) of
{ok, FD} ->
io:put_chars(FD, Text),
ok = file:close(FD);
{error, R} ->
R1 = file:format_error(R),
io:format("could not write file '~s': ~s\n", [File, R1]),
halt(2)
end.
7 changes: 5 additions & 2 deletions lib/erl_docgen/priv/docbuilder_dtd/common.refs.dtd
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,18 @@

<!ELEMENT description (%block;|quote|br|marker|warning|note)* >
<!ELEMENT funcs (func)+ >
<!ELEMENT func (name+,fsummary,type?,desc?) >
<!ELEMENT func (name+,type_desc+,fsummary,type?,desc?) >
<!-- ELEMENT name is defined in each ref dtd -->
<!ELEMENT fsummary (#PCDATA|c|em)* >
<!ELEMENT type (v,d?)+ >
<!ELEMENT v (#PCDATA) >
<!ELEMENT d (#PCDATA|c|em)* >
<!ELEMENT desc (%block;|quote|br|marker|warning|note)* >
<!ELEMENT desc (%block;|quote|br|marker|warning|note|anno)* >
<!ELEMENT authors (aname,email)+ >
<!ELEMENT aname (#PCDATA) >
<!ELEMENT email (#PCDATA) >
<!ELEMENT section (marker*,title,(%block;|quote|br|marker|
warning|note)*) >
<!ELEMENT datatypes (datatype)+ >
<!ELEMENT datatype (name+,desc?) >
<!ELEMENT type_desc (#PCDATA) >
2 changes: 1 addition & 1 deletion lib/erl_docgen/priv/docbuilder_dtd/erlref.dtd
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
%common.refs;

<!ELEMENT erlref (header,module,modulesummary,description,
(section|funcs)*,authors?) >
(section|funcs|datatypes)*,authors?) >
<!ELEMENT module (#PCDATA) >
<!ELEMENT modulesummary (#PCDATA) >

Expand Down
Loading

0 comments on commit 49b581e

Please sign in to comment.