diff options
Diffstat (limited to 'lib/edoc')
29 files changed, 413 insertions, 654 deletions
diff --git a/lib/edoc/doc/overview.edoc b/lib/edoc/doc/overview.edoc index 2af425272e..0ced8cab32 100644 --- a/lib/edoc/doc/overview.edoc +++ b/lib/edoc/doc/overview.edoc @@ -76,8 +76,6 @@ The following are the main functions for running EDoc: <ul> <li>{@link edoc:application/2}: Creates documentation for a typical Erlang application.</li> - <li>{@link edoc:packages/2}: Creates documentation for one or - more packages, automatically locating source files.</li> <li>{@link edoc:files/2}: Creates documentation for a specified set of source files.</li> <li>{@link edoc:run/3}: General interface function; the common @@ -184,7 +182,7 @@ The following tags can be used anywhere within a module: path (see {@link edoc:read_source/2}).</dd> <dt><a name="gtag-todo">`@todo' (or `@TODO')</a></dt> - <dd>Attaches a To-Do note to a function, module, package, or + <dd>Attaches a To-Do note to a function, module or overview-page. The content can be any XHTML text describing the issue, e.g.: ```%% @TODO Finish writing the documentation.''' @@ -338,7 +336,7 @@ The following tags can be used before a module declaration: <dt><a name="mtag-since">`@since'</a></dt> <dd>Specifies when the module was introduced, with respect to - the application, package, release or distribution it is part + the application, release or distribution it is part of. The content can be arbitrary text.</dd> <dt><a name="mtag-version">`@version'</a></dt> @@ -445,7 +443,6 @@ possible formats for references are: <table border="1" summary="reference syntax"> <tr><th>Reference syntax</th><th>Example</th><th>Scope</th></tr> <tr><td>`Module'</td><td>{@link edoc_run}, `erl.lang.list'</td><td>Global</td></tr> - <tr><td>`Package.*'</td><td>`erl.lang.*'</td><td>Global</td></tr> <tr><td>`Function/Arity'</td><td>`file/2'</td><td>Within module</td></tr> <tr><td>`Module:Function/Arity'</td><td>{@link edoc:application/2}</td><td>Global</td></tr> <tr><td>`Type()'</td><td>`filename()'</td><td>Within module</td></tr> @@ -531,7 +528,7 @@ after the empty line into separate paragraphs. For example: ```%% @doc This will all be part of the first paragraph. %% It can stretch over several lines and contain <em>any %% XHTML markup</em>. - %% + %% %% This is the second paragraph. The above line is %% regarded as "empty" by EDoc, even though it ends with %% a space.''' @@ -685,17 +682,6 @@ information. User-defined macros override predefined macros. <dd>Expands to the current date, as "<tt>Month Day Year</tt>", e.g. "{@date}".</dd> - <dt><a name="predefmacro-docRoot"><code>@{@docRoot}</code></a></dt> - <dd>Expands to the relative URL path (such as - `"../../.."') from the current page to the root - directory of the generated documentation. This can be used to - create XHTML references such as `<img - src="@{@docRoot}/images/logo.jpeg">' that are independent of how - deep down in a package structure they occur. If packages are not - used (i.e., if all modules are in the "empty" package), - <code>@{@docRoot}</code> will always resolve to the empty - string.</dd> - <dt><a name="predefmacro-link"><code>@{@link <em>reference</em>. <em>description</em>}</code></a></dt> <dd>This creates a hypertext link; cf. the @@ -710,9 +696,6 @@ information. User-defined macros override predefined macros. <dd>Expands to the name of the current module. Only defined when a module is being processed.</dd> - <dt><a name="predefmacro-package"><code>@{@package}</code></a></dt> - <dd>Expands to the name of the current package.</dd> - <dt><a name="predefmacro-section"><code>@{@section <em>heading</em>}</code></a></dt> <dd>Expands to a hypertext link to the specified section heading; diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml index d7cbfa1fdc..e350adb540 100644 --- a/lib/edoc/doc/src/notes.xml +++ b/lib/edoc/doc/src/notes.xml @@ -31,6 +31,57 @@ <p>This document describes the changes made to the EDoc application.</p> +<section><title>Edoc 0.7.16</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Maps: Properly align union typed assoc values in + documentation</p> + <p> + Own Id: OTP-12190</p> + </item> + </list> + </section> + +</section> + +<section><title>Edoc 0.7.15</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix spec to doc generation from erl_docgen and edoc for + maps</p> + <p> + Own Id: OTP-12058</p> + </item> + </list> + </section> + +</section> + +<section><title>Edoc 0.7.14</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> The default encoding for Erlang source files is now + UTF-8. As a temporary measure to ease the transition from + the old default of Latin-1, if EDoc encounters byte + sequences that are not valid UTF-8 sequences, EDoc will + re-try in Latin-1 mode. This workaround will be removed + in a future release. </p> + <p> + Own Id: OTP-12008</p> + </item> + </list> + </section> + +</section> + <section><title>Edoc 0.7.13</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/edoc/include/edoc_doclet.hrl b/lib/edoc/include/edoc_doclet.hrl index 60ec7f44e4..ac6763fb33 100644 --- a/lib/edoc/include/edoc_doclet.hrl +++ b/lib/edoc/include/edoc_doclet.hrl @@ -1,6 +1,6 @@ %% ===================================================================== %% Header file for EDoc doclet modules. -%% +%% %% Copyright (C) 2001-2004 Richard Carlsson %% %% This library is free software; you can redistribute it and/or modify @@ -43,16 +43,11 @@ %% @type doclet_gen() = #doclet_gen{sources = [string()], %% app = no_app() | atom(), -%% packages = [atom()], -%% modules = [atom()], -%% modules = [atom()], -%% filemap = function()} +%% modules = [atom()]} -record(doclet_gen, {sources = [], app = ?NO_APP, - packages = [], - modules = [], - filemap + modules = [] }). %% @type doclet_toc() = #doclet_gen{paths = [string()], diff --git a/lib/edoc/priv/edoc.dtd b/lib/edoc/priv/edoc.dtd index ba4ac0db28..4278a9e643 100644 --- a/lib/edoc/priv/edoc.dtd +++ b/lib/edoc/priv/edoc.dtd @@ -2,20 +2,13 @@ <!-- EDoc DTD Version 0.3 --> <!ELEMENT overview (title, description?, author*, copyright?, version?, - since?, see*, reference*, todo?, packages, modules)> + since?, see*, reference*, todo?, modules)> <!ATTLIST overview root CDATA #IMPLIED encoding CDATA #IMPLIED> <!ELEMENT title (#PCDATA)> -<!ELEMENT package (description?, author*, copyright?, version?, - since?, deprecated?, see*, reference*, todo?, - modules)> -<!ATTLIST package - name CDATA #REQUIRED - root CDATA #IMPLIED> - <!ELEMENT modules (module+)> diff --git a/lib/edoc/priv/stylesheet.css b/lib/edoc/priv/stylesheet.css index e426a90483..ab170c091f 100644 --- a/lib/edoc/priv/stylesheet.css +++ b/lib/edoc/priv/stylesheet.css @@ -27,10 +27,10 @@ div.spec { margin-left: 2em; background-color: #eeeeee; } -a.module,a.package { +a.module { text-decoration:none } -a.module:hover,a.package:hover { +a.module:hover { background-color: #eeeeee; } ul.definitions { diff --git a/lib/edoc/src/edoc.erl b/lib/edoc/src/edoc.erl index a87a8471e3..78915e8943 100644 --- a/lib/edoc/src/edoc.erl +++ b/lib/edoc/src/edoc.erl @@ -24,12 +24,11 @@ %% TODO: option for ignoring functions matching some pattern ('..._test_'/0) %% TODO: @private_type tag, opaque unless generating private docs? %% TODO: document the record type syntax -%% TODO: some 'skip' option for ignoring particular modules/packages? -%% TODO: intermediate-level packages: document even if no local sources. +%% TODO: some 'skip' option for ignoring particular modules? %% TODO: multiline comment support (needs modified comment representation) %% TODO: config-file for default settings %% TODO: config: locations of all local docdirs; generate local doc-index page -%% TODO: config: URL:s of offline packages/apps +%% TODO: config: URL:s of offline apps %% TODO: config: default stylesheet %% TODO: config: default header/footer, etc. %% TODO: offline linkage @@ -45,10 +44,10 @@ -module(edoc). --export([packages/1, packages/2, files/1, files/2, +-export([files/1, files/2, application/1, application/2, application/3, toc/1, toc/2, toc/3, - run/3, + run/2, file/1, file/2, read/1, read/2, layout/1, layout/2, @@ -68,15 +67,15 @@ file(Name) -> file(Name, []). -%% @spec file(filename(), proplist()) -> ok +%% @spec file(filename(), proplist()) -> ok %% %% @type filename() = //kernel/file:filename() %% @type proplist() = [term()] %% %% @deprecated This is part of the old interface to EDoc and is mainly %% kept for backwards compatibility. The preferred way of generating -%% documentation is through one of the functions {@link application/2}, -%% {@link packages/2} and {@link files/2}. +%% documentation is through one of the functions {@link application/2} +%% and {@link files/2}. %% %% @doc Reads a source code file and outputs formatted documentation to %% a corresponding file. @@ -121,44 +120,24 @@ file(Name, Options) -> ?DEFAULT_FILE_SUFFIX), Dir = proplists:get_value(dir, Options, filename:dirname(Name)), Encoding = [{encoding, edoc_lib:read_encoding(Name, [])}], - edoc_lib:write_file(Text, Dir, BaseName ++ Suffix, '', Encoding). + edoc_lib:write_file(Text, Dir, BaseName ++ Suffix, Encoding). -%% TODO: better documentation of files/1/2, packages/1/2, application/1/2/3 +%% TODO: better documentation of files/1/2, application/1/2/3 -%% @spec (Files::[filename() | {package(), [filename()]}]) -> ok -%% @equiv packages(Packages, []) +%% @spec (Files::[filename()]) -> ok files(Files) -> files(Files, []). -%% @spec (Files::[filename() | {package(), [filename()]}], +%% @spec (Files::[filename()], %% Options::proplist()) -> ok -%% @doc Runs EDoc on a given set of source files. See {@link run/3} for +%% @doc Runs EDoc on a given set of source files. See {@link run/2} for %% details, including options. %% @equiv run([], Files, Options) files(Files, Options) -> - run([], Files, Options). - -%% @spec (Packages::[package()]) -> ok -%% @equiv packages(Packages, []) - -packages(Packages) -> - packages(Packages, []). - -%% @spec (Packages::[package()], Options::proplist()) -> ok -%% @type package() = atom() | string() -%% -%% @doc Runs EDoc on a set of packages. The `source_path' option is used -%% to locate the files; see {@link run/3} for details, including -%% options. This function automatically appends the current directory to -%% the source path. -%% -%% @equiv run(Packages, [], Options) - -packages(Packages, Options) -> - run(Packages, [], Options ++ [{source_path, [?CURRENT_DIR]}]). + run(Files, Options). %% @spec (Application::atom()) -> ok %% @equiv application(Application, []) @@ -194,7 +173,7 @@ application(App, Options) when is_atom(App) -> %% subdirectory, if it exists, or otherwise in the application %% directory itself. %% </li> -%% <li>The {@link run/3. `subpackages'} option is turned on. All found +%% <li>The {@link run/2. `subpackages'} option is turned on. All found %% source files will be processed. %% </li> %% <li>The `include' subdirectory is automatically added to the @@ -203,7 +182,7 @@ application(App, Options) when is_atom(App) -> %% </li> %% </ul> %% -%% See {@link run/3} for details, including options. +%% See {@link run/2} for details, including options. %% %% @see application/2 @@ -219,7 +198,7 @@ application(App, Dir, Options) when is_atom(App) -> {includes, [filename:join(Dir, "include")]}], Opts1 = set_app_default(App, Dir, Opts), %% Recursively document all subpackages of '' - i.e., everything. - run([''], [], [{application, App} | Opts1]). + run([], [{application, App} | Opts1]). %% Try to set up a default application base URI in a smart way if the %% user has not specified it explicitly. @@ -240,31 +219,20 @@ set_app_default(App, Dir0, Opts) -> Opts end. -%% If no source files are found for a (specified) package, no package -%% documentation will be generated either (even if there is a -%% package-documentation file). This is the way it should be. For -%% specified files, use empty package (unless otherwise specified). The -%% assumed package is always used for creating the output. If the actual -%% module or package of the source differs from the assumption gathered -%% from the path and file name, a warning should be issued (since links -%% are likely to be incorrect). - opt_defaults() -> - [packages]. + []. opt_negations() -> [{no_preprocess, preprocess}, {no_subpackages, subpackages}, - {no_report_missing_types, report_missing_types}, - {no_packages, packages}]. + {no_report_missing_types, report_missing_types}]. -%% @spec run(Packages::[package()], -%% Files::[filename() | {package(), [filename()]}], +%% @spec run(Files::[filename()], %% Options::proplist()) -> ok -%% @doc Runs EDoc on a given set of source files and/or packages. Note +%% @doc Runs EDoc on a given set of source files. Note %% that the doclet plugin module has its own particular options; see the %% `doclet' option below. -%% +%% %% Also see {@link layout/2} for layout-related options, and %% {@link get_doc/2} for options related to reading source %% files. @@ -298,11 +266,6 @@ opt_negations() -> %% The default doclet module is {@link edoc_doclet}; see {@link %% edoc_doclet:run/2} for doclet-specific options. %% </dd> -%% <dt>{@type {exclude_packages, [package()]@}} -%% </dt> -%% <dd>Lists packages to be excluded from the documentation. Typically -%% used in conjunction with the `subpackages' option. -%% </dd> %% <dt>{@type {file_suffix, string()@}} %% </dt> %% <dd>Specifies the suffix used for output files. The default value is @@ -314,22 +277,6 @@ opt_negations() -> %% target directory will be ignored and overwritten. The default %% value is `false'. %% </dd> -%% <dt>{@type {packages, boolean()@}} -%% </dt> -%% <dd>If the value is `true', it it assumed that packages (module -%% namespaces) are being used, and that the source code directory -%% structure reflects this. The default value is `true'. (Usually, -%% this does the right thing even if all the modules belong to the -%% top-level "empty" package.) `no_packages' is an alias for -%% `{packages, false}'. See the `subpackages' option below for -%% further details. -%% -%% If the source code is organized in a hierarchy of -%% subdirectories although it does not use packages, use -%% `no_packages' together with the recursive-search `subpackages' -%% option (on by default) to automatically generate documentation -%% for all the modules. -%% </dd> %% <dt>{@type {source_path, [filename()]@}} %% </dt> %% <dd>Specifies a list of file system paths used to locate the source @@ -345,7 +292,7 @@ opt_negations() -> %% <dd>If the value is `true', all subpackages of specified packages %% will also be included in the documentation. The default value is %% `false'. `no_subpackages' is an alias for `{subpackages, -%% false}'. See also the `exclude_packages' option. +%% false}'. %% %% Subpackage source files are found by recursively searching %% for source code files in subdirectories of the known source code @@ -358,38 +305,31 @@ opt_negations() -> %% </dl> %% %% @see files/2 -%% @see packages/2 %% @see application/2 %% NEW-OPTIONS: source_path, application %% INHERIT-OPTIONS: init_context/1 %% INHERIT-OPTIONS: expand_sources/2 %% INHERIT-OPTIONS: target_dir_info/5 -%% INHERIT-OPTIONS: edoc_lib:find_sources/3 +%% INHERIT-OPTIONS: edoc_lib:find_sources/2 %% INHERIT-OPTIONS: edoc_lib:run_doclet/2 %% INHERIT-OPTIONS: edoc_lib:get_doc_env/4 -run(Packages, Files, Opts0) -> +run(Files, Opts0) -> Opts = expand_opts(Opts0), Ctxt = init_context(Opts), Dir = Ctxt#context.dir, Path = proplists:append_values(source_path, Opts), - Ss = sources(Path, Packages, Opts), + Ss = sources(Path, Opts), {Ss1, Ms} = expand_sources(expand_files(Files) ++ Ss, Opts), - Ps = [P || {_, P, _, _} <- Ss1], App = proplists:get_value(application, Opts, ?NO_APP), - {App1, Ps1, Ms1} = target_dir_info(Dir, App, Ps, Ms, Opts), - %% The "empty package" is never included in the list of packages. - Ps2 = edoc_lib:unique(lists:sort(Ps1)) -- [''], + {App1, Ms1} = target_dir_info(Dir, App, Ms, Opts), Ms2 = edoc_lib:unique(lists:sort(Ms1)), - Fs = package_files(Path, Ps2), - Env = edoc_lib:get_doc_env(App1, Ps2, Ms2, Opts), + Env = edoc_lib:get_doc_env(App1, Ms2, Opts), Ctxt1 = Ctxt#context{env = Env}, Cmd = #doclet_gen{sources = Ss1, app = App1, - packages = Ps2, - modules = Ms2, - filemap = Fs + modules = Ms2 }, F = fun (M) -> M:run(Cmd, Ctxt1) @@ -401,42 +341,22 @@ expand_opts(Opts0) -> Opts0 ++ opt_defaults()). %% NEW-OPTIONS: dir -%% DEFER-OPTIONS: run/3 +%% DEFER-OPTIONS: run/2 init_context(Opts) -> #context{dir = proplists:get_value(dir, Opts, ?CURRENT_DIR), opts = Opts }. -%% INHERIT-OPTIONS: edoc_lib:find_sources/3 - -sources(Path, Packages, Opts) -> - lists:foldl(fun (P, Xs) -> - edoc_lib:find_sources(Path, P, Opts) ++ Xs - end, - [], Packages). - -package_files(Path, Packages) -> - Name = ?PACKAGE_FILE, % this is hard-coded for now - D = lists:foldl(fun (P, D) -> - F = edoc_lib:find_file(Path, P, Name), - dict:store(P, F, D) - end, - dict:new(), Packages), - fun (P) -> - case dict:find(P, D) of - {ok, F} -> F; - error -> "" - end - end. +%% INHERIT-OPTIONS: edoc_lib:find_sources/2 + +sources(Path, Opts) -> + edoc_lib:find_sources(Path, Opts). %% Expand user-specified sets of files. -expand_files([{P, Fs1} | Fs]) -> - [{P, filename:basename(F), filename:dirname(F)} || F <- Fs1] - ++ expand_files(Fs); expand_files([F | Fs]) -> - [{'', filename:basename(F), filename:dirname(F)} | + [{filename:basename(F), filename:dirname(F)} | expand_files(Fs)]; expand_files([]) -> []. @@ -444,26 +364,23 @@ expand_files([]) -> %% Create the (assumed) full module names. Keep only the first source %% for each module, but preserve the order of the list. -%% NEW-OPTIONS: source_suffix, packages -%% DEFER-OPTIONS: run/3 +%% NEW-OPTIONS: source_suffix +%% DEFER-OPTIONS: run/2 expand_sources(Ss, Opts) -> Suffix = proplists:get_value(source_suffix, Opts, ?DEFAULT_SOURCE_SUFFIX), - Ss1 = case proplists:get_bool(packages, Opts) of - true -> Ss; - false -> [{'',F,D} || {_P,F,D} <- Ss] - end, + Ss1 = [{F,D} || {F,D} <- Ss], expand_sources(Ss1, Suffix, sets:new(), [], []). -expand_sources([{'', F, D} | Fs], Suffix, S, As, Ms) -> +expand_sources([{F, D} | Fs], Suffix, S, As, Ms) -> M = list_to_atom(filename:rootname(F, Suffix)), case sets:is_element(M, S) of true -> expand_sources(Fs, Suffix, S, As, Ms); false -> S1 = sets:add_element(M, S), - expand_sources(Fs, Suffix, S1, [{M, '', F, D} | As], + expand_sources(Fs, Suffix, S1, [{M, F, D} | As], [M | Ms]) end; expand_sources([], _Suffix, _S, As, Ms) -> @@ -471,16 +388,15 @@ expand_sources([], _Suffix, _S, As, Ms) -> %% NEW-OPTIONS: new -target_dir_info(Dir, App, Ps, Ms, Opts) -> +target_dir_info(Dir, App, Ms, Opts) -> case proplists:get_bool(new, Opts) of true -> - {App, Ps, Ms}; + {App, Ms}; false -> - {App1, Ps1, Ms1} = edoc_lib:read_info_file(Dir), + {App1, Ms1} = edoc_lib:read_info_file(Dir), {if App == ?NO_APP -> App1; true -> App end, - Ps ++ Ps1, Ms ++ Ms1} end. @@ -510,7 +426,7 @@ toc(Dir, Opts) -> toc(Dir, Paths, Opts0) -> Opts = expand_opts(Opts0 ++ [{dir, Dir}]), Ctxt = init_context(Opts), - Env = edoc_lib:get_doc_env('', [], [], Opts), + Env = edoc_lib:get_doc_env('', [], Opts), Ctxt1 = Ctxt#context{env = Env}, F = fun (M) -> M:run(#doclet_toc{paths=Paths}, Ctxt1) @@ -562,7 +478,7 @@ layout(Doc) -> %% </dl> %% %% @see layout/1 -%% @see run/3 +%% @see run/2 %% @see read/2 %% @see file/2 @@ -696,15 +612,44 @@ read_source_2(Name, Opts) -> %% The line of the dot token will be copied to the integer token. parse_file(Name, Includes, Macros) -> - case epp:open(Name, Includes, Macros) of - {ok, Epp} -> - try {ok, parse_file(Epp)} + case parse_file(utf8, Name, Includes, Macros) of + invalid_unicode -> + parse_file(latin1, Name, Includes, Macros); + Ret -> + Ret + end. + +parse_file(DefEncoding, Name, Includes, Macros) -> + Options = [{name, Name}, + {includes, Includes}, + {macros, Macros}, + {default_encoding, DefEncoding}], + case epp:open([extra | Options]) of + {ok, Epp, Extra} -> + try parse_file(Epp) of + Forms -> + Encoding = proplists:get_value(encoding, Extra), + case find_invalid_unicode(Forms) of + invalid_unicode when Encoding =/= utf8 -> + invalid_unicode; + _ -> + {ok, Forms} + end after _ = epp:close(Epp) end; Error -> Error end. +find_invalid_unicode([H|T]) -> + case H of + {error,{_Line,file_io_server,invalid_unicode}} -> + invalid_unicode; + _Other -> + find_invalid_unicode(T) + end; +find_invalid_unicode([]) -> none. + parse_file(Epp) -> case scan_and_parse(Epp) of {ok, Form} -> @@ -827,7 +772,7 @@ get_doc(File) -> %% edoc_lib:get_doc_env/4} for further options. %% %% @see get_doc/3 -%% @see run/3 +%% @see run/2 %% @see edoc_extract:source/5 %% @see read/2 %% @see layout/2 diff --git a/lib/edoc/src/edoc.hrl b/lib/edoc/src/edoc.hrl index 44c5d6fef4..5b0fb68cf9 100644 --- a/lib/edoc/src/edoc.hrl +++ b/lib/edoc/src/edoc.hrl @@ -1,6 +1,6 @@ %% ===================================================================== %% Header file for EDoc -%% +%% %% Copyright (C) 2001-2004 Richard Carlsson %% %% This library is free software; you can redistribute it and/or modify @@ -25,9 +25,7 @@ -define(APPLICATION, edoc). -define(INFO_FILE, "edoc-info"). --define(PACKAGE_FILE, "package.edoc"). -define(OVERVIEW_FILE, "overview.edoc"). --define(PACKAGE_SUMMARY, "package-summary"). -define(DEFAULT_SOURCE_SUFFIX, ".erl"). -define(DEFAULT_FILE_SUFFIX, ".html"). -define(DEFAULT_DOCLET, edoc_doclet). @@ -65,13 +63,10 @@ %% Environment for generating documentation data -record(env, {module = [], - package = [], root = "", file_suffix, - package_summary, apps, modules, - packages, app_default, macros = [], includes = [] diff --git a/lib/edoc/src/edoc_data.erl b/lib/edoc/src/edoc_data.erl index f88ba05f4b..b797d74a71 100644 --- a/lib/edoc/src/edoc_data.erl +++ b/lib/edoc/src/edoc_data.erl @@ -26,7 +26,7 @@ -module(edoc_data). --export([module/4, package/4, overview/4, type/2]). +-export([module/4, overview/4, type/2]). -export([hidden_filter/2, get_all_tags/1]). @@ -173,21 +173,34 @@ callbacks(Es, Module, Env, Opts) -> lists:keymember(callback, 1, Module#module.attributes) of true -> - try (Module#module.name):behaviour_info(callbacks) of - Fs -> - Fs1 = [{F,A} || {F,A} <- Fs, is_atom(F), is_integer(A)], - if Fs1 =:= [] -> - []; - true -> - [{callbacks, - [callback(F, Env, Opts) || F <- Fs1]}] - end - catch - _:_ -> [] - end; + M = Module#module.name, + Fs = get_callback_functions(M, callbacks), + Os1 = get_callback_functions(M, optional_callbacks), + Fs1 = [FA || FA <- Fs, not lists:member(FA, Os1)], + Req = if Fs1 =:= [] -> + []; + true -> + [{callbacks, + [callback(FA, Env, Opts) || FA <- Fs1]}] + end, + Opt = if Os1 =:= [] -> + []; + true -> + [{optional_callbacks, + [callback(FA, Env, Opts) || FA <- Os1]}] + end, + Req ++ Opt; false -> [] end. +get_callback_functions(M, Callbacks) -> + try + [FA || {F, A} = FA <- M:behaviour_info(Callbacks), + is_atom(F), is_integer(A), A >= 0] + catch + _:_ -> [] + end. + %% <!ELEMENT callback EMPTY> %% <!ATTLIST callback %% name CDATA #REQUIRED @@ -497,41 +510,14 @@ get_tags(_, []) -> []. type(T, Env) -> xmerl_lib:expand_element({type, [edoc_types:to_xml(T, Env)]}). -%% <!ELEMENT package (description?, author*, copyright?, version?, -%% since?, deprecated?, see*, reference*, todo?, -%% modules)> -%% <!ATTLIST package -%% name CDATA #REQUIRED -%% root CDATA #IMPLIED> -%% <!ELEMENT modules (module+)> - -package(Package, Tags, Env, Opts) -> - Env1 = Env#env{package = Package, - root = edoc_refs:relative_package_path('', Package)}, - xmerl_lib:expand_element(package_1(Package, Tags, Env1, Opts)). - -package_1(Package, Tags, Env, Opts) -> - {package, [{root, Env#env.root}], - ([{packageName, [atom_to_list(Package)]}] - ++ get_doc(Tags) - ++ authors(Tags) - ++ get_copyright(Tags) - ++ get_version(Tags) - ++ get_since(Tags) - ++ get_deprecated(Tags) - ++ sees(Tags, Env) - ++ references(Tags) - ++ todos(Tags, Opts)) - }. - %% <!ELEMENT overview (title, description?, author*, copyright?, version?, -%% since?, see*, reference*, todo?, packages, modules)> +%% since?, see*, reference*, todo?, modules)> %% <!ATTLIST overview %% root CDATA #IMPLIED> %% <!ELEMENT title (#PCDATA)> overview(Title, Tags, Env, Opts) -> - Env1 = Env#env{package = '', + Env1 = Env#env{ root = ""}, xmerl_lib:expand_element(overview_1(Title, Tags, Env1, Opts)). diff --git a/lib/edoc/src/edoc_doclet.erl b/lib/edoc/src/edoc_doclet.erl index 5653b5894b..5961ca8cc0 100644 --- a/lib/edoc/src/edoc_doclet.erl +++ b/lib/edoc/src/edoc_doclet.erl @@ -42,9 +42,7 @@ -define(DEFAULT_FILE_SUFFIX, ".html"). -define(INDEX_FILE, "index.html"). -define(OVERVIEW_FILE, "overview.edoc"). --define(PACKAGE_SUMMARY, "package-summary.html"). -define(OVERVIEW_SUMMARY, "overview-summary.html"). --define(PACKAGES_FRAME, "packages-frame.html"). -define(MODULES_FRAME, "modules-frame.html"). -define(STYLESHEET, "stylesheet.css"). -define(IMAGE, "erlang.png"). @@ -52,11 +50,10 @@ -include_lib("xmerl/include/xmerl.hrl"). -%% Sources is the list of inputs in the order they were found. Packages -%% and Modules are sorted lists of atoms without duplicates. (They +%% Sources is the list of inputs in the order they were found. +%% Modules are sorted lists of atoms without duplicates. (They %% usually include the data from the edoc-info file in the target -%% directory, if it exists.) Note that the "empty package" is never -%% included in Packages! +%% directory, if it exists.) %% @spec (Command::doclet_gen() | doclet_toc(), edoc_context()) -> ok %% @doc Main doclet entry point. See the file <a @@ -117,14 +114,12 @@ run(#doclet_gen{}=Cmd, Ctxt) -> gen(Cmd#doclet_gen.sources, Cmd#doclet_gen.app, - Cmd#doclet_gen.packages, Cmd#doclet_gen.modules, - Cmd#doclet_gen.filemap, Ctxt); run(#doclet_toc{}=Cmd, Ctxt) -> toc(Cmd#doclet_toc.paths, Ctxt). -gen(Sources, App, Packages, Modules, FileMap, Ctxt) -> +gen(Sources, App, Modules, Ctxt) -> Dir = Ctxt#context.dir, Env = Ctxt#context.env, Options = Ctxt#context.opts, @@ -132,11 +127,9 @@ gen(Sources, App, Packages, Modules, FileMap, Ctxt) -> CSS = stylesheet(Options), {Modules1, Error} = sources(Sources, Dir, Modules, Env, Options), modules_frame(Dir, Modules1, Title, CSS), - packages(Packages, Dir, FileMap, Env, Options), - packages_frame(Dir, Packages, Title, CSS), overview(Dir, Title, Env, Options), - index_file(Dir, length(Packages) > 1, Title), - edoc_lib:write_info_file(App, Packages, Modules1, Dir), + index_file(Dir, Title), + edoc_lib:write_info_file(App, Modules1, Dir), copy_stylesheet(Dir, Options), copy_image(Dir), %% handle postponed error during processing of source files @@ -182,19 +175,19 @@ sources(Sources, Dir, Modules, Env, Options) -> %% set if it was successful. Errors are just flagged at this stage, %% allowing all source files to be processed even if some of them fail. -source({M, P, Name, Path}, Dir, Suffix, Env, Set, Private, Hidden, +source({M, Name, Path}, Dir, Suffix, Env, Set, Private, Hidden, Error, Options) -> File = filename:join(Path, Name), case catch {ok, edoc:get_doc(File, Env, Options)} of {ok, {Module, Doc}} -> - check_name(Module, M, P, File), + check_name(Module, M, File), case ((not is_private(Doc)) orelse Private) andalso ((not is_hidden(Doc)) orelse Hidden) of true -> Text = edoc:layout(Doc, Options), Name1 = atom_to_list(M) ++ Suffix, Encoding = [{encoding,encoding(Doc)}], - edoc_lib:write_file(Text, Dir, Name1, P, Encoding), + edoc_lib:write_file(Text, Dir, Name1, Encoding), {sets:add_element(Module, Set), Error}; false -> {Set, Error} @@ -204,8 +197,7 @@ source({M, P, Name, Path}, Dir, Suffix, Env, Set, Private, Hidden, {Set, true} end. -check_name(M, M0, P0, File) -> - P = '', +check_name(M, M0, File) -> N = M, N0 = M0, case N of @@ -222,47 +214,12 @@ check_name(M, M0, P0, File) -> ok end end, - if P =/= P0 -> - warning("file '~ts' belongs to package '~s', not '~s'.", - [File, P, P0]); - true -> - ok - end. - - -%% Generating the summary files for packages. - -%% INHERIT-OPTIONS: read_file/4 -%% INHERIT-OPTIONS: edoc_lib:run_layout/2 - -packages(Packages, Dir, FileMap, Env, Options) -> - lists:foreach(fun (P) -> - package(P, Dir, FileMap, Env, Options) - end, - Packages). - -package(P, Dir, FileMap, Env, Opts) -> - Tags = case FileMap(P) of - "" -> - []; - File -> - read_file(File, package, Env, Opts) - end, - Data = edoc_data:package(P, Tags, Env, Opts), - F = fun (M) -> - M:package(Data, Opts) - end, - Text = edoc_lib:run_layout(F, Opts), - edoc_lib:write_file(Text, Dir, ?PACKAGE_SUMMARY, P). - + ok. %% Creating an index file, with some frames optional. %% TODO: get rid of frames, or change doctype to Frameset -index_file(Dir, Packages, Title) -> - Frame1 = {frame, [{src,?PACKAGES_FRAME}, - {name,"packagesFrame"},{title,""}], - []}, +index_file(Dir, Title) -> Frame2 = {frame, [{src,?MODULES_FRAME}, {name,"modulesFrame"},{title,""}], []}, @@ -270,16 +227,7 @@ index_file(Dir, Packages, Title) -> {name,"overviewFrame"},{title,""}], []}, Frameset = {frameset, [{cols,"20%,80%"}], - case Packages of - true -> - [?NL, - {frameset, [{rows,"30%,70%"}], - [?NL, Frame1, ?NL, Frame2, ?NL]} - ]; - false -> - [?NL, Frame2, ?NL] - end - ++ [?NL, Frame3, ?NL, + [?NL, Frame2, ?NL, ?NL, Frame3, ?NL, {noframes, [?NL, {h2, ["This page uses frames"]}, @@ -296,24 +244,6 @@ index_file(Dir, Packages, Title) -> Text = xmerl:export_simple([XML], xmerl_html, []), edoc_lib:write_file(Text, Dir, ?INDEX_FILE). -packages_frame(Dir, Ps, Title, CSS) -> - Body = [?NL, - {h2, [{class, "indextitle"}], ["Packages"]}, - ?NL, - {table, [{width, "100%"}, {border, 0}, - {summary, "list of packages"}], - lists:concat( - [[?NL, - {tr, [{td, [], [{a, [{href, package_ref(P)}, - {target,"overviewFrame"}, - {class, "package"}], - [atom_to_list(P)]}]}]}] - || P <- Ps])}, - ?NL], - XML = xhtml(Title, CSS, Body), - Text = xmerl:export_simple([XML], xmerl_html, []), - edoc_lib:write_file(Text, Dir, ?PACKAGES_FRAME). - modules_frame(Dir, Ms, Title, CSS) -> Body = [?NL, {h2, [{class, "indextitle"}], ["Modules"]}, @@ -334,11 +264,7 @@ modules_frame(Dir, Ms, Title, CSS) -> edoc_lib:write_file(Text, Dir, ?MODULES_FRAME). module_ref(M) -> - edoc_refs:relative_package_path(M, '') ++ ?DEFAULT_FILE_SUFFIX. - -package_ref(P) -> - edoc_lib:join_uri(edoc_refs:relative_package_path(P, ''), - ?PACKAGE_SUMMARY). + atom_to_list(M) ++ ?DEFAULT_FILE_SUFFIX. xhtml(Title, CSS, Content) -> xhtml_1(Title, CSS, {body, [{bgcolor, "white"}], Content}). @@ -372,7 +298,7 @@ overview(Dir, Title, Env, Opts) -> end, Text = edoc_lib:run_layout(F, Opts), EncOpts = [{encoding,Encoding}], - edoc_lib:write_file(Text, Dir, ?OVERVIEW_SUMMARY, '', EncOpts). + edoc_lib:write_file(Text, Dir, ?OVERVIEW_SUMMARY, EncOpts). copy_image(Dir) -> case code:priv_dir(?EDOC_APP) of @@ -505,7 +431,7 @@ app_index_file(Paths, Dir, Env, Options) -> % Priv = proplists:get_bool(private, Options), CSS = stylesheet(Options), Apps1 = [{filename:dirname(A),filename:basename(A)} || A <- Paths], - index_file(Dir, false, Title), + index_file(Dir, Title), application_frame(Dir, Apps1, Title, CSS), modules_frame(Dir, [], Title, CSS), overview(Dir, Title, Env, Options), diff --git a/lib/edoc/src/edoc_extract.erl b/lib/edoc/src/edoc_extract.erl index 67a95e80aa..a2a1a6b718 100644 --- a/lib/edoc/src/edoc_extract.erl +++ b/lib/edoc/src/edoc_extract.erl @@ -121,10 +121,8 @@ source1(Tree, File0, Env, Opts, TypeDocs) -> Module = get_module_info(Tree, File), {Header, Footer, Entries} = collect(Forms, Module), Name = Module#module.name, - Package = '', Env1 = Env#env{module = Name, - package = Package, - root = edoc_refs:relative_package_path('', Package)}, + root = ""}, Env2 = add_macro_defs(module_macros(Env1), Opts, Env1), Entries1 = get_tags([Header, Footer | Entries], Env2, File, TypeDocs), Entries2 = edoc_specs:add_data(Entries1, Opts, File, Module), @@ -218,7 +216,7 @@ add_macro_defs(Defs0, Opts, Env) -> %% @spec file(File::filename(), Context, Env::edoc_env(), %% Options::proplist()) -> {ok, Tags} | {error, Reason} -%% Context = overview | package +%% Context = overview %% Tags = [term()] %% Reason = term() %% @@ -249,7 +247,7 @@ file(File, Context, Env, Opts) -> %% @spec (Text::string(), Context, Env::edoc_env(), %% Options::proplist()) -> Tags -%% Context = overview | package +%% Context = overview %% Tags = [term()] %% %% @doc Returns the list of tags in the text. Any lines of text before diff --git a/lib/edoc/src/edoc_layout.erl b/lib/edoc/src/edoc_layout.erl index e164ff060f..6309e88475 100644 --- a/lib/edoc/src/edoc_layout.erl +++ b/lib/edoc/src/edoc_layout.erl @@ -27,7 +27,7 @@ -module(edoc_layout). --export([module/2, package/2, overview/2, type/1]). +-export([module/2, overview/2, type/1]). -import(edoc_report, [report/2]). @@ -701,6 +701,8 @@ deprecated(Es, S) -> end. behaviours(Es, Name) -> + CBs = get_content(callbacks, Es), + OCBs = get_content(optional_callbacks, Es), (case get_elem(behaviour, Es) of [] -> []; Es1 -> @@ -709,13 +711,24 @@ behaviours(Es, Name) -> ?NL] end ++ - case get_content(callbacks, Es) of - [] -> []; - Es1 -> + if CBs =:= [], OCBs =:= [] -> + []; + true -> + Req = if CBs =:= [] -> + []; + true -> + [br, " Required callback functions: "] + ++ seq(fun callback/1, CBs, ["."]) + end, + Opt = if OCBs =:= [] -> + []; + true -> + [br, " Optional callback functions: "] + ++ seq(fun callback/1, OCBs, ["."]) + end, [{p, ([{b, ["This module defines the ", {tt, [Name]}, - " behaviour."]}, - br, " Required callback functions: "] - ++ seq(fun callback/1, Es1, ["."]))}, + " behaviour."]}] + ++ Req ++ Opt)}, ?NL] end). @@ -831,8 +844,6 @@ t_type([#xmlElement{name = nonempty_list, content = Es}]) -> t_nonempty_list(Es); t_type([#xmlElement{name = map, content = Es}]) -> t_map(Es); -t_type([#xmlElement{name = map_field, content=Es}]) -> - t_map_field(Es); t_type([#xmlElement{name = tuple, content = Es}]) -> t_tuple(Es); t_type([#xmlElement{name = 'fun', content = Es}]) -> @@ -882,10 +893,11 @@ t_fun(Es) -> [") -> "] ++ t_utype(get_elem(type, Es))). t_map(Es) -> - ["#{"] ++ seq(fun t_utype_elem/1, Es, ["}"]). + Fs = get_elem(map_field, Es), + ["#{"] ++ seq(fun t_map_field/1, Fs, ["}"]). -t_map_field([K,V]) -> - [t_utype_elem(K) ++ " => " ++ t_utype_elem(V)]. +t_map_field(#xmlElement{content = [K,V]}) -> + t_utype_elem(K) ++ [" => "] ++ t_utype_elem(V). t_record(E, Es) -> Name = ["#"] ++ t_type(get_elem(atom, Es)), @@ -966,9 +978,6 @@ get_text(Name, Es) -> local_label(R) -> "#" ++ R. -xhtml(Title, CSS, Body) -> - xhtml(Title, CSS, Body, "latin1"). - xhtml(Title, CSS, Body, Encoding) -> EncString = case Encoding of "latin1" -> "ISO-8859-1"; @@ -998,27 +1007,6 @@ type(E, Ds) -> xmerl:export_simple_content(t_utype_elem(E) ++ local_defs(Ds, Opts), ?HTML_EXPORT). -package(E=#xmlElement{name = package, content = Es}, Options) -> - Opts = init_opts(E, Options), - Name = get_text(packageName, Es), - Title = ["Package ", Name], - Desc = get_content(description, Es), -% ShortDesc = get_content(briefDescription, Desc), - FullDesc = get_content(fullDescription, Desc), - Body = ([?NL, {h1, [Title]}, ?NL] -% ++ ShortDesc - ++ copyright(Es) - ++ deprecated(Es, "package") - ++ version(Es) - ++ since(Es) - ++ authors(Es) - ++ references(Es) - ++ sees(Es) - ++ todos(Es) - ++ FullDesc), - XML = xhtml(Title, stylesheet(Opts), Body), - xmerl:export_simple(XML, ?HTML_EXPORT, []). - overview(E=#xmlElement{name = overview, content = Es}, Options) -> Opts = init_opts(E, Options), Title = [get_text(title, Es)], @@ -1082,6 +1070,8 @@ ot_type([#xmlElement{name = nonempty_list, content = Es}]) -> ot_nonempty_list(Es); ot_type([#xmlElement{name = tuple, content = Es}]) -> ot_tuple(Es); +ot_type([#xmlElement{name = map, content = Es}]) -> + ot_map(Es); ot_type([#xmlElement{name = 'fun', content = Es}]) -> ot_fun(Es); ot_type([#xmlElement{name = record, content = Es}]) -> @@ -1138,6 +1128,12 @@ ot_nonempty_list(Es) -> ot_tuple(Es) -> {type,0,tuple,[ot_utype_elem(E) || E <- Es]}. +ot_map(Es) -> + {type,0,map,[ot_map_field(E) || E <- get_elem(map_field,Es)]}. + +ot_map_field(#xmlElement{content=[K,V]}) -> + {type,0,map_field_assoc,ot_utype_elem(K), ot_utype_elem(V)}. + ot_fun(Es) -> Range = ot_utype(get_elem(type, Es)), Args = [ot_utype_elem(A) || A <- get_content(argtypes, Es)], diff --git a/lib/edoc/src/edoc_lib.erl b/lib/edoc/src/edoc_lib.erl index c46338a2e1..813fcf2476 100644 --- a/lib/edoc/src/edoc_lib.erl +++ b/lib/edoc/src/edoc_lib.erl @@ -29,9 +29,9 @@ get_first_sentence/1, is_space/1, strip_space/1, parse_expr/2, parse_contact/2, escape_uri/1, join_uri/2, is_relative_uri/1, is_name/1, to_label/1, find_doc_dirs/0, find_sources/2, - find_sources/3, find_file/3, try_subdir/2, unique/1, - write_file/3, write_file/4, write_file/5, write_info_file/4, - read_info_file/1, get_doc_env/1, get_doc_env/4, copy_file/2, + find_file/2, try_subdir/2, unique/1, + write_file/3, write_file/4, write_info_file/3, + read_info_file/1, get_doc_env/1, get_doc_env/3, copy_file/2, uri_get/1, run_doclet/2, run_layout/2, simplify_path/1, timestr/1, datestr/1, read_encoding/2]). @@ -266,13 +266,6 @@ is_name_1([$_ | Cs]) -> is_name_1([]) -> true; is_name_1(_) -> false. -to_atom(A) when is_atom(A) -> A; -to_atom(S) when is_list(S) -> list_to_atom(S). - -to_list(A) when is_atom(A) -> atom_to_list(A); -to_list(S) when is_list(S) -> S. - - %% @private unique([X | Xs]) -> [X | unique(Xs, X)]; unique([]) -> []. @@ -674,7 +667,7 @@ simplify_path(P) -> try_subdir(Dir, Subdir) -> D = filename:join(Dir, Subdir), case filelib:is_dir(D) of - true -> D; + true -> D; false -> Dir end. @@ -686,19 +679,10 @@ try_subdir(Dir, Subdir) -> %% @private write_file(Text, Dir, Name) -> - write_file(Text, Dir, Name, ''). - -%% @spec (Text::deep_string(), Dir::edoc:filename(), -%% Name::edoc:filename(), Package::atom()|string()) -> ok -%% @doc Like {@link write_file/3}, but adds path components to the target -%% directory corresponding to the specified package. -%% @private + write_file(Text, Dir, Name, [{encoding,latin1}]). -write_file(Text, Dir, Name, Package) -> - write_file(Text, Dir, Name, Package, [{encoding,latin1}]). - -write_file(Text, Dir, Name, Package, Options) -> - File = filename:join([Dir, to_list(Package), Name]), +write_file(Text, Dir, Name, Options) -> + File = filename:join([Dir, Name]), ok = filelib:ensure_dir(File), case file:open(File, [write] ++ Options) of {ok, FD} -> @@ -711,15 +695,14 @@ write_file(Text, Dir, Name, Package, Options) -> end. %% @private -write_info_file(App, Packages, Modules, Dir) -> - Ts = [{packages, Packages}, - {modules, Modules}], +write_info_file(App, Modules, Dir) -> + Ts = [{modules, Modules}], Ts1 = if App =:= ?NO_APP -> Ts; true -> [{application, App} | Ts] end, S0 = [io_lib:fwrite("~p.\n", [T]) || T <- Ts1], S = ["%% encoding: UTF-8\n" | S0], - write_file(S, Dir, ?INFO_FILE, '', [{encoding,unicode}]). + write_file(S, Dir, ?INFO_FILE, [{encoding,unicode}]). %% @spec (Name::edoc:filename()) -> {ok, string()} | {error, Reason} %% @@ -744,9 +727,8 @@ read_file(File) -> info_file_data(Ts) -> App = proplists:get_value(application, Ts, ?NO_APP), - Ps = proplists:append_values(packages, Ts), Ms = proplists:append_values(modules, Ts), - {App, Ps, Ms}. + {App, Ms}. %% Local file access - don't complain if file does not exist. @@ -761,10 +743,10 @@ read_info_file(Dir) -> {error, R} -> R1 = file:format_error(R), warning("could not read '~ts': ~ts.", [File, R1]), - {?NO_APP, [], []} - end; + {?NO_APP, []} + end; false -> - {?NO_APP, [], []} + {?NO_APP, []} end. %% URI access @@ -776,7 +758,7 @@ uri_get_info_file(Base) -> parse_info_file(Text, URI); {error, Msg} -> warning("could not read '~ts': ~ts.", [URI, Msg]), - {?NO_APP, [], []} + {?NO_APP, []} end. parse_info_file(Text, Name) -> @@ -785,10 +767,10 @@ parse_info_file(Text, Name) -> info_file_data(Vs); {error, eof} -> warning("unexpected end of file in '~ts'.", [Name]), - {?NO_APP, [], []}; + {?NO_APP, []}; {error, {_Line,Module,R}} -> warning("~ts: ~ts.", [Module:format_error(R), Name]), - {?NO_APP, [], []} + {?NO_APP, []} end. parse_terms(Text) -> @@ -815,82 +797,67 @@ parse_terms_1([], _As, _Vs) -> %% --------------------------------------------------------------------- -%% Source files and packages - -%% @private -find_sources(Path, Opts) -> - find_sources(Path, "", Opts). +%% Source files -%% @doc See {@link edoc:run/3} for a description of the options -%% `subpackages', `source_suffix' and `exclude_packages'. +%% @doc See {@link edoc:run/2} for a description of the options +%% `subpackages', `source_suffix'. %% @private -%% NEW-OPTIONS: subpackages, source_suffix, exclude_packages -%% DEFER-OPTIONS: edoc:run/3 +%% NEW-OPTIONS: subpackages, source_suffix +%% DEFER-OPTIONS: edoc:run/2 -find_sources(Path, Pkg, Opts) -> +find_sources(Path, Opts) -> Rec = proplists:get_bool(subpackages, Opts), Ext = proplists:get_value(source_suffix, Opts, ?DEFAULT_SOURCE_SUFFIX), - find_sources(Path, Pkg, Rec, Ext, Opts). + find_sources(Path, Rec, Ext, Opts). -find_sources(Path, Pkg, Rec, Ext, Opts) -> - Skip = proplists:get_value(exclude_packages, Opts, []), - lists:flatten(find_sources_1(Path, to_atom(Pkg), Rec, Ext, Skip)). +find_sources(Path, Rec, Ext, _Opts) -> + lists:flatten(find_sources_1(Path, Rec, Ext)). -find_sources_1([P | Ps], Pkg, Rec, Ext, Skip) -> - Dir = filename:join(P, atom_to_list(Pkg)), - Fs1 = find_sources_1(Ps, Pkg, Rec, Ext, Skip), +find_sources_1([P | Ps], Rec, Ext) -> + Dir = P, + Fs1 = find_sources_1(Ps, Rec, Ext), case filelib:is_dir(Dir) of true -> - [find_sources_2(Dir, Pkg, Rec, Ext, Skip) | Fs1]; + [find_sources_2(Dir, Rec, Ext) | Fs1]; false -> Fs1 end; -find_sources_1([], _Pkg, _Rec, _Ext, _Skip) -> +find_sources_1([], _Rec, _Ext) -> []. -find_sources_2(Dir, Pkg, Rec, Ext, Skip) -> - case lists:member(Pkg, Skip) of - false -> - Es = list_dir(Dir, false), % just warn if listing fails - Es1 = [{Pkg, E, Dir} || E <- Es, is_source_file(E, Ext)], - case Rec of +find_sources_2(Dir, Rec, Ext) -> + Es = list_dir(Dir, false), % just warn if listing fails + Es1 = [{E, Dir} || E <- Es, is_source_file(E, Ext)], + case Rec of true -> - [find_sources_3(Es, Dir, Pkg, Rec, Ext, Skip) | Es1]; + [find_sources_3(Es, Dir, Rec, Ext) | Es1]; false -> - Es1 - end; - true -> - [] - end. + Es1 + end. -find_sources_3(Es, Dir, Pkg, Rec, Ext, Skip) -> +find_sources_3(Es, Dir, Rec, Ext) -> [find_sources_2(filename:join(Dir, E), - to_atom(join(Pkg, E)), Rec, Ext, Skip) - || E <- Es, is_package_dir(E, Dir)]. - -join('', E) -> E; -join(Pkg, E) -> filename:join(Pkg, E). + Rec, Ext) + || E <- Es, is_source_dir(E, Dir)]. is_source_file(Name, Ext) -> (filename:extension(Name) == Ext) andalso is_name(filename:rootname(Name, Ext)). -is_package_dir(Name, Dir) -> - is_name(filename:rootname(filename:basename(Name))) - andalso filelib:is_dir(filename:join(Dir, Name)). +is_source_dir(Name, Dir) -> + filelib:is_dir(filename:join(Dir, Name)). %% @private -find_file([P | Ps], []=Pkg, Name) -> - Pkg = [], +find_file([P | Ps], Name) -> File = filename:join(P, Name), case filelib:is_file(File) of true -> - File; + File; false -> - find_file(Ps, Pkg, Name) - end; -find_file([], [], _Name) -> + find_file(Ps, Name) + end; +find_file([], _Name) -> "". %% @private @@ -909,7 +876,7 @@ find_doc_dirs([P0 | Ps]) -> File = filename:join(Dir, ?INFO_FILE), case filelib:is_file(File) of true -> - [Dir | find_doc_dirs(Ps)]; + [Dir | find_doc_dirs(Ps)]; false -> find_doc_dirs(Ps) end; @@ -923,22 +890,21 @@ find_doc_dirs([]) -> %% NEW-OPTIONS: doc_path %% DEFER-OPTIONS: get_doc_env/4 -get_doc_links(App, Packages, Modules, Opts) -> +get_doc_links(App, Modules, Opts) -> Path = proplists:append_values(doc_path, Opts) ++ find_doc_dirs(), Ds = [{P, uri_get_info_file(P)} || P <- Path], - Ds1 = [{"", {App, Packages, Modules}} | Ds], + Ds1 = [{"", {App, Modules}} | Ds], D = dict:new(), - make_links(Ds1, D, D, D). + make_links(Ds1, D, D). -make_links([{Dir, {App, Ps, Ms}} | Ds], A, P, M) -> +make_links([{Dir, {App, Ms}} | Ds], A, M) -> A1 = if App == ?NO_APP -> A; true -> add_new(App, Dir, A) end, F = fun (K, D) -> add_new(K, Dir, D) end, - P1 = lists:foldl(F, P, Ps), M1 = lists:foldl(F, M, Ms), - make_links(Ds, A1, P1, M1); -make_links([], A, P, M) -> + make_links(Ds, A1, M1); +make_links([], A, M) -> F = fun (D) -> fun (K) -> case dict:find(K, D) of @@ -947,7 +913,7 @@ make_links([], A, P, M) -> end end end, - {F(A), F(P), F(M)}. + {F(A), F(M)}. add_new(K, V, D) -> case dict:is_key(K, D) of @@ -962,11 +928,10 @@ add_new(K, V, D) -> %% @private get_doc_env(Opts) -> - get_doc_env([], [], [], Opts). + get_doc_env([], [], Opts). -%% @spec (App, Packages, Modules, Options::proplist()) -> edoc_env() +%% @spec (App, Modules, Options::proplist()) -> edoc_env() %% App = [] | atom() -%% Packages = [atom()] %% Modules = [atom()] %% proplist() = [term()] %% @@ -985,17 +950,15 @@ get_doc_env(Opts) -> %% INHERIT-OPTIONS: get_doc_links/4 %% DEFER-OPTIONS: edoc:run/3 -get_doc_env(App, Packages, Modules, Opts) -> +get_doc_env(App, Modules, Opts) -> Suffix = proplists:get_value(file_suffix, Opts, ?DEFAULT_FILE_SUFFIX), AppDefault = proplists:get_value(app_default, Opts, ?APP_DEFAULT), Includes = proplists:append_values(includes, Opts), - {A, P, M} = get_doc_links(App, Packages, Modules, Opts), + {A, M} = get_doc_links(App, Modules, Opts), #env{file_suffix = Suffix, - package_summary = ?PACKAGE_SUMMARY ++ Suffix, apps = A, - packages = P, modules = M, app_default = AppDefault, includes = Includes diff --git a/lib/edoc/src/edoc_macros.erl b/lib/edoc/src/edoc_macros.erl index 8efbfd00c7..bdcb3fe81f 100644 --- a/lib/edoc/src/edoc_macros.erl +++ b/lib/edoc/src/edoc_macros.erl @@ -40,10 +40,6 @@ std_macros(Env) -> true -> [{module, atom_to_list(Env#env.module)}] end ++ - if Env#env.package =:= [] -> []; - true -> [{package, atom_to_list(Env#env.package)}] - end - ++ [{date, fun date_macro/3}, {docRoot, Env#env.root}, {link, fun link_macro/3}, diff --git a/lib/edoc/src/edoc_parser.yrl b/lib/edoc/src/edoc_parser.yrl index c6f8a04775..48c01c8dce 100644 --- a/lib/edoc/src/edoc_parser.yrl +++ b/lib/edoc/src/edoc_parser.yrl @@ -28,7 +28,7 @@ Nonterminals start spec func_type utype_list utype_tuple utypes utype ptypes ptype nutype function_name where_defs defs defs2 def typedef etype -throws qname ref aref mref lref pref var_list vars fields field +throws qname ref aref mref lref var_list vars fields field utype_map utype_map_fields utype_map_field futype_list bin_base_type bin_unit_type. @@ -207,14 +207,11 @@ typedef -> atom var_list '=' utype where_defs: ref -> aref: '$1'. ref -> mref: '$1'. ref -> lref: '$1'. -ref -> pref: '$1'. aref -> '//' atom: edoc_refs:app(tok_val('$2')). aref -> '//' atom '/' mref: edoc_refs:app(tok_val('$2'), '$4'). -aref -> '//' atom '/' pref: - edoc_refs:app(tok_val('$2'), '$4'). mref -> qname ':' atom '/' integer: edoc_refs:function(qname('$1'), tok_val('$3'), tok_val('$5')). @@ -223,9 +220,6 @@ mref -> qname ':' atom '(' ')': mref -> qname: edoc_refs:module(qname('$1')). -pref -> qname '.' '*': - edoc_refs:package(qname('$1')). - lref -> atom '/' integer: edoc_refs:function(tok_val('$1'), tok_val('$3')). lref -> atom '(' ')': @@ -399,7 +393,7 @@ parse_typedef_1(S, L) -> %% @doc Parses a <a %% href="overview-summary.html#References">reference</a> to a module, -%% package, function, type, or application +%% function, type, or application parse_ref(S, L) -> case edoc_scanner:string(S, L) of diff --git a/lib/edoc/src/edoc_refs.erl b/lib/edoc/src/edoc_refs.erl index ea439490ed..b9a9391053 100644 --- a/lib/edoc/src/edoc_refs.erl +++ b/lib/edoc/src/edoc_refs.erl @@ -27,10 +27,9 @@ -module(edoc_refs). --export([app/1, app/2, package/1, module/1, module/2, module/3, +-export([app/1, app/2, module/1, module/2, module/3, function/2, function/3, function/4, type/1, type/2, type/3, - to_string/1, to_label/1, get_uri/2, is_top/2, - relative_module_path/2, relative_package_path/2]). + to_string/1, to_label/1, get_uri/2, is_top/2]). -import(edoc_lib, [join_uri/2, escape_uri/1]). @@ -56,9 +55,6 @@ module(M, Ref) -> module(App, M, Ref) -> app(App, module(M, Ref)). -package(P) -> - {package, P}. - function(F, A) -> {function, F, A}. @@ -88,8 +84,6 @@ to_string({module, M}) -> atom_to_list(M) ; to_string({module, M, Ref}) -> atom_to_list(M) ++ ":" ++ to_string(Ref); -to_string({package, P}) -> - atom_to_list(P) ++ ".*"; to_string({function, F, A}) -> atom_to_list(F) ++ "/" ++ integer_to_list(A); to_string({type, T}) -> @@ -111,24 +105,19 @@ get_uri({module, M, Ref}, Env) -> module_ref(M, Env) ++ "#" ++ to_label(Ref); get_uri({module, M}, Env) -> module_ref(M, Env); -get_uri({package, P}, Env) -> - package_ref(P, Env); get_uri(Ref, _Env) -> "#" ++ to_label(Ref). abs_uri({module, M}, Env) -> module_absref(M, Env); abs_uri({module, M, Ref}, Env) -> - module_absref(M, Env) ++ "#" ++ to_label(Ref); -abs_uri({package, P}, Env) -> - package_absref(P, Env). + module_absref(M, Env) ++ "#" ++ to_label(Ref). module_ref(M, Env) -> case (Env#env.modules)(M) of "" -> File = atom_to_list(M) ++ Env#env.file_suffix, - Path = relative_module_path(M, Env#env.package), - join_uri(Path, escape_uri(File)); + escape_uri(File); Base -> join_uri(Base, module_absref(M, Env)) end. @@ -136,19 +125,6 @@ module_ref(M, Env) -> module_absref(M, Env) -> escape_uri(atom_to_list(M)) ++ escape_uri(Env#env.file_suffix). -package_ref(P, Env) -> - case (Env#env.packages)(P) of - "" -> - join_uri(relative_package_path(P, Env#env.package), - escape_uri(Env#env.package_summary)); - Base -> - join_uri(Base, package_absref(P, Env)) - end. - -package_absref(P, Env) -> - join_uri(escape_uri(atom_to_list(P)), - escape_uri(Env#env.package_summary)). - app_ref(A, Env) -> case (Env#env.apps)(A) of "" -> @@ -166,43 +142,3 @@ is_top({app, _App}, _Env) -> is_top(_Ref, _Env) -> false. -%% Each segment of a path must be separately escaped before joining. - -join_segments([S]) -> - escape_uri(S); -join_segments([S | Ss]) -> - join_uri(escape_uri(S), join_segments(Ss)). - -%% 'From' is always the "current package" here: - -%% The empty string is returned if the To module has only one segment, -%% implying a local reference. - -relative_module_path(_To, _From) -> - "". - -relative_package_path(To, From) -> - relative_path([atom_to_list(To)], [atom_to_list(From)]). - -%% This takes two lists of path segments (From, To). Note that an empty -%% string will be returned if the paths are the same. Empty leading -%% segments are stripped from both paths. - -relative_path(Ts, ["" | Fs]) -> - relative_path(Ts, Fs); -relative_path(["" | Ts], Fs) -> - relative_path(Ts, Fs); -relative_path(Ts, Fs) -> - relative_path_1(Ts, Fs). - -relative_path_1([T | Ts], [F | Fs]) when F == T -> - relative_path_1(Ts, Fs); -relative_path_1(Ts, Fs) -> - relative_path_2(Fs, Ts). - -relative_path_2([_F | Fs], Ts) -> - relative_path_2(Fs, [".." | Ts]); -relative_path_2([], []) -> - ""; -relative_path_2([], Ts) -> - join_segments(Ts). diff --git a/lib/edoc/src/edoc_run.erl b/lib/edoc/src/edoc_run.erl index b5a1ef713d..9a569d0879 100644 --- a/lib/edoc/src/edoc_run.erl +++ b/lib/edoc/src/edoc_run.erl @@ -17,7 +17,7 @@ %% @copyright 2003 Richard Carlsson %% @author Richard Carlsson <[email protected]> %% @see edoc -%% @end +%% @end %% ===================================================================== %% @doc Interface for calling EDoc from Erlang startup options. @@ -38,7 +38,7 @@ -module(edoc_run). --export([file/1, application/1, packages/1, files/1, toc/1]). +-export([file/1, application/1, files/1, toc/1]). -compile({no_auto_import,[error/1]}). @@ -92,28 +92,6 @@ files(Args) -> end, run(F). -%% @spec packages([string()]) -> none() -%% -%% @doc Calls {@link edoc:application/2} with the corresponding -%% arguments. The strings in the list are parsed as Erlang constant -%% terms. The list can be either `[Packages]' or `[Packages, Options]'. -%% In the first case {@link edoc:application/1} is called instead. -%% -%% The function call never returns; instead, the emulator is -%% automatically terminated when the call has completed, signalling -%% success or failure to the operating system. - -packages(Args) -> - F = fun () -> - case parse_args(Args) of - [Packages] -> edoc:packages(Packages); - [Packages, Opts] -> edoc:packages(Packages, Opts); - _ -> - invalid_args("edoc_run:packages/1", Args) - end - end, - run(F). - %% @hidden Not official yet toc(Args) -> F = fun () -> @@ -131,8 +109,8 @@ toc(Args) -> %% %% @deprecated This is part of the old interface to EDoc and is mainly %% kept for backwards compatibility. The preferred way of generating -%% documentation is through one of the functions {@link application/1}, -%% {@link packages/1} and {@link files/1}. +%% documentation is through one of the functions {@link application/1} +%% and {@link files/1}. %% %% @doc Calls {@link edoc:file/2} with the corresponding arguments. The %% strings in the list are parsed as Erlang constant terms. The list can diff --git a/lib/edoc/src/edoc_specs.erl b/lib/edoc/src/edoc_specs.erl index 211a354c74..3bf81c6503 100644 --- a/lib/edoc/src/edoc_specs.erl +++ b/lib/edoc/src/edoc_specs.erl @@ -362,7 +362,7 @@ d2e({type,_,map,any}) -> #t_map{ types = []}; d2e({type,_,map,Es}) -> #t_map{ types = d2e(Es) }; -d2e({type,_,map_field_assoc,K,V}) -> +d2e({type,_,map_field_assoc,[K,V]}) -> #t_map_field{ k_type = d2e(K), v_type=d2e(V) }; d2e({type,_,map_field_exact,K,V}) -> #t_map_field{ k_type = d2e(K), v_type=d2e(V) }; @@ -388,6 +388,9 @@ d2e({record_field,L,_Name}=F) -> d2e({type,_,Name,Types0}) -> Types = d2e(Types0), typevar_anno(#t_type{name = #t_name{name = Name}, args = Types}, Types); +d2e({user_type,_,Name,Types0}) -> + Types = d2e(Types0), + typevar_anno(#t_type{name = #t_name{name = Name}, args = Types}, Types); d2e({var,_,'_'}) -> #t_type{name = #t_name{name = ?TOP_TYPE}}; d2e({var,_,TypeName}) -> diff --git a/lib/edoc/src/edoc_tags.erl b/lib/edoc/src/edoc_tags.erl index 264a533a52..c1c453511a 100644 --- a/lib/edoc/src/edoc_tags.erl +++ b/lib/edoc/src/edoc_tags.erl @@ -42,7 +42,7 @@ %% Name = atom() %% Parser = text | xml | (Text,Line,Where) -> term() %% Flags = [Flag] -%% Flag = module | function | package | overview | single +%% Flag = module | function | overview | single %% %% Note that the pseudo-tag '@clear' is not listed here. %% (Cf. the function 'filter_tags'.) @@ -57,11 +57,11 @@ %% - @category (useless; superseded by keywords or free text search) tags() -> - All = [module,footer,function,package,overview], - [{author, fun parse_contact/4, [module,package,overview]}, - {copyright, text, [module,package,overview,single]}, - {deprecated, xml, [module,function,package,single]}, - {doc, xml, [module,function,package,overview,single]}, + All = [module,footer,function,overview], + [{author, fun parse_contact/4, [module,overview]}, + {copyright, text, [module,overview,single]}, + {deprecated, xml, [module,function,single]}, + {doc, xml, [module,function,overview,single]}, {docfile, fun parse_file/4, All}, {'end', text, All}, {equiv, fun parse_expr/4, [function,single]}, @@ -69,17 +69,17 @@ tags() -> {hidden, text, [module,function,single]}, {param, fun parse_param/4, [function]}, {private, text, [module,function,single]}, - {reference, xml, [module,footer,package,overview]}, + {reference, xml, [module,footer,overview]}, {returns, xml, [function,single]}, - {see, fun parse_see/4, [module,function,package,overview]}, - {since, text, [module,function,package,overview,single]}, + {see, fun parse_see/4, [module,function,overview]}, + {since, text, [module,function,overview,single]}, {spec, fun parse_spec/4, [function,single]}, {throws, fun parse_throws/4, [function,single]}, {title, text, [overview,single]}, {'TODO', xml, All}, {todo, xml, All}, {type, fun parse_typedef/4, [module,footer,function]}, - {version, text, [module,package,overview,single]}]. + {version, text, [module,overview,single]}]. aliases('TODO') -> todo; aliases(return) -> returns; @@ -329,10 +329,7 @@ parse_typedef(Data, Line, _Env, Where) -> NAs = length(As), case edoc_types:is_predefined(T, NAs) of true -> - case - edoc_types:is_new_predefined(T, NAs) - orelse edoc_types:is_predefined_otp_type(T, NAs) - of + case edoc_types:is_new_predefined(T, NAs) of false -> throw_error(Line, {"redefining built-in type '~w'.", [T]}); @@ -372,7 +369,7 @@ parse_header(Data, Line, Env, Where) when is_list(Where) -> {string, _, File} -> Dir = filename:dirname(Where), Path = Env#env.includes ++ [Dir], - case edoc_lib:find_file(Path, "", File) of + case edoc_lib:find_file(Path, File) of "" -> throw_error(Line, {file_not_found, File}); File1 -> @@ -499,7 +496,6 @@ check_used_type(#t_name{name = N, module = Mod}=Name, Args, P, LocalTypes) -> Mod =/= [] orelse lists:member(TypeName, ets:lookup(DT, Name)) orelse edoc_types:is_predefined(N, NArgs) - orelse edoc_types:is_predefined_otp_type(N, NArgs) orelse lists:member(TypeName, LocalTypes) of true -> diff --git a/lib/edoc/src/edoc_types.erl b/lib/edoc/src/edoc_types.erl index d4e00d3ecd..65fba61a72 100644 --- a/lib/edoc/src/edoc_types.erl +++ b/lib/edoc/src/edoc_types.erl @@ -25,7 +25,7 @@ -module(edoc_types). --export([is_predefined/2, is_new_predefined/2, is_predefined_otp_type/2, +-export([is_predefined/2, is_new_predefined/2, to_ref/1, to_xml/2, to_label/1, arg_names/1, set_arg_names/2, arg_descs/1, range_desc/1]). @@ -34,67 +34,13 @@ -include("edoc_types.hrl"). -include_lib("xmerl/include/xmerl.hrl"). - -is_predefined(any, 0) -> true; -is_predefined(atom, 0) -> true; -is_predefined(binary, 0) -> true; -is_predefined(bool, 0) -> true; % kept for backwards compatibility -is_predefined(char, 0) -> true; is_predefined(cons, 2) -> true; is_predefined(deep_string, 0) -> true; -is_predefined(float, 0) -> true; -is_predefined(function, 0) -> true; -is_predefined(integer, 0) -> true; -is_predefined(list, 0) -> true; -is_predefined(list, 1) -> true; -is_predefined(nil, 0) -> true; -is_predefined(none, 0) -> true; -is_predefined(no_return, 0) -> true; -is_predefined(number, 0) -> true; -is_predefined(pid, 0) -> true; -is_predefined(port, 0) -> true; -is_predefined(reference, 0) -> true; -is_predefined(string, 0) -> true; -is_predefined(term, 0) -> true; -is_predefined(tuple, 0) -> true; -is_predefined(F, A) -> is_new_predefined(F, A). +is_predefined(F, A) -> erl_internal:is_type(F, A). -%% Should eventually be coalesced with is_predefined/2. -is_new_predefined(arity, 0) -> true; -is_new_predefined(bitstring, 0) -> true; -is_new_predefined(boolean, 0) -> true; -is_new_predefined(byte, 0) -> true; -is_new_predefined(iodata, 0) -> true; -is_new_predefined(iolist, 0) -> true; is_new_predefined(map, 0) -> true; -is_new_predefined(maybe_improper_list, 0) -> true; -is_new_predefined(maybe_improper_list, 2) -> true; -is_new_predefined(mfa, 0) -> true; -is_new_predefined(module, 0) -> true; -is_new_predefined(neg_integer, 0) -> true; -is_new_predefined(node, 0) -> true; -is_new_predefined(non_neg_integer, 0) -> true; -is_new_predefined(nonempty_improper_list, 2) -> true; -is_new_predefined(nonempty_list, 0) -> true; -is_new_predefined(nonempty_list, 1) -> true; -is_new_predefined(nonempty_maybe_improper_list, 0) -> true; -is_new_predefined(nonempty_maybe_improper_list, 2) -> true; -is_new_predefined(nonempty_string, 0) -> true; -is_new_predefined(pos_integer, 0) -> true; -is_new_predefined(timeout, 0) -> true; is_new_predefined(_, _) -> false. -%% The following types will be removed later, but they are currently -%% kind of built-in. -is_predefined_otp_type(array, 0) -> true; -is_predefined_otp_type(dict, 0) -> true; -is_predefined_otp_type(digraph, 0) -> true; -is_predefined_otp_type(gb_set, 0) -> true; -is_predefined_otp_type(gb_tree, 0) -> true; -is_predefined_otp_type(queue, 0) -> true; -is_predefined_otp_type(set, 0) -> true; -is_predefined_otp_type(_, _) -> false. - to_ref(#t_typedef{name = N}) -> to_ref(N); to_ref(#t_def{name = N}) -> @@ -129,8 +75,7 @@ to_xml(#t_type{name = N, args = As}, Env) -> Predef = case N of #t_name{module = [], name = T} -> NArgs = length(As), - (is_predefined(T, NArgs) - orelse is_predefined_otp_type(T, NArgs)); + is_predefined(T, NArgs); _ -> false end, @@ -143,7 +88,7 @@ to_xml(#t_fun{args = As, range = T}, Env) -> {'fun', [{argtypes, map(fun wrap_utype/2, As, Env)}, wrap_utype(T, Env)]}; to_xml(#t_map{ types = Ts}, Env) -> - {map, map(fun wrap_utype/2, Ts, Env)}; + {map, map(fun to_xml/2, Ts, Env)}; to_xml(#t_map_field{ k_type=K, v_type=V}, Env) -> {map_field, [wrap_utype(K,Env), wrap_utype(V, Env)]}; to_xml(#t_tuple{types = Ts}, Env) -> diff --git a/lib/edoc/src/otpsgml_layout.erl b/lib/edoc/src/otpsgml_layout.erl index 2c4cd919bb..052c75b9d4 100644 --- a/lib/edoc/src/otpsgml_layout.erl +++ b/lib/edoc/src/otpsgml_layout.erl @@ -28,7 +28,7 @@ -module(otpsgml_layout). --export([module/2, package/2, overview/2,type/1]). +-export([module/2, overview/2,type/1]). -import(edoc_report, [report/2]). @@ -811,27 +811,6 @@ xml(Title, CSS, Body) -> xmerl:export_simple_content(t_utype_elem(E) ++ local_defs(Ds), ?SGML_EXPORT). - -package(E=#xmlElement{name = package, content = Es}, Options) -> - Opts = init_opts(E, Options), - Name = get_text(packageName, Es), - Title = io_lib:fwrite("Package ~s", [Name]), - Desc = get_content(description, Es), -% ShortDesc = get_content(briefDescription, Desc), - FullDesc = get_content(fullDescription, Desc), - Body = ([?NL, {h1, [Title]}, ?NL] -% ++ ShortDesc - ++ copyright(Es) - ++ deprecated(Es, "package") - ++ version(Es) - ++ since(Es) - ++ authors(Es) - ++ references(Es) - ++ sees(Es) - ++ FullDesc), - XML = xml(Title, stylesheet(Opts), Body), - xmerl:export_simple([XML], ?SGML_EXPORT, []). - overview(E=#xmlElement{name = overview, content = Es}, Options) -> Opts = init_opts(E, Options), Title = get_text(title, Es), @@ -843,6 +822,7 @@ overview(E=#xmlElement{name = overview, content = Es}, Options) -> ++ copyright(Es) ++ version(Es) ++ since(Es) + ++ deprecated(Es, "application") ++ authors(Es) ++ references(Es) ++ sees(Es) diff --git a/lib/edoc/test/edoc_SUITE.erl b/lib/edoc/test/edoc_SUITE.erl index c9c7811afb..6b23054ce3 100644 --- a/lib/edoc/test/edoc_SUITE.erl +++ b/lib/edoc/test/edoc_SUITE.erl @@ -22,12 +22,12 @@ init_per_group/2,end_per_group/2]). %% Test cases --export([app/1,appup/1,build_std/1,build_map_module/1]). +-export([app/1,appup/1,build_std/1,build_map_module/1,otp_12008/1, build_app/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [app,appup,build_std,build_map_module]. + [app,appup,build_std,build_map_module,otp_12008, build_app]. groups() -> []. @@ -77,3 +77,38 @@ build_map_module(Config) when is_list(Config) -> Filename = filename:join(DataDir, "map_module.erl"), ok = edoc:file(Filename, [{dir, PrivDir}]), ok. + +otp_12008(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + Un1 = filename:join(DataDir, "un1.erl"), + Un2 = filename:join(DataDir, "un2.erl"), + Un3 = filename:join(DataDir, "un3.erl"), + %% epp_dodger + Opts1 = [{dir, PrivDir}], + ok = edoc:files([Un1], Opts1), + ok = edoc:files([Un2], Opts1), + {'EXIT', error} = (catch edoc:files([Un3], Opts1)), + %% epp + Opts2 = [{preprocess, true}, {dir, PrivDir}], + ok = edoc:files([Un1], Opts2), + ok = edoc:files([Un2], Opts2), + {'EXIT', error} = (catch edoc:files([Un3], Opts2)), + ok. + +build_app(suite) -> []; +build_app(doc) -> ["Build a local app with nested source directories"]; +build_app(Config) -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + OutDir = filename:join(PrivDir, "myapp"), + Src = filename:join(DataDir, "myapp"), + + ok = edoc:application(myapp, Src, [{dir, OutDir}, {subpackages, false}]), + true = filelib:is_regular(filename:join(OutDir, "a.html")), + false = filelib:is_regular(filename:join(OutDir, "b.html")), + + ok = edoc:application(myapp, Src, [{dir, OutDir}]), + true = filelib:is_regular(filename:join(OutDir, "a.html")), + true = filelib:is_regular(filename:join(OutDir, "b.html")), + ok. diff --git a/lib/edoc/test/edoc_SUITE_data/map_module.erl b/lib/edoc/test/edoc_SUITE_data/map_module.erl index 94ee7e6f26..f242721637 100644 --- a/lib/edoc/test/edoc_SUITE_data/map_module.erl +++ b/lib/edoc/test/edoc_SUITE_data/map_module.erl @@ -1,6 +1,6 @@ -module(map_module). --export([foo1/1,foo2/3]). +-export([foo1/1,foo2/3,start_child/2]). %% @type wazzup() = integer() %% @type some_type() = map() @@ -25,3 +25,43 @@ foo1(#{ a:= 1, b := V}) -> V. Map :: #{ get => 'value', 'value' => binary()}) -> binary(). foo2(Type1, {a,#{ "a" := _}}, #{get := value, value := B}) when is_map(Type1) -> B. + +%% from supervisor 18.0 + +-type child() :: 'undefined' | pid(). +-type child_id() :: term(). +-type mfargs() :: {M :: module(), F :: atom(), A :: [term()] | undefined}. +-type modules() :: [module()] | 'dynamic'. +-type restart() :: 'permanent' | 'transient' | 'temporary'. +-type shutdown() :: 'brutal_kill' | timeout(). +-type worker() :: 'worker' | 'supervisor'. +-type sup_ref() :: (Name :: atom()) + | {Name :: atom(), Node :: node()} + | {'global', Name :: atom()} + | {'via', Module :: module(), Name :: any()} + | pid(). +-type child_spec() :: #{name => child_id(), % mandatory + start => mfargs(), % mandatory + restart => restart(), % optional + shutdown => shutdown(), % optional + type => worker(), % optional + modules => modules()} % optional + | {Id :: child_id(), + StartFunc :: mfargs(), + Restart :: restart(), + Shutdown :: shutdown(), + Type :: worker(), + Modules :: modules()}. + +-type startchild_err() :: 'already_present' + | {'already_started', Child :: child()} | term(). +-type startchild_ret() :: {'ok', Child :: child()} + | {'ok', Child :: child(), Info :: term()} + | {'error', startchild_err()}. + + +-spec start_child(SupRef, ChildSpec) -> startchild_ret() when + SupRef :: sup_ref(), + ChildSpec :: child_spec() | (List :: [term()]). +start_child(Supervisor, ChildSpec) -> + {Supervisor,ChildSpec}. diff --git a/lib/edoc/test/edoc_SUITE_data/myapp/doc/.dummy b/lib/edoc/test/edoc_SUITE_data/myapp/doc/.dummy new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/lib/edoc/test/edoc_SUITE_data/myapp/doc/.dummy diff --git a/lib/edoc/test/edoc_SUITE_data/myapp/src/a.erl b/lib/edoc/test/edoc_SUITE_data/myapp/src/a.erl new file mode 100644 index 0000000000..1b5b704551 --- /dev/null +++ b/lib/edoc/test/edoc_SUITE_data/myapp/src/a.erl @@ -0,0 +1 @@ +-module(a). diff --git a/lib/edoc/test/edoc_SUITE_data/myapp/src/src_1/b.erl b/lib/edoc/test/edoc_SUITE_data/myapp/src/src_1/b.erl new file mode 100644 index 0000000000..6d6f15dfe5 --- /dev/null +++ b/lib/edoc/test/edoc_SUITE_data/myapp/src/src_1/b.erl @@ -0,0 +1 @@ +-module(b). diff --git a/lib/edoc/test/edoc_SUITE_data/un1.erl b/lib/edoc/test/edoc_SUITE_data/un1.erl new file mode 100644 index 0000000000..0c48e7f940 --- /dev/null +++ b/lib/edoc/test/edoc_SUITE_data/un1.erl @@ -0,0 +1,7 @@ +-module(un1). + +-export([t/0]). + +%% @doc F�pp +t() -> + �rlig. diff --git a/lib/edoc/test/edoc_SUITE_data/un2.erl b/lib/edoc/test/edoc_SUITE_data/un2.erl new file mode 100644 index 0000000000..a6d13f4723 --- /dev/null +++ b/lib/edoc/test/edoc_SUITE_data/un2.erl @@ -0,0 +1,8 @@ +-module(un2). +%% coding: latin-1 + +-export([t/0]). + +%% @doc F�pp +t() -> + �rlig. diff --git a/lib/edoc/test/edoc_SUITE_data/un3.erl b/lib/edoc/test/edoc_SUITE_data/un3.erl new file mode 100644 index 0000000000..fbe9591dce --- /dev/null +++ b/lib/edoc/test/edoc_SUITE_data/un3.erl @@ -0,0 +1,8 @@ +-module(un3). +%% coding: utf-8 + +-export([t/0]). + +%% @doc F�pp +t() -> + �rlig. diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk index 0172aac48b..24cfbf16d5 100644 --- a/lib/edoc/vsn.mk +++ b/lib/edoc/vsn.mk @@ -1 +1 @@ -EDOC_VSN = 0.7.13 +EDOC_VSN = 0.7.16 |