1%% =====================================================================
2%% Licensed under the Apache License, Version 2.0 (the "License"); you may
3%% not use this file except in compliance with the License. You may obtain
4%% a copy of the License at <http://www.apache.org/licenses/LICENSE-2.0>
5%%
6%% Unless required by applicable law or agreed to in writing, software
7%% distributed under the License is distributed on an "AS IS" BASIS,
8%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9%% See the License for the specific language governing permissions and
10%% limitations under the License.
11%%
12%% Alternatively, you may use this file under the terms of the GNU Lesser
13%% General Public License (the "LGPL") as published by the Free Software
14%% Foundation; either version 2.1, or (at your option) any later version.
15%% If you wish to allow use of your version of this file only under the
16%% terms of the LGPL, you should delete the provisions above and replace
17%% them with the notice and other provisions required by the LGPL; see
18%% <http://www.gnu.org/licenses/>. If you do not delete the provisions
19%% above, a recipient may use your version of this file under the terms of
20%% either the Apache License or the LGPL.
21%%
22%% @copyright 2001-2007 Richard Carlsson
23%% @author Richard Carlsson <carlsson.richard@gmail.com>
24%% @version {@version}
25%% @end
26%% =====================================================================
27
28%% TODO: check weirdness in name generation for @spec f(TypeName, ...) -> ...
29%% TODO: option for ignoring functions matching some pattern ('..._test_'/0)
30%% TODO: @private_type tag, opaque unless generating private docs?
31%% TODO: document the record type syntax
32%% TODO: some 'skip' option for ignoring particular modules?
33%% TODO: multiline comment support (needs modified comment representation)
34%% TODO: config-file for default settings
35%% TODO: config: locations of all local docdirs; generate local doc-index page
36%% TODO: config: URL:s of offline apps
37%% TODO: config: default stylesheet
38%% TODO: config: default header/footer, etc.
39%% TODO: offline linkage
40%% TODO: including source code, explicitly and/or automatically
41
42%% @doc EDoc - the Erlang program documentation generator.
43%%
44%% This module provides the main user interface to EDoc.
45%% <ul>
46%%   <li><a href="overview-summary.html">EDoc User Manual</a></li>
47%%   <li><a href="overview-summary.html#Running_EDoc">Running EDoc</a></li>
48%% </ul>
49
50-module(edoc).
51
52-export([files/1, files/2,
53	 application/1, application/2, application/3,
54	 toc/1, toc/2, toc/3,
55	 run/2,
56	 file/1, file/2,
57	 read/1, read/2,
58	 layout/1, layout/2,
59	 get_doc/1, get_doc/2, get_doc/3,
60	 read_comments/1, read_comments/2,
61	 read_source/1, read_source/2]).
62
63-compile({no_auto_import,[error/1]}).
64
65-include("edoc.hrl").
66
67
68%% @spec (Name::filename()) -> ok
69%% @equiv file(Name, [])
70%% @deprecated See {@link file/2} for details.
71
72file(Name) ->
73    file(Name, []).
74
75%% @spec file(filename(), proplist()) -> ok
76%%
77%% @type filename() = //kernel/file:filename()
78%% @type proplist() = [term()]
79%%
80%% @deprecated This is part of the old interface to EDoc and is mainly
81%% kept for backwards compatibility. The preferred way of generating
82%% documentation is through one of the functions {@link application/2}
83%% and {@link files/2}.
84%%
85%% @doc Reads a source code file and outputs formatted documentation to
86%% a corresponding file.
87%%
88%% Options:
89%% <dl>
90%%  <dt>{@type {dir, filename()@}}
91%%  </dt>
92%%  <dd>Specifies the output directory for the created file. (By
93%%      default, the output is written to the directory of the source
94%%      file.)
95%%  </dd>
96%%  <dt>{@type {source_suffix, string()@}}
97%%  </dt>
98%%  <dd>Specifies the expected suffix of the input file. The default
99%%      value is `".erl"'.
100%%  </dd>
101%%  <dt>{@type {file_suffix, string()@}}
102%%  </dt>
103%%  <dd>Specifies the suffix for the created file. The default value is
104%%      `".html"'.
105%%  </dd>
106%% </dl>
107%%
108%% See {@link get_doc/2} and {@link layout/2} for further
109%% options.
110%%
111%% For running EDoc from a Makefile or similar, see
112%% {@link edoc_run:file/1}.
113%%
114%% @see read/2
115
116%% NEW-OPTIONS: source_suffix, file_suffix, dir
117%% INHERIT-OPTIONS: read/2
118
119file(Name, Options) ->
120    Text = read(Name, Options),
121    SrcSuffix = proplists:get_value(source_suffix, Options,
122				    ?DEFAULT_SOURCE_SUFFIX),
123    BaseName = filename:basename(Name, SrcSuffix),
124    Suffix = proplists:get_value(file_suffix, Options,
125				 ?DEFAULT_FILE_SUFFIX),
126    Dir = proplists:get_value(dir, Options, filename:dirname(Name)),
127    Encoding = [{encoding, edoc_lib:read_encoding(Name, [])}],
128    edoc_lib:write_file(Text, Dir, BaseName ++ Suffix, Encoding).
129
130
131%% TODO: better documentation of files/1/2, application/1/2/3
132
133%% @spec (Files::[filename()]) -> ok
134
135files(Files) ->
136    files(Files, []).
137
138%% @spec (Files::[filename()],
139%%        Options::proplist()) -> ok
140%% @doc Runs EDoc on a given set of source files. See {@link run/2} for
141%% details, including options.
142%% @equiv run([], Files, Options)
143
144files(Files, Options) ->
145    run(Files, Options).
146
147%% @spec (Application::atom()) -> ok
148%% @equiv application(Application, [])
149
150application(App) ->
151    application(App, []).
152
153%% @spec (Application::atom(), Options::proplist()) -> ok
154%% @doc Run EDoc on an application in its default app-directory. See
155%% {@link application/3} for details.
156%% @see application/1
157
158application(App, Options) when is_atom(App) ->
159    case code:lib_dir(App) of
160 	Dir when is_list(Dir) ->
161 	    application(App, Dir, Options);
162 	_ ->
163	    edoc_report:report("cannot find application directory for '~s'.",
164                               [App]),
165 	    exit(error)
166    end.
167
168%% @spec (Application::atom(), Dir::filename(), Options::proplist())
169%%        -> ok
170%% @doc Run EDoc on an application located in the specified directory.
171%% Tries to automatically set up good defaults. Unless the user
172%% specifies otherwise:
173%% <ul>
174%%   <li>The `doc' subdirectory will be used as the target directory, if
175%%   it exists; otherwise the application directory is used.
176%%   </li>
177%%   <li>The source code is assumed to be located in the `src'
178%%   subdirectory, if it exists, or otherwise in the application
179%%   directory itself.
180%%   </li>
181%%   <li>The {@link run/2. `subpackages'} option is turned on. All found
182%%   source files will be processed.
183%%   </li>
184%%   <li>The `include' subdirectory is automatically added to the
185%%   include path. (Only important if {@link read_source/2.
186%%   preprocessing} is turned on.)
187%%   </li>
188%% </ul>
189%%
190%% See {@link run/2} for details, including options.
191%%
192%% @see application/2
193
194application(App, Dir, Options) when is_atom(App) ->
195    Src = edoc_lib:try_subdir(Dir, ?SOURCE_DIR),
196    Overview = filename:join(edoc_lib:try_subdir(Dir, ?EDOC_DIR),
197			     ?OVERVIEW_FILE),
198    Opts = Options ++ [{source_path, [Src]},
199		       subpackages,
200		       {title, io_lib:fwrite("The ~ts application", [App])},
201		       {overview, Overview},
202		       {dir, filename:join(Dir, ?EDOC_DIR)},
203		       {includes, [filename:join(Dir, "include")]}],
204    Opts1 = set_app_default(App, Dir, Opts),
205    %% Recursively document all subpackages of '' - i.e., everything.
206    run([], [{application, App} | Opts1]).
207
208%% Try to set up a default application base URI in a smart way if the
209%% user has not specified it explicitly.
210
211set_app_default(App, Dir0, Opts) ->
212    case proplists:get_value(app_default, Opts) of
213	undefined ->
214	    AppName = atom_to_list(App),
215	    Dir = edoc_lib:simplify_path(filename:absname(Dir0)),
216	    AppDir = case filename:basename(Dir) of
217			 AppName ->
218			     filename:dirname(Dir);
219			 _ ->
220			     ?APP_DEFAULT
221		     end,
222	    [{app_default, AppDir} | Opts];
223	_ ->
224	    Opts
225    end.
226
227opt_defaults() ->
228    [].
229
230opt_negations() ->
231    [{no_preprocess, preprocess},
232     {no_subpackages, subpackages},
233     {no_report_missing_types, report_missing_types}].
234
235%% @spec run(Files::[filename()],
236%%           Options::proplist()) -> ok
237%% @doc Runs EDoc on a given set of source files. Note
238%% that the doclet plugin module has its own particular options; see the
239%% `doclet' option below.
240%%
241%% Also see {@link layout/2} for layout-related options, and
242%% {@link get_doc/2} for options related to reading source
243%% files.
244%%
245%% Options:
246%% <dl>
247%%  <dt>{@type {app_default, string()@}}
248%%  </dt>
249%%  <dd>Specifies the default base URI for unknown applications.
250%%  </dd>
251%%  <dt>{@type {application, App::atom()@}}
252%%  </dt>
253%%  <dd>Specifies that the generated documentation describes the
254%%      application `App'. This mainly affects generated references.
255%%  </dd>
256%%  <dt>{@type {dir, filename()@}}
257%%  </dt>
258%%  <dd>Specifies the target directory for the generated documentation.
259%%  </dd>
260%%  <dt>{@type {doc_path, [string()]@}}
261%%  </dt>
262%%  <dd>Specifies a list of URI:s pointing to directories that contain
263%%      EDoc-generated documentation. URI without a `scheme://' part are
264%%      taken as relative to `file://'. (Note that such paths must use
265%%      `/' as separator, regardless of the host operating system.)
266%%  </dd>
267%%  <dt>{@type {doclet, Module::atom()@}}
268%%  </dt>
269%%  <dd>Specifies a callback module to be used for creating the
270%%      documentation. The module must export a function `run(Cmd, Ctxt)'.
271%%      The default doclet module is {@link edoc_doclet}; see {@link
272%%      edoc_doclet:run/2} for doclet-specific options.
273%%  </dd>
274%%  <dt>{@type {file_suffix, string()@}}
275%%  </dt>
276%%  <dd>Specifies the suffix used for output files. The default value is
277%%      `".html"'. Note that this also affects generated references.
278%%  </dd>
279%%  <dt>{@type {new, boolean()@}}
280%%  </dt>
281%%  <dd>If the value is `true', any existing `edoc-info' file in the
282%%      target directory will be ignored and overwritten. The default
283%%      value is `false'.
284%%  </dd>
285%%  <dt>{@type {source_path, [filename()]@}}
286%%  </dt>
287%%  <dd>Specifies a list of file system paths used to locate the source
288%%      code for packages.
289%%  </dd>
290%%  <dt>{@type {source_suffix, string()@}}
291%%  </dt>
292%%  <dd>Specifies the expected suffix of input files. The default
293%%      value is `".erl"'.
294%%  </dd>
295%%  <dt>{@type {subpackages, boolean()@}}
296%%  </dt>
297%%  <dd>If the value is `true', all subpackages of specified packages
298%%      will also be included in the documentation. The default value is
299%%      `false'. `no_subpackages' is an alias for `{subpackages,
300%%      false}'.
301%%
302%%      Subpackage source files are found by recursively searching
303%%      for source code files in subdirectories of the known source code
304%%      root directories. (Also see the `source_path' option.) Directory
305%%      names must begin with a lowercase letter and contain only
306%%      alphanumeric characters and underscore, or they will be ignored.
307%%      (For example, a subdirectory named `test-files' will not be
308%%      searched.)
309%%  </dd>
310%% </dl>
311%%
312%% @see files/2
313%% @see application/2
314
315%% NEW-OPTIONS: source_path, application
316%% INHERIT-OPTIONS: init_context/1
317%% INHERIT-OPTIONS: expand_sources/2
318%% INHERIT-OPTIONS: target_dir_info/5
319%% INHERIT-OPTIONS: edoc_lib:find_sources/2
320%% INHERIT-OPTIONS: edoc_lib:run_doclet/2
321%% INHERIT-OPTIONS: edoc_lib:get_doc_env/3
322
323run(Files, Opts0) ->
324    Opts = expand_opts(Opts0),
325    Ctxt = init_context(Opts),
326    Dir = Ctxt#context.dir,
327    Path = proplists:append_values(source_path, Opts),
328    Ss = sources(Path, Opts),
329    {Ss1, Ms} = expand_sources(expand_files(Files) ++ Ss, Opts),
330    App = proplists:get_value(application, Opts, ?NO_APP),
331    {App1, Ms1} = target_dir_info(Dir, App, Ms, Opts),
332    Ms2 = edoc_lib:unique(lists:sort(Ms1)),
333    Env = edoc_lib:get_doc_env(App1, Ms2, Opts),
334    Ctxt1 = Ctxt#context{env = Env},
335    Cmd = #doclet_gen{sources = Ss1,
336		      app = App1,
337		      modules = Ms2
338		     },
339    F = fun (M) ->
340		M:run(Cmd, Ctxt1)
341	end,
342    edoc_lib:run_doclet(F, Opts).
343
344expand_opts(Opts0) ->
345    proplists:substitute_negations(opt_negations(),
346				   Opts0 ++ opt_defaults()).
347
348%% NEW-OPTIONS: dir
349%% DEFER-OPTIONS: run/2
350
351init_context(Opts) ->
352    #context{dir = proplists:get_value(dir, Opts, ?CURRENT_DIR),
353	     opts = Opts
354	    }.
355
356%% INHERIT-OPTIONS: edoc_lib:find_sources/2
357
358sources(Path, Opts) ->
359	edoc_lib:find_sources(Path, Opts).
360
361%% Expand user-specified sets of files.
362
363expand_files([F | Fs]) ->
364    [{filename:basename(F), filename:dirname(F)} |
365     expand_files(Fs)];
366expand_files([]) ->
367    [].
368
369%% Create the (assumed) full module names. Keep only the first source
370%% for each module, but preserve the order of the list.
371
372%% NEW-OPTIONS: source_suffix
373%% DEFER-OPTIONS: run/2
374
375expand_sources(Ss, Opts) ->
376    Suffix = proplists:get_value(source_suffix, Opts,
377				 ?DEFAULT_SOURCE_SUFFIX),
378    Ss1 = [{F,D} || {F,D} <- Ss],
379    expand_sources(Ss1, Suffix, sets:new(), [], []).
380
381expand_sources([{F, D} | Fs], Suffix, S, As, Ms) ->
382    M = list_to_atom(filename:rootname(F, Suffix)),
383    case sets:is_element(M, S) of
384	true ->
385	    expand_sources(Fs, Suffix, S, As, Ms);
386	false ->
387	    S1 = sets:add_element(M, S),
388	    expand_sources(Fs, Suffix, S1, [{M, F, D} | As],
389			   [M | Ms])
390    end;
391expand_sources([], _Suffix, _S, As, Ms) ->
392    {lists:reverse(As), lists:reverse(Ms)}.
393
394%% NEW-OPTIONS: new
395
396target_dir_info(Dir, App, Ms, Opts) ->
397    case proplists:get_bool(new, Opts) of
398	true ->
399	    {App, Ms};
400	false ->
401	    {App1, Ms1} = edoc_lib:read_info_file(Dir),
402	    {if App == ?NO_APP -> App1;
403		true -> App
404	     end,
405	     Ms ++ Ms1}
406    end.
407
408
409%% @hidden   Not official yet
410
411toc(Dir) ->
412    toc(Dir, []).
413
414%% @equiv toc(Dir, Paths, [])
415%% @hidden   Not official yet
416
417%% NEW-OPTIONS: doc_path
418
419toc(Dir, Opts) ->
420    Paths = proplists:append_values(doc_path, Opts)
421	++ edoc_lib:find_doc_dirs(),
422    toc(Dir, Paths, Opts).
423
424%% @doc Create a meta-level table of contents.
425%% @hidden   Not official yet
426
427%% INHERIT-OPTIONS: init_context/1
428%% INHERIT-OPTIONS: edoc_lib:run_doclet/2
429%% INHERIT-OPTIONS: edoc_lib:get_doc_env/3
430
431toc(Dir, Paths, Opts0) ->
432    Opts = expand_opts(Opts0 ++ [{dir, Dir}]),
433    Ctxt = init_context(Opts),
434    Env = edoc_lib:get_doc_env('', [], Opts),
435    Ctxt1 = Ctxt#context{env = Env},
436    F = fun (M) ->
437		M:run(#doclet_toc{paths=Paths}, Ctxt1)
438	end,
439    edoc_lib:run_doclet(F, Opts).
440
441
442%% @spec read(File::filename()) -> string()
443%% @equiv read(File, [])
444
445read(File) ->
446    read(File, []).
447
448%% @spec read(File::filename(), Options::proplist()) -> string()
449%%
450%% @doc Reads and processes a source file and returns the resulting
451%% EDoc-text as a string. See {@link get_doc/2} and {@link layout/2} for
452%% options.
453%%
454%% @see file/2
455
456%% INHERIT-OPTIONS: get_doc/2, layout/2
457
458read(File, Opts) ->
459    {_ModuleName, Doc} = get_doc(File, Opts),
460    layout(Doc, Opts).
461
462
463%% @spec layout(Doc::edoc_module()) -> string()
464%% @equiv layout(Doc, [])
465
466layout(Doc) ->
467    layout(Doc, []).
468
469%% @spec layout(Doc::edoc_module(), Options::proplist()) -> string()
470%%
471%% @doc Transforms EDoc module documentation data to text. The default
472%% layout creates an HTML document.
473%%
474%% Options:
475%% <dl>
476%%  <dt>{@type {layout, Module::atom()@}}
477%%  </dt>
478%%  <dd>Specifies a callback module to be used for formatting. The
479%%      module must export a function `module(Doc, Options)'. The
480%%      default callback module is {@link edoc_layout}; see {@link
481%%      edoc_layout:module/2} for layout-specific options.
482%%  </dd>
483%% </dl>
484%%
485%% @see layout/1
486%% @see run/2
487%% @see read/2
488%% @see file/2
489
490%% INHERIT-OPTIONS: edoc_lib:run_layout/2
491
492layout(Doc, Opts) ->
493    F = fun (M) ->
494		M:module(Doc, Opts)
495	end,
496    edoc_lib:run_layout(F, Opts).
497
498
499%% @spec (File) ->  [comment()]
500%% @type comment() = {Line, Column, Indentation, Text}
501%% where
502%%   Line = integer(),
503%%   Column = integer(),
504%%   Indentation = integer(),
505%%   Text = [string()]
506%% @equiv read_comments(File, [])
507
508read_comments(File) ->
509    read_comments(File, []).
510
511%% @spec read_comments(File::filename(), Options::proplist()) ->
512%%           [comment()]
513%%
514%% @doc Extracts comments from an Erlang source code file. See the
515%% module {@link //syntax_tools/erl_comment_scan} for details on the
516%% representation of comments. Currently, no options are avaliable.
517
518read_comments(File, _Opts) ->
519    erl_comment_scan:file(File).
520
521
522%% @spec (File) -> [syntaxTree()]
523%% @equiv read_source(File, [])
524
525read_source(Name) ->
526    read_source(Name, []).
527
528%% @spec read_source(File::filename(), Options::proplist()) ->
529%%           [syntaxTree()]
530%%
531%% @type syntaxTree() = //syntax_tools/erl_syntax:syntaxTree()
532%%
533%% @doc Reads an Erlang source file and returns the list of "source code
534%% form" syntax trees.
535%%
536%% Options:
537%% <dl>
538%%  <dt>{@type {preprocess, boolean()@}}
539%%  </dt>
540%%  <dd>If the value is `true', the source file will be read via the
541%%      Erlang preprocessor (`epp'). The default value is `false'.
542%%      `no_preprocess' is an alias for `{preprocess, false}'.
543%%
544%%      Normally, preprocessing is not necessary for EDoc to work, but
545%%      if a file contains too exotic definitions or uses of macros, it
546%%      will not be possible to read it without preprocessing. <em>Note:
547%%      comments in included files will not be available to EDoc, even
548%%      with this option enabled.</em>
549%%  </dd>
550%%  <dt>{@type {includes, Path::[string()]@}}
551%%  </dt>
552%%  <dd>Specifies a list of directory names to be searched for include
553%%      files, if the `preprocess' option is turned on. Also used with
554%%      the `@headerfile' tag. The default value is the empty list. The
555%%      directory of the source file is always automatically appended to
556%%      the search path.
557%%  </dd>
558%%  <dt>{@type {macros, [{atom(), term()@}]@}}
559%%  </dt>
560%%  <dd>Specifies a list of pre-defined Erlang preprocessor (`epp')
561%%      macro definitions, used if the `preprocess' option is turned on.
562%%      The default value is the empty list.</dd>
563%%  <dt>{@type {report_missing_types, boolean()@}}
564%%  </dt>
565%%  <dd>If the value is `true', warnings are issued for missing types.
566%%      The default value is `false'.
567%%      `no_report_missing_types' is an alias for
568%%      `{report_missing_types, false}'.
569%%  </dd>
570%% </dl>
571%%
572%% @see get_doc/2
573%% @see //syntax_tools/erl_syntax
574
575%% NEW-OPTIONS: [no_]preprocess (preprocess -> includes, macros)
576
577read_source(Name, Opts0) ->
578    Opts = expand_opts(Opts0),
579    case read_source_1(Name, Opts) of
580	{ok, Forms} ->
581	    check_forms(Forms, Name, Opts),
582	    Forms;
583	{error, R} ->
584	    edoc_report:error({"error reading file '~ts'.",
585                               [edoc_lib:filename(Name)]}),
586	    exit({error, R})
587    end.
588
589read_source_1(Name, Opts) ->
590    case proplists:get_bool(preprocess, Opts) of
591	true ->
592	    read_source_2(Name, Opts);
593	false ->
594	    epp_dodger:quick_parse_file(Name, Opts ++ [{no_fail, false}])
595    end.
596
597read_source_2(Name, Opts) ->
598    Includes = proplists:append_values(includes, Opts)
599	++ [filename:dirname(Name)],
600    Macros = proplists:append_values(macros, Opts),
601    %% epp:parse_file(Name, Includes, Macros).
602    parse_file(Name, Includes, Macros).
603
604%% The code below has been copied from epp.erl.
605%%
606%% Copy the line of the last token to the last token that will be
607%% part of the parse tree.
608%%
609%% The last line is used in edoc_extract:find_type_docs() to determine
610%% if a type declaration is followed by a comment.
611%% <example>
612%%    -type t() :: [
613%%                    {tag, integer()}
614%%                 ].
615%%   %% Protocol options.
616%% </example>
617%% The line of the dot token will be copied to the integer token.
618
619parse_file(Name, Includes, Macros) ->
620    case parse_file(utf8, Name, Includes, Macros) of
621        invalid_unicode ->
622            parse_file(latin1, Name, Includes, Macros);
623        Ret ->
624            Ret
625    end.
626
627parse_file(DefEncoding, Name, Includes, Macros) ->
628    Options = [{name, Name},
629               {includes, Includes},
630               {macros, Macros},
631               {default_encoding, DefEncoding}],
632    case epp:open([extra | Options]) of
633        {ok, Epp, Extra} ->
634            try parse_file(Epp) of
635                Forms ->
636                    Encoding = proplists:get_value(encoding, Extra),
637                    case find_invalid_unicode(Forms) of
638                        invalid_unicode when Encoding =/= utf8 ->
639                            invalid_unicode;
640                        _ ->
641                            {ok, Forms}
642                    end
643            after _ = epp:close(Epp)
644            end;
645        Error ->
646            Error
647    end.
648
649find_invalid_unicode([H|T]) ->
650    case H of
651	{error,{_Line,file_io_server,invalid_unicode}} ->
652	    invalid_unicode;
653	_Other ->
654	    find_invalid_unicode(T)
655    end;
656find_invalid_unicode([]) -> none.
657
658parse_file(Epp) ->
659    case scan_and_parse(Epp) of
660	{ok, Form} ->
661            [Form | parse_file(Epp)];
662	{error, E} ->
663	    [{error, E} | parse_file(Epp)];
664	{eof, Location} ->
665	    [{eof, Location}]
666    end.
667
668scan_and_parse(Epp) ->
669    case epp:scan_erl_form(Epp) of
670        {ok, Toks0} ->
671            Toks = fix_last_line(Toks0),
672            case erl_parse:parse_form(Toks) of
673                {ok, Form} ->
674                    {ok, Form};
675                Else ->
676                    Else
677            end;
678        Else ->
679            Else
680    end.
681
682fix_last_line(Toks0) ->
683    Toks1 = lists:reverse(Toks0),
684    LastLine = erl_scan:line(hd(Toks1)),
685    fll(Toks1, LastLine, []).
686
687fll([{Category, Anno0, Symbol} | L], LastLine, Ts) ->
688    Anno = erl_anno:set_line(LastLine, Anno0),
689    lists:reverse(L, [{Category, Anno, Symbol} | Ts]);
690fll([T | L], LastLine, Ts) ->
691    fll(L, LastLine, [T | Ts]);
692fll(L, _LastLine, Ts) ->
693    lists:reverse(L, Ts).
694
695check_forms(Fs, Name, Opts) ->
696    Fun = fun (F) ->
697	     case erl_syntax:type(F) of
698		 error_marker ->
699		     case erl_syntax:error_marker_info(F) of
700			 {L, M, D} ->
701                             edoc_report:error(L, Name, {format_error, M, D}),
702                             case proplists:get_bool(preprocess, Opts) of
703                                 true ->
704                                     ok;
705                                 false ->
706                                     helpful_message(Name)
707                             end;
708			 Other ->
709			     edoc_report:report(Name, "unknown error in "
710                                                "source code: ~w.", [Other])
711		     end,
712		     exit(error);
713		 _ ->
714		     ok
715	     end
716	  end,
717    lists:foreach(Fun, Fs).
718
719helpful_message(Name) ->
720    Ms = ["If the error is caused by too exotic macro",
721          "definitions or uses of macros, adding option",
722          "{preprocess, true} can help. See also edoc(3)."],
723    lists:foreach(fun(M) -> edoc_report:report(Name, M, []) end, Ms).
724
725%% @spec get_doc(File::filename()) -> {ModuleName, edoc_module()}
726%% @equiv get_doc(File, [])
727
728get_doc(File) ->
729    get_doc(File, []).
730
731%% @spec get_doc(File::filename(), Options::proplist()) ->
732%%           {ModuleName, edoc_module()}
733%%	ModuleName = atom()
734%%
735%% @type edoc_module(). The EDoc documentation data for a module,
736%% expressed as an XML document in {@link //xmerl. XMerL} format. See
737%% the file <a href="edoc.dtd">`edoc.dtd'</a> for details.
738%%
739%% @doc Reads a source code file and extracts EDoc documentation data.
740%% Note that without an environment parameter (see {@link get_doc/3}),
741%% hypertext links may not be correct.
742%%
743%% Options:
744%% <dl>
745%%  <dt>{@type {def, Macros@}}
746%%  </dt>
747%%  <dd><ul>
748%%       <li>`Macros' = {@type Macro | [Macro]}</li>
749%%       <li>`Macro' = {@type {Name::atom(), Text::string()@}}</li>
750%%      </ul>
751%%    Specifies a set of EDoc macro definitions. See
752%%    <a href="overview-summary.html#Macro_expansion">Inline macro expansion</a>
753%%    for details.
754%%  </dd>
755%%  <dt>{@type {hidden, boolean()@}}
756%%  </dt>
757%%  <dd>If the value is `true', documentation of hidden functions will
758%%      also be included. The default value is `false'.
759%%  </dd>
760%%  <dt>{@type {private, boolean()@}}
761%%  </dt>
762%%  <dd>If the value is `true', documentation of private functions will
763%%      also be included. The default value is `false'.
764%%  </dd>
765%%  <dt>{@type {todo, boolean()@}}
766%%  </dt>
767%%  <dd>If the value is `true', To-Do notes written using `@todo' or
768%%  `@TODO' tags will be included in the documentation. The default
769%%  value is `false'.
770%%  </dd>
771%% </dl>
772%%
773%% See {@link read_source/2}, {@link read_comments/2} and {@link
774%% edoc_lib:get_doc_env/3} for further options.
775%%
776%% @see get_doc/3
777%% @see run/2
778%% @see edoc_extract:source/5
779%% @see read/2
780%% @see layout/2
781
782%% INHERIT-OPTIONS: get_doc/3
783%% INHERIT-OPTIONS: edoc_lib:get_doc_env/3
784
785get_doc(File, Opts) ->
786    Env = edoc_lib:get_doc_env(Opts),
787    get_doc(File, Env, Opts).
788
789%% @spec get_doc(File::filename(), Env::edoc_lib:edoc_env(),
790%%        Options::proplist()) -> {ModuleName, edoc_module()}
791%%     ModuleName = atom()
792%%
793%% @doc Like {@link get_doc/2}, but for a given environment
794%% parameter. `Env' is an environment created by {@link
795%% edoc_lib:get_doc_env/3}.
796
797%% INHERIT-OPTIONS: read_source/2, read_comments/2, edoc_extract:source/5
798%% DEFER-OPTIONS: get_doc/2
799
800get_doc(File, Env, Opts) ->
801    edoc_extract:source(File, Env, Opts).
802